001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.context.support; 018 019import java.io.Serializable; 020 021import org.springframework.context.MessageSourceResolvable; 022import org.springframework.lang.Nullable; 023import org.springframework.util.ObjectUtils; 024import org.springframework.util.StringUtils; 025 026/** 027 * Spring's default implementation of the {@link MessageSourceResolvable} interface. 028 * Offers an easy way to store all the necessary values needed to resolve 029 * a message via a {@link org.springframework.context.MessageSource}. 030 * 031 * @author Juergen Hoeller 032 * @since 13.02.2004 033 * @see org.springframework.context.MessageSource#getMessage(MessageSourceResolvable, java.util.Locale) 034 */ 035@SuppressWarnings("serial") 036public class DefaultMessageSourceResolvable implements MessageSourceResolvable, Serializable { 037 038 @Nullable 039 private final String[] codes; 040 041 @Nullable 042 private final Object[] arguments; 043 044 @Nullable 045 private final String defaultMessage; 046 047 048 /** 049 * Create a new DefaultMessageSourceResolvable. 050 * @param code the code to be used to resolve this message 051 */ 052 public DefaultMessageSourceResolvable(String code) { 053 this(new String[] {code}, null, null); 054 } 055 056 /** 057 * Create a new DefaultMessageSourceResolvable. 058 * @param codes the codes to be used to resolve this message 059 */ 060 public DefaultMessageSourceResolvable(String[] codes) { 061 this(codes, null, null); 062 } 063 064 /** 065 * Create a new DefaultMessageSourceResolvable. 066 * @param codes the codes to be used to resolve this message 067 * @param defaultMessage the default message to be used to resolve this message 068 */ 069 public DefaultMessageSourceResolvable(String[] codes, String defaultMessage) { 070 this(codes, null, defaultMessage); 071 } 072 073 /** 074 * Create a new DefaultMessageSourceResolvable. 075 * @param codes the codes to be used to resolve this message 076 * @param arguments the array of arguments to be used to resolve this message 077 */ 078 public DefaultMessageSourceResolvable(String[] codes, Object[] arguments) { 079 this(codes, arguments, null); 080 } 081 082 /** 083 * Create a new DefaultMessageSourceResolvable. 084 * @param codes the codes to be used to resolve this message 085 * @param arguments the array of arguments to be used to resolve this message 086 * @param defaultMessage the default message to be used to resolve this message 087 */ 088 public DefaultMessageSourceResolvable( 089 @Nullable String[] codes, @Nullable Object[] arguments, @Nullable String defaultMessage) { 090 091 this.codes = codes; 092 this.arguments = arguments; 093 this.defaultMessage = defaultMessage; 094 } 095 096 /** 097 * Copy constructor: Create a new instance from another resolvable. 098 * @param resolvable the resolvable to copy from 099 */ 100 public DefaultMessageSourceResolvable(MessageSourceResolvable resolvable) { 101 this(resolvable.getCodes(), resolvable.getArguments(), resolvable.getDefaultMessage()); 102 } 103 104 105 /** 106 * Return the default code of this resolvable, that is, 107 * the last one in the codes array. 108 */ 109 @Nullable 110 public String getCode() { 111 return (this.codes != null && this.codes.length > 0 ? this.codes[this.codes.length - 1] : null); 112 } 113 114 @Override 115 @Nullable 116 public String[] getCodes() { 117 return this.codes; 118 } 119 120 @Override 121 @Nullable 122 public Object[] getArguments() { 123 return this.arguments; 124 } 125 126 @Override 127 @Nullable 128 public String getDefaultMessage() { 129 return this.defaultMessage; 130 } 131 132 /** 133 * Indicate whether the specified default message needs to be rendered for 134 * substituting placeholders and/or {@link java.text.MessageFormat} escaping. 135 * @return {@code true} if the default message may contain argument placeholders; 136 * {@code false} if it definitely does not contain placeholders or custom escaping 137 * and can therefore be simply exposed as-is 138 * @since 5.1.7 139 * @see #getDefaultMessage() 140 * @see #getArguments() 141 * @see AbstractMessageSource#renderDefaultMessage 142 */ 143 public boolean shouldRenderDefaultMessage() { 144 return true; 145 } 146 147 148 /** 149 * Build a default String representation for this MessageSourceResolvable: 150 * including codes, arguments, and default message. 151 */ 152 protected final String resolvableToString() { 153 StringBuilder result = new StringBuilder(64); 154 result.append("codes [").append(StringUtils.arrayToDelimitedString(this.codes, ",")); 155 result.append("]; arguments [").append(StringUtils.arrayToDelimitedString(this.arguments, ",")); 156 result.append("]; default message [").append(this.defaultMessage).append(']'); 157 return result.toString(); 158 } 159 160 /** 161 * The default implementation exposes the attributes of this MessageSourceResolvable. 162 * <p>To be overridden in more specific subclasses, potentially including the 163 * resolvable content through {@code resolvableToString()}. 164 * @see #resolvableToString() 165 */ 166 @Override 167 public String toString() { 168 return getClass().getName() + ": " + resolvableToString(); 169 } 170 171 172 @Override 173 public boolean equals(@Nullable Object other) { 174 if (this == other) { 175 return true; 176 } 177 if (!(other instanceof MessageSourceResolvable)) { 178 return false; 179 } 180 MessageSourceResolvable otherResolvable = (MessageSourceResolvable) other; 181 return (ObjectUtils.nullSafeEquals(getCodes(), otherResolvable.getCodes()) && 182 ObjectUtils.nullSafeEquals(getArguments(), otherResolvable.getArguments()) && 183 ObjectUtils.nullSafeEquals(getDefaultMessage(), otherResolvable.getDefaultMessage())); 184 } 185 186 @Override 187 public int hashCode() { 188 int hashCode = ObjectUtils.nullSafeHashCode(getCodes()); 189 hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getArguments()); 190 hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getDefaultMessage()); 191 return hashCode; 192 } 193 194}