001/*
002 * Copyright 2002-2018 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.expression.spel;
018
019import java.text.MessageFormat;
020
021/**
022 * Contains all the messages that can be produced by the Spring Expression Language.
023 * Each message has a kind (info, warn, error) and a code number. Tests can be written to
024 * expect particular code numbers rather than particular text, enabling the message text
025 * to more easily be modified and the tests to run successfully in different locales.
026 *
027 * <p>When a message is formatted, it will have this kind of form, capturing the prefix
028 * and the error kind:
029 *
030 * <pre class="code">EL1004E: Type cannot be found 'String'</pre>
031 *
032 * @author Andy Clement
033 * @author Juergen Hoeller
034 * @since 3.0
035 */
036public enum SpelMessage {
037
038        TYPE_CONVERSION_ERROR(Kind.ERROR, 1001,
039                        "Type conversion problem, cannot convert from {0} to {1}"),
040
041        CONSTRUCTOR_NOT_FOUND(Kind.ERROR, 1002,
042                        "Constructor call: No suitable constructor found on type {0} for arguments {1}"),
043
044        CONSTRUCTOR_INVOCATION_PROBLEM(Kind.ERROR, 1003,
045                        "A problem occurred whilst attempting to construct an object of type ''{0}'' using arguments ''{1}''"),
046
047        METHOD_NOT_FOUND(Kind.ERROR, 1004,
048                        "Method call: Method {0} cannot be found on type {1}"),
049
050        TYPE_NOT_FOUND(Kind.ERROR, 1005,
051                        "Type cannot be found ''{0}''"),
052
053        FUNCTION_NOT_DEFINED(Kind.ERROR, 1006,
054                        "Function ''{0}'' could not be found"),
055
056        PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL(Kind.ERROR, 1007,
057                        "Property or field ''{0}'' cannot be found on null"),
058
059        PROPERTY_OR_FIELD_NOT_READABLE(Kind.ERROR, 1008,
060                        "Property or field ''{0}'' cannot be found on object of type ''{1}'' - maybe not public or not valid?"),
061
062        PROPERTY_OR_FIELD_NOT_WRITABLE_ON_NULL(Kind.ERROR, 1009,
063                        "Property or field ''{0}'' cannot be set on null"),
064
065        PROPERTY_OR_FIELD_NOT_WRITABLE(Kind.ERROR, 1010,
066                        "Property or field ''{0}'' cannot be set on object of type ''{1}'' - maybe not public or not writable?"),
067
068        METHOD_CALL_ON_NULL_OBJECT_NOT_ALLOWED(Kind.ERROR, 1011,
069                        "Method call: Attempted to call method {0} on null context object"),
070
071        CANNOT_INDEX_INTO_NULL_VALUE(Kind.ERROR, 1012,
072                        "Cannot index into a null value"),
073
074        NOT_COMPARABLE(Kind.ERROR, 1013,
075                        "Cannot compare instances of {0} and {1}"),
076
077        INCORRECT_NUMBER_OF_ARGUMENTS_TO_FUNCTION(Kind.ERROR, 1014,
078                        "Incorrect number of arguments for function, {0} supplied but function takes {1}"),
079
080        INVALID_TYPE_FOR_SELECTION(Kind.ERROR, 1015,
081                        "Cannot perform selection on input data of type ''{0}''"),
082
083        RESULT_OF_SELECTION_CRITERIA_IS_NOT_BOOLEAN(Kind.ERROR, 1016,
084                        "Result of selection criteria is not boolean"),
085
086        BETWEEN_RIGHT_OPERAND_MUST_BE_TWO_ELEMENT_LIST(Kind.ERROR, 1017,
087                        "Right operand for the 'between' operator has to be a two-element list"),
088
089        INVALID_PATTERN(Kind.ERROR, 1018,
090                        "Pattern is not valid ''{0}''"),
091
092        PROJECTION_NOT_SUPPORTED_ON_TYPE(Kind.ERROR, 1019,
093                        "Projection is not supported on the type ''{0}''"),
094
095        ARGLIST_SHOULD_NOT_BE_EVALUATED(Kind.ERROR, 1020,
096                        "The argument list of a lambda expression should never have getValue() called upon it"),
097
098        EXCEPTION_DURING_PROPERTY_READ(Kind.ERROR, 1021,
099                        "A problem occurred whilst attempting to access the property ''{0}'': ''{1}''"),
100
101        FUNCTION_REFERENCE_CANNOT_BE_INVOKED(Kind.ERROR, 1022,
102                        "The function ''{0}'' mapped to an object of type ''{1}'' which cannot be invoked"),
103
104        EXCEPTION_DURING_FUNCTION_CALL(Kind.ERROR, 1023,
105                        "A problem occurred whilst attempting to invoke the function ''{0}'': ''{1}''"),
106
107        ARRAY_INDEX_OUT_OF_BOUNDS(Kind.ERROR, 1024,
108                        "The array has ''{0}'' elements, index ''{1}'' is invalid"),
109
110        COLLECTION_INDEX_OUT_OF_BOUNDS(Kind.ERROR, 1025,
111                        "The collection has ''{0}'' elements, index ''{1}'' is invalid"),
112
113        STRING_INDEX_OUT_OF_BOUNDS(Kind.ERROR, 1026,
114                        "The string has ''{0}'' characters, index ''{1}'' is invalid"),
115
116        INDEXING_NOT_SUPPORTED_FOR_TYPE(Kind.ERROR, 1027,
117                        "Indexing into type ''{0}'' is not supported"),
118
119        INSTANCEOF_OPERATOR_NEEDS_CLASS_OPERAND(Kind.ERROR, 1028,
120                        "The operator 'instanceof' needs the right operand to be a class, not a ''{0}''"),
121
122        EXCEPTION_DURING_METHOD_INVOCATION(Kind.ERROR, 1029,
123                        "A problem occurred when trying to execute method ''{0}'' on object of type ''{1}'': ''{2}''"),
124
125        OPERATOR_NOT_SUPPORTED_BETWEEN_TYPES(Kind.ERROR, 1030,
126                        "The operator ''{0}'' is not supported between objects of type ''{1}'' and ''{2}''"),
127
128        PROBLEM_LOCATING_METHOD(Kind.ERROR, 1031,
129                        "Problem locating method {0} on type {1}"),
130
131        SETVALUE_NOT_SUPPORTED( Kind.ERROR, 1032,
132                        "setValue(ExpressionState, Object) not supported for ''{0}''"),
133
134        MULTIPLE_POSSIBLE_METHODS(Kind.ERROR, 1033,
135                        "Method call of ''{0}'' is ambiguous, supported type conversions allow multiple variants to match"),
136
137        EXCEPTION_DURING_PROPERTY_WRITE(Kind.ERROR, 1034,
138                        "A problem occurred whilst attempting to set the property ''{0}'': {1}"),
139
140        NOT_AN_INTEGER(Kind.ERROR, 1035,
141                        "The value ''{0}'' cannot be parsed as an int"),
142
143        NOT_A_LONG(Kind.ERROR, 1036,
144                        "The value ''{0}'' cannot be parsed as a long"),
145
146        INVALID_FIRST_OPERAND_FOR_MATCHES_OPERATOR(Kind.ERROR, 1037,
147                        "First operand to matches operator must be a string. ''{0}'' is not"),
148
149        INVALID_SECOND_OPERAND_FOR_MATCHES_OPERATOR(Kind.ERROR, 1038,
150                        "Second operand to matches operator must be a string. ''{0}'' is not"),
151
152        FUNCTION_MUST_BE_STATIC(Kind.ERROR, 1039,
153                        "Only static methods can be called via function references. " +
154                        "The method ''{0}'' referred to by name ''{1}'' is not static."),
155
156        NOT_A_REAL(Kind.ERROR, 1040,
157                        "The value ''{0}'' cannot be parsed as a double"),
158
159        MORE_INPUT(Kind.ERROR, 1041,
160                        "After parsing a valid expression, there is still more data in the expression: ''{0}''"),
161
162        RIGHT_OPERAND_PROBLEM(Kind.ERROR, 1042,
163                        "Problem parsing right operand"),
164
165        NOT_EXPECTED_TOKEN(Kind.ERROR, 1043,
166                        "Unexpected token. Expected ''{0}'' but was ''{1}''"),
167
168        OOD(Kind.ERROR, 1044,
169                        "Unexpectedly ran out of input"),
170
171        NON_TERMINATING_DOUBLE_QUOTED_STRING(Kind.ERROR, 1045,
172                        "Cannot find terminating \" for string"),
173
174        NON_TERMINATING_QUOTED_STRING(Kind.ERROR, 1046,
175                        "Cannot find terminating '' for string"),
176
177        MISSING_LEADING_ZERO_FOR_NUMBER(Kind.ERROR, 1047,
178                        "A real number must be prefixed by zero, it cannot start with just ''.''"),
179
180        REAL_CANNOT_BE_LONG(Kind.ERROR, 1048,
181                        "Real number cannot be suffixed with a long (L or l) suffix"),
182
183        UNEXPECTED_DATA_AFTER_DOT(Kind.ERROR, 1049,
184                        "Unexpected data after ''.'': ''{0}''"),
185
186        MISSING_CONSTRUCTOR_ARGS(Kind.ERROR, 1050,
187                        "The arguments '(...)' for the constructor call are missing"),
188
189        RUN_OUT_OF_ARGUMENTS(Kind.ERROR, 1051,
190                        "Unexpectedly ran out of arguments"),
191
192        UNABLE_TO_GROW_COLLECTION(Kind.ERROR, 1052,
193                        "Unable to grow collection"),
194
195        UNABLE_TO_GROW_COLLECTION_UNKNOWN_ELEMENT_TYPE(Kind.ERROR, 1053,
196                        "Unable to grow collection: unable to determine list element type"),
197
198        UNABLE_TO_CREATE_LIST_FOR_INDEXING(Kind.ERROR, 1054,
199                        "Unable to dynamically create a List to replace a null value"),
200
201        UNABLE_TO_CREATE_MAP_FOR_INDEXING(Kind.ERROR, 1055,
202                        "Unable to dynamically create a Map to replace a null value"),
203
204        UNABLE_TO_DYNAMICALLY_CREATE_OBJECT(Kind.ERROR, 1056,
205                        "Unable to dynamically create instance of ''{0}'' to replace a null value"),
206
207        NO_BEAN_RESOLVER_REGISTERED(Kind.ERROR, 1057,
208                        "No bean resolver registered in the context to resolve access to bean ''{0}''"),
209
210        EXCEPTION_DURING_BEAN_RESOLUTION(Kind.ERROR, 1058,
211                        "A problem occurred when trying to resolve bean ''{0}'':''{1}''"),
212
213        INVALID_BEAN_REFERENCE(Kind.ERROR, 1059,
214                        "@ or & can only be followed by an identifier or a quoted name"),
215
216        TYPE_NAME_EXPECTED_FOR_ARRAY_CONSTRUCTION(Kind.ERROR, 1060,
217                        "Expected the type of the new array to be specified as a String but found ''{0}''"),
218
219        INCORRECT_ELEMENT_TYPE_FOR_ARRAY(Kind.ERROR, 1061,
220                        "The array of type ''{0}'' cannot have an element of type ''{1}'' inserted"),
221
222        MULTIDIM_ARRAY_INITIALIZER_NOT_SUPPORTED(Kind.ERROR, 1062,
223                        "Using an initializer to build a multi-dimensional array is not currently supported"),
224
225        MISSING_ARRAY_DIMENSION(Kind.ERROR, 1063,
226                        "A required array dimension has not been specified"),
227
228        INITIALIZER_LENGTH_INCORRECT(Kind.ERROR, 1064,
229                        "Array initializer size does not match array dimensions"),
230
231        UNEXPECTED_ESCAPE_CHAR(Kind.ERROR, 1065,
232                        "Unexpected escape character"),
233
234        OPERAND_NOT_INCREMENTABLE(Kind.ERROR, 1066,
235                        "The expression component ''{0}'' does not support increment"),
236
237        OPERAND_NOT_DECREMENTABLE(Kind.ERROR, 1067,
238                        "The expression component ''{0}'' does not support decrement"),
239
240        NOT_ASSIGNABLE(Kind.ERROR, 1068,
241                        "The expression component ''{0}'' is not assignable"),
242
243        MISSING_CHARACTER(Kind.ERROR, 1069,
244                        "Missing expected character ''{0}''"),
245
246        LEFT_OPERAND_PROBLEM(Kind.ERROR, 1070,
247                        "Problem parsing left operand"),
248
249        MISSING_SELECTION_EXPRESSION(Kind.ERROR, 1071,
250                        "A required selection expression has not been specified"),
251
252        /** @since 4.1 */
253        EXCEPTION_RUNNING_COMPILED_EXPRESSION(Kind.ERROR, 1072,
254                        "An exception occurred whilst evaluating a compiled expression"),
255
256        /** @since 4.3.17 */
257        FLAWED_PATTERN(Kind.ERROR, 1073,
258                        "Failed to efficiently evaluate pattern ''{0}'': consider redesigning it");
259
260
261        private final Kind kind;
262
263        private final int code;
264
265        private final String message;
266
267
268        SpelMessage(Kind kind, int code, String message) {
269                this.kind = kind;
270                this.code = code;
271                this.message = message;
272        }
273
274
275        /**
276         * Produce a complete message including the prefix and with the inserts
277         * applied to the message.
278         * @param inserts the inserts to put into the formatted message
279         * @return a formatted message
280         * @since 4.3.5
281         */
282        public String formatMessage(Object... inserts) {
283                StringBuilder formattedMessage = new StringBuilder();
284                formattedMessage.append("EL").append(this.code);
285                switch (this.kind) {
286                        case ERROR:
287                                formattedMessage.append("E");
288                                break;
289                }
290                formattedMessage.append(": ");
291                formattedMessage.append(MessageFormat.format(this.message, inserts));
292                return formattedMessage.toString();
293        }
294
295        /**
296         * Produce a complete message including the prefix, the position (if known)
297         * and with the inserts applied to the message.
298         * @param pos the position (ignored and not included in the message if less than 0)
299         * @param inserts the inserts to put into the formatted message
300         * @return a formatted message
301         * @deprecated as of Spring 4.3.5, in favor of {@link #formatMessage(Object...)}
302         */
303        @Deprecated
304        public String formatMessage(int pos, Object... inserts) {
305                StringBuilder formattedMessage = new StringBuilder();
306                formattedMessage.append("EL").append(this.code);
307                switch (this.kind) {
308                        case ERROR:
309                                formattedMessage.append("E");
310                                break;
311                }
312                formattedMessage.append(":");
313                if (pos >= 0) {
314                        formattedMessage.append("(pos ").append(pos).append("): ");
315                }
316                formattedMessage.append(MessageFormat.format(this.message, inserts));
317                return formattedMessage.toString();
318        }
319
320
321        public enum Kind { INFO, WARNING, ERROR }
322
323}