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.common;
018
019import org.springframework.core.convert.TypeDescriptor;
020import org.springframework.expression.EvaluationContext;
021import org.springframework.expression.EvaluationException;
022import org.springframework.expression.Expression;
023import org.springframework.expression.TypedValue;
024import org.springframework.lang.Nullable;
025
026/**
027 * Represents a template expression broken into pieces. Each piece will be an Expression
028 * but pure text parts to the template will be represented as LiteralExpression objects.
029 * An example of a template expression might be:
030 *
031 * <pre class="code">
032 * &quot;Hello ${getName()}&quot;
033 * </pre>
034 *
035 * which will be represented as a CompositeStringExpression of two parts. The first part
036 * being a LiteralExpression representing 'Hello ' and the second part being a real
037 * expression that will call {@code getName()} when invoked.
038 *
039 * @author Andy Clement
040 * @author Juergen Hoeller
041 * @since 3.0
042 */
043public class CompositeStringExpression implements Expression {
044
045        private final String expressionString;
046
047        /** The array of expressions that make up the composite expression. */
048        private final Expression[] expressions;
049
050
051        public CompositeStringExpression(String expressionString, Expression[] expressions) {
052                this.expressionString = expressionString;
053                this.expressions = expressions;
054        }
055
056
057        @Override
058        public final String getExpressionString() {
059                return this.expressionString;
060        }
061
062        public final Expression[] getExpressions() {
063                return this.expressions;
064        }
065
066        @Override
067        public String getValue() throws EvaluationException {
068                StringBuilder sb = new StringBuilder();
069                for (Expression expression : this.expressions) {
070                        String value = expression.getValue(String.class);
071                        if (value != null) {
072                                sb.append(value);
073                        }
074                }
075                return sb.toString();
076        }
077
078        @Override
079        @Nullable
080        public <T> T getValue(@Nullable Class<T> expectedResultType) throws EvaluationException {
081                Object value = getValue();
082                return ExpressionUtils.convertTypedValue(null, new TypedValue(value), expectedResultType);
083        }
084
085        @Override
086        public String getValue(@Nullable Object rootObject) throws EvaluationException {
087                StringBuilder sb = new StringBuilder();
088                for (Expression expression : this.expressions) {
089                        String value = expression.getValue(rootObject, String.class);
090                        if (value != null) {
091                                sb.append(value);
092                        }
093                }
094                return sb.toString();
095        }
096
097        @Override
098        @Nullable
099        public <T> T getValue(@Nullable Object rootObject, @Nullable Class<T> desiredResultType) throws EvaluationException {
100                Object value = getValue(rootObject);
101                return ExpressionUtils.convertTypedValue(null, new TypedValue(value), desiredResultType);
102        }
103
104        @Override
105        public String getValue(EvaluationContext context) throws EvaluationException {
106                StringBuilder sb = new StringBuilder();
107                for (Expression expression : this.expressions) {
108                        String value = expression.getValue(context, String.class);
109                        if (value != null) {
110                                sb.append(value);
111                        }
112                }
113                return sb.toString();
114        }
115
116        @Override
117        @Nullable
118        public <T> T getValue(EvaluationContext context, @Nullable Class<T> expectedResultType)
119                        throws EvaluationException {
120
121                Object value = getValue(context);
122                return ExpressionUtils.convertTypedValue(context, new TypedValue(value), expectedResultType);
123        }
124
125        @Override
126        public String getValue(EvaluationContext context, @Nullable Object rootObject) throws EvaluationException {
127                StringBuilder sb = new StringBuilder();
128                for (Expression expression : this.expressions) {
129                        String value = expression.getValue(context, rootObject, String.class);
130                        if (value != null) {
131                                sb.append(value);
132                        }
133                }
134                return sb.toString();
135        }
136
137        @Override
138        @Nullable
139        public <T> T getValue(EvaluationContext context, @Nullable Object rootObject, @Nullable Class<T> desiredResultType)
140                        throws EvaluationException {
141
142                Object value = getValue(context,rootObject);
143                return ExpressionUtils.convertTypedValue(context, new TypedValue(value), desiredResultType);
144        }
145
146        @Override
147        public Class<?> getValueType() {
148                return String.class;
149        }
150
151        @Override
152        public Class<?> getValueType(EvaluationContext context) {
153                return String.class;
154        }
155
156        @Override
157        public Class<?> getValueType(@Nullable Object rootObject) throws EvaluationException {
158                return String.class;
159        }
160
161        @Override
162        public Class<?> getValueType(EvaluationContext context, @Nullable Object rootObject) throws EvaluationException {
163                return String.class;
164        }
165
166        @Override
167        public TypeDescriptor getValueTypeDescriptor() {
168                return TypeDescriptor.valueOf(String.class);
169        }
170
171        @Override
172        public TypeDescriptor getValueTypeDescriptor(@Nullable Object rootObject) throws EvaluationException {
173                return TypeDescriptor.valueOf(String.class);
174        }
175
176        @Override
177        public TypeDescriptor getValueTypeDescriptor(EvaluationContext context) {
178                return TypeDescriptor.valueOf(String.class);
179        }
180
181        @Override
182        public TypeDescriptor getValueTypeDescriptor(EvaluationContext context, @Nullable Object rootObject)
183                        throws EvaluationException {
184
185                return TypeDescriptor.valueOf(String.class);
186        }
187
188        @Override
189        public boolean isWritable(@Nullable Object rootObject) throws EvaluationException {
190                return false;
191        }
192
193        @Override
194        public boolean isWritable(EvaluationContext context) {
195                return false;
196        }
197
198        @Override
199        public boolean isWritable(EvaluationContext context, @Nullable Object rootObject) throws EvaluationException {
200                return false;
201        }
202
203        @Override
204        public void setValue(@Nullable Object rootObject, @Nullable Object value) throws EvaluationException {
205                throw new EvaluationException(this.expressionString, "Cannot call setValue on a composite expression");
206        }
207
208        @Override
209        public void setValue(EvaluationContext context, @Nullable Object value) throws EvaluationException {
210                throw new EvaluationException(this.expressionString, "Cannot call setValue on a composite expression");
211        }
212
213        @Override
214        public void setValue(EvaluationContext context, @Nullable Object rootObject, @Nullable Object value) throws EvaluationException {
215                throw new EvaluationException(this.expressionString, "Cannot call setValue on a composite expression");
216        }
217
218}