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.util.ObjectUtils; 023import org.springframework.util.StringUtils; 024 025/** 026 * Spring's default implementation of the {@link MessageSourceResolvable} interface. 027 * Offers an easy way to store all the necessary values needed to resolve 028 * a message via a {@link org.springframework.context.MessageSource}. 029 * 030 * @author Juergen Hoeller 031 * @since 13.02.2004 032 * @see org.springframework.context.MessageSource#getMessage(MessageSourceResolvable, java.util.Locale) 033 */ 034@SuppressWarnings("serial") 035public class DefaultMessageSourceResolvable implements MessageSourceResolvable, Serializable { 036 037 private final String[] codes; 038 039 private final Object[] arguments; 040 041 private final String defaultMessage; 042 043 044 /** 045 * Create a new DefaultMessageSourceResolvable. 046 * @param code the code to be used to resolve this message 047 */ 048 public DefaultMessageSourceResolvable(String code) { 049 this(new String[] {code}, null, null); 050 } 051 052 /** 053 * Create a new DefaultMessageSourceResolvable. 054 * @param codes the codes to be used to resolve this message 055 */ 056 public DefaultMessageSourceResolvable(String[] codes) { 057 this(codes, null, null); 058 } 059 060 /** 061 * Create a new DefaultMessageSourceResolvable. 062 * @param codes the codes to be used to resolve this message 063 * @param defaultMessage the default message to be used to resolve this message 064 */ 065 public DefaultMessageSourceResolvable(String[] codes, String defaultMessage) { 066 this(codes, null, defaultMessage); 067 } 068 069 /** 070 * Create a new DefaultMessageSourceResolvable. 071 * @param codes the codes to be used to resolve this message 072 * @param arguments the array of arguments to be used to resolve this message 073 */ 074 public DefaultMessageSourceResolvable(String[] codes, Object[] arguments) { 075 this(codes, arguments, null); 076 } 077 078 /** 079 * Create a new DefaultMessageSourceResolvable. 080 * @param codes the codes to be used to resolve this message 081 * @param arguments the array of arguments to be used to resolve this message 082 * @param defaultMessage the default message to be used to resolve this message 083 */ 084 public DefaultMessageSourceResolvable(String[] codes, Object[] arguments, String defaultMessage) { 085 this.codes = codes; 086 this.arguments = arguments; 087 this.defaultMessage = defaultMessage; 088 } 089 090 /** 091 * Copy constructor: Create a new instance from another resolvable. 092 * @param resolvable the resolvable to copy from 093 */ 094 public DefaultMessageSourceResolvable(MessageSourceResolvable resolvable) { 095 this(resolvable.getCodes(), resolvable.getArguments(), resolvable.getDefaultMessage()); 096 } 097 098 099 /** 100 * Return the default code of this resolvable, that is, 101 * the last one in the codes array. 102 */ 103 public String getCode() { 104 return (this.codes != null && this.codes.length > 0 ? this.codes[this.codes.length - 1] : null); 105 } 106 107 @Override 108 public String[] getCodes() { 109 return this.codes; 110 } 111 112 @Override 113 public Object[] getArguments() { 114 return this.arguments; 115 } 116 117 @Override 118 public String getDefaultMessage() { 119 return this.defaultMessage; 120 } 121 122 123 /** 124 * Build a default String representation for this MessageSourceResolvable: 125 * including codes, arguments, and default message. 126 */ 127 protected final String resolvableToString() { 128 StringBuilder result = new StringBuilder(64); 129 result.append("codes [").append(StringUtils.arrayToDelimitedString(this.codes, ",")); 130 result.append("]; arguments [").append(StringUtils.arrayToDelimitedString(this.arguments, ",")); 131 result.append("]; default message [").append(this.defaultMessage).append(']'); 132 return result.toString(); 133 } 134 135 /** 136 * The default implementation exposes the attributes of this MessageSourceResolvable. 137 * <p>To be overridden in more specific subclasses, potentially including the 138 * resolvable content through {@code resolvableToString()}. 139 * @see #resolvableToString() 140 */ 141 @Override 142 public String toString() { 143 return getClass().getName() + ": " + resolvableToString(); 144 } 145 146 147 @Override 148 public boolean equals(Object other) { 149 if (this == other) { 150 return true; 151 } 152 if (!(other instanceof MessageSourceResolvable)) { 153 return false; 154 } 155 MessageSourceResolvable otherResolvable = (MessageSourceResolvable) other; 156 return (ObjectUtils.nullSafeEquals(getCodes(), otherResolvable.getCodes()) && 157 ObjectUtils.nullSafeEquals(getArguments(), otherResolvable.getArguments()) && 158 ObjectUtils.nullSafeEquals(getDefaultMessage(), otherResolvable.getDefaultMessage())); 159 } 160 161 @Override 162 public int hashCode() { 163 int hashCode = ObjectUtils.nullSafeHashCode(getCodes()); 164 hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getArguments()); 165 hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getDefaultMessage()); 166 return hashCode; 167 } 168 169}