KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > freemarker > core > DynamicKeyName


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 java.util.ArrayList JavaDoc;
56 import freemarker.template.*;
57
58 /**
59  * A unary operator that uses the string value of an expression as a hash key.
60  * It associates with the <tt>Identifier</tt> or <tt>Dot</tt> to its left.
61  */

62 final class DynamicKeyName extends Expression {
63
64     private final Expression nameExpression;
65     private final Expression target;
66
67     DynamicKeyName(Expression target, Expression nameExpression) {
68         this.target = target;
69         this.nameExpression = nameExpression;
70     }
71
72     TemplateModel _getAsTemplateModel(Environment env) throws TemplateException
73     {
74         TemplateModel targetModel = target.getAsTemplateModel(env);
75         assertNonNull(targetModel, target, env);
76         if (nameExpression instanceof Range) {
77             return dealWithRangeKey(targetModel, (Range) nameExpression, env);
78         }
79         TemplateModel keyModel = nameExpression.getAsTemplateModel(env);
80         if(keyModel == null) {
81             if(env.isClassicCompatible()) {
82                 keyModel = TemplateScalarModel.EMPTY_STRING;
83             }
84             else {
85                 assertNonNull(keyModel, nameExpression, env);
86             }
87         }
88         if (keyModel instanceof TemplateNumberModel) {
89             int index = EvaluationUtil.getNumber(keyModel, nameExpression, env).intValue();
90             return dealWithNumericalKey(targetModel, index, env);
91         }
92         if (keyModel instanceof TemplateScalarModel) {
93             String JavaDoc key = EvaluationUtil.getString((TemplateScalarModel)keyModel, nameExpression, env);
94             return dealWithStringKey(targetModel, key, env);
95         }
96         throw invalidTypeException(keyModel, nameExpression, env, "number, range, or string");
97     }
98
99
100     private TemplateModel dealWithNumericalKey(TemplateModel targetModel,
101                                                int index,
102                                                Environment env)
103         throws TemplateException
104     {
105         if (targetModel instanceof TemplateSequenceModel) {
106             TemplateSequenceModel tsm = (TemplateSequenceModel) targetModel;
107             int size = Integer.MAX_VALUE;
108             try {
109                 size = tsm.size();
110             } catch (Exception JavaDoc e) {}
111             return index<size ? tsm.get(index) : null;
112         }
113         
114         try
115         {
116             String JavaDoc s = target.getStringValue(env);
117             try {
118                return new SimpleScalar(s.substring(index, index+1));
119             } catch (RuntimeException JavaDoc re) {
120                 throw new TemplateException("", re, env);
121             }
122         }
123         catch(NonStringException e)
124         {
125             throw invalidTypeException(targetModel, target, env, "number, sequence, or string");
126         }
127     }
128
129
130     private TemplateModel dealWithStringKey(TemplateModel targetModel,
131                                             String JavaDoc key,
132                                             Environment env)
133         throws TemplateException
134     {
135         if(targetModel instanceof TemplateHashModel) {
136             return((TemplateHashModel) targetModel).get(key);
137         }
138         throw invalidTypeException(targetModel, target, env, "hash");
139     }
140
141     private TemplateModel dealWithRangeKey(TemplateModel targetModel,
142                                            Range range,
143                                            Environment env)
144         throws TemplateException
145     {
146         int start = EvaluationUtil.getNumber(range.left, env).intValue();
147         int end = EvaluationUtil.getNumber(range.right, env).intValue();
148         if (targetModel instanceof TemplateSequenceModel) {
149             TemplateSequenceModel sequence = (TemplateSequenceModel) targetModel;
150             ArrayList JavaDoc list = new ArrayList JavaDoc(1+Math.abs(start-end));
151             if (start>end) {
152                 for (int i = start; i>=end; i--) {
153                     list.add(sequence.get(i));
154                 }
155             }
156             else {
157                 for (int i = start; i<=end; i++) {
158                     list.add(sequence.get(i));
159                 }
160             }
161             return new SimpleSequence(list);
162         }
163         
164         try
165         {
166             String JavaDoc s = target.getStringValue(env);
167             try {
168                 return new SimpleScalar(s.substring(start, end+1));
169             } catch (RuntimeException JavaDoc re) {
170                 String JavaDoc msg = "Error " + getStartLocation();
171                 throw new TemplateException(msg, re, env);
172             }
173         }
174         catch(NonStringException e)
175         {
176             throw invalidTypeException(target.getAsTemplateModel(env), target, env, "number, scalar, or sequence");
177         }
178     }
179
180     public String JavaDoc getCanonicalForm() {
181         return target.getCanonicalForm()
182                + "["
183                + nameExpression.getCanonicalForm()
184                + "]";
185     }
186     
187     boolean isLiteral() {
188         return constantValue != null || (target.isLiteral() && nameExpression.isLiteral());
189     }
190
191     Expression _deepClone(String JavaDoc name, Expression subst) {
192         return new DynamicKeyName(target.deepClone(name, subst), nameExpression.deepClone(name, subst));
193     }
194 }
195
Popular Tags