KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > freemarker > core > AddConcatExpression


1 /*
2  * Copyright (c) 2003 The Visigoth Software Society. All rights
3  * reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * 3. The end-user documentation included with the redistribution, if
18  * any, must include the following acknowledgement:
19  * "This product includes software developed by the
20  * Visigoth Software Society (http://www.visigoths.org/)."
21  * Alternately, this acknowledgement may appear in the software itself,
22  * if and wherever such third-party acknowledgements normally appear.
23  *
24  * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
25  * project contributors may be used to endorse or promote products derived
26  * from this software without prior written permission. For written
27  * permission, please contact visigoths@visigoths.org.
28  *
29  * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
30  * nor may "FreeMarker" or "Visigoth" appear in their names
31  * without prior written permission of the Visigoth Software Society.
32  *
33  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
34  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36  * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
37  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
40  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  * ====================================================================
46  *
47  * This software consists of voluntary contributions made by many
48  * individuals on behalf of the Visigoth Software Society. For more
49  * information on the Visigoth Software Society, please see
50  * http://www.visigoths.org/
51  */

52
53 package freemarker.core;
54
55 import freemarker.template.*;
56 import java.util.*;
57
58 /**
59  * An operator for the + operator. Note that this is treated
60  * separately from the other 4 arithmetic operators,
61  * since + is overloaded to mean string concatenation.
62  * @author <a HREF="mailto:jon@revusky.com">Jonathan Revusky</a>
63  */

64 final class AddConcatExpression extends Expression {
65
66     private final Expression left;
67     private final Expression right;
68
69     AddConcatExpression(Expression left, Expression right) {
70         this.left = left;
71         this.right = right;
72     }
73
74     TemplateModel _getAsTemplateModel(Environment env)
75             throws TemplateException
76     {
77         TemplateModel leftModel = left.getAsTemplateModel(env);
78         TemplateModel rightModel = right.getAsTemplateModel(env);
79         if (leftModel instanceof TemplateNumberModel && rightModel instanceof TemplateNumberModel)
80         {
81             Number JavaDoc first = EvaluationUtil.getNumber((TemplateNumberModel) leftModel, left, env);
82             Number JavaDoc second = EvaluationUtil.getNumber((TemplateNumberModel) rightModel, right, env);
83             ArithmeticEngine ae =
84                 env != null
85                     ? env.getArithmeticEngine()
86                     : getTemplate().getArithmeticEngine();
87             return new SimpleNumber(ae.add(first, second));
88         }
89         else if(leftModel instanceof TemplateSequenceModel && rightModel instanceof TemplateSequenceModel)
90         {
91             return new ConcatenatedSequence((TemplateSequenceModel)leftModel, (TemplateSequenceModel)rightModel);
92         }
93         else
94         {
95             try {
96                 String JavaDoc s1 = getStringValue(leftModel, left, env);
97                 if(s1 == null) s1 = "null";
98                 String JavaDoc s2 = getStringValue(rightModel, right, env);
99                 if(s2 == null) s2 = "null";
100                 return new SimpleScalar(s1.concat(s2));
101             } catch (NonStringException e) {
102                 if (leftModel instanceof TemplateHashModel && rightModel instanceof TemplateHashModel) {
103                     if (leftModel instanceof TemplateHashModelEx && rightModel instanceof TemplateHashModelEx) {
104                         TemplateHashModelEx leftModelEx = (TemplateHashModelEx)leftModel;
105                         TemplateHashModelEx rightModelEx = (TemplateHashModelEx)rightModel;
106                         if (leftModelEx.size() == 0) {
107                             return rightModelEx;
108                         } else if (rightModelEx.size() == 0) {
109                             return leftModelEx;
110                         } else {
111                             return new ConcatenatedHashEx(leftModelEx, rightModelEx);
112                         }
113                     } else {
114                         return new ConcatenatedHash((TemplateHashModel)leftModel,
115                                                     (TemplateHashModel)rightModel);
116                     }
117                 } else {
118                     throw e;
119                 }
120             }
121         }
122     }
123
124     boolean isLiteral() {
125         return constantValue != null || (left.isLiteral() && right.isLiteral());
126     }
127
128     Expression _deepClone(String JavaDoc name, Expression subst) {
129         return new AddConcatExpression(left.deepClone(name, subst), right.deepClone(name, subst));
130     }
131
132     public String JavaDoc getCanonicalForm() {
133         return left.getCanonicalForm() + " + " + right.getCanonicalForm();
134     }
135
136     private static final class ConcatenatedSequence
137     implements
138         TemplateSequenceModel
139     {
140         private final TemplateSequenceModel left;
141         private final TemplateSequenceModel right;
142
143         ConcatenatedSequence(TemplateSequenceModel left, TemplateSequenceModel right)
144         {
145             this.left = left;
146             this.right = right;
147         }
148
149         public int size()
150         throws
151             TemplateModelException
152         {
153             return left.size() + right.size();
154         }
155
156         public TemplateModel get(int i)
157         throws
158             TemplateModelException
159         {
160             int ls = left.size();
161             return i < ls ? left.get(i) : right.get(i - ls);
162         }
163     }
164
165     private static class ConcatenatedHash
166     implements TemplateHashModel
167     {
168         protected final TemplateHashModel left;
169         protected final TemplateHashModel right;
170
171         ConcatenatedHash(TemplateHashModel left, TemplateHashModel right)
172         {
173             this.left = left;
174             this.right = right;
175         }
176         
177         public TemplateModel get(String JavaDoc key)
178         throws TemplateModelException
179         {
180             TemplateModel model = right.get(key);
181             return (model != null) ? model : left.get(key);
182         }
183
184         public boolean isEmpty()
185         throws TemplateModelException
186         {
187             return left.isEmpty() && right.isEmpty();
188         }
189     }
190
191     private static final class ConcatenatedHashEx
192     extends ConcatenatedHash
193     implements TemplateHashModelEx
194     {
195         private Set keySet;
196         private TemplateCollectionModel keys;
197         private TemplateCollectionModel values;
198         private int size;
199
200         ConcatenatedHashEx(TemplateHashModelEx left, TemplateHashModelEx right)
201         {
202             super(left, right);
203         }
204         
205         public int size() throws TemplateModelException
206         {
207             initKeys();
208             return size;
209         }
210
211         public TemplateCollectionModel keys()
212         throws TemplateModelException
213         {
214             initKeys();
215             return keys;
216         }
217
218         public TemplateCollectionModel values()
219         throws TemplateModelException
220         {
221             initValues();
222             return values;
223         }
224
225         private void initKeys()
226         throws TemplateModelException
227         {
228             if (keys == null) {
229                 keySet = new HashSet();
230                 addKeys(keySet, (TemplateHashModelEx)this.left);
231                 addKeys(keySet, (TemplateHashModelEx)this.right);
232                 size = keySet.size();
233                 keys = new CollectionAndSequence(new SimpleSequence(keySet));
234             }
235         }
236
237         private static void addKeys(Set set, TemplateHashModelEx hash)
238         throws TemplateModelException
239         {
240             TemplateModelIterator it = hash.keys().iterator();
241             while (it.hasNext()) {
242                 set.add(((TemplateScalarModel)it.next()).getAsString());
243             }
244         }
245
246         private void initValues()
247         throws TemplateModelException
248         {
249             if (values == null) {
250                 List list = new ArrayList(size());
251                 for (Iterator it = keySet.iterator(); it.hasNext();) {
252                     list.add(get((String JavaDoc)it.next()));
253                 }
254                 values = new CollectionAndSequence(new SimpleSequence(list));
255             }
256         }
257     }
258 }
259
Popular Tags