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}