1 package org.apache.velocity.runtime.parser.node;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import org.apache.velocity.context.InternalContextAdapter;
26 import org.apache.velocity.exception.MethodInvocationException;
27 import org.apache.velocity.runtime.parser.Parser;
28 import org.apache.velocity.runtime.parser.ParserVisitor;
29
30 /**
31 * handles the range 'operator' [ n .. m ]
32 *
33 * Please look at the Parser.jjt file which is
34 * what controls the generation of this class.
35 *
36 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
37 */
38 public class ASTIntegerRange extends SimpleNode
39 {
40 /**
41 * @param id
42 */
43 public ASTIntegerRange(int id)
44 {
45 super(id);
46 }
47
48 /**
49 * @param p
50 * @param id
51 */
52 public ASTIntegerRange(Parser p, int id)
53 {
54 super(p, id);
55 }
56
57 /**
58 * @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.ParserVisitor, java.lang.Object)
59 */
60 public Object jjtAccept(ParserVisitor visitor, Object data)
61 {
62 return visitor.visit(this, data);
63 }
64
65 /**
66 * does the real work. Creates an Vector of Integers with the
67 * right value range
68 *
69 * @param context app context used if Left or Right of .. is a ref
70 * @return Object array of Integers
71 * @throws MethodInvocationException
72 */
73 public Object value( InternalContextAdapter context)
74 throws MethodInvocationException
75 {
76 /*
77 * get the two range ends
78 */
79
80 Object left = jjtGetChild(0).value( context );
81 Object right = jjtGetChild(1).value( context );
82
83 /*
84 * if either is null, lets log and bail
85 */
86
87 if (left == null || right == null)
88 {
89 log.error((left == null ? "Left" : "Right")
90 + " side of range operator [n..m] has null value."
91 + " Operation not possible. "
92 + context.getCurrentTemplateName() + " [line " + getLine()
93 + ", column " + getColumn() + "]");
94 return null;
95 }
96
97 /*
98 * if not an Integer, not much we can do either
99 */
100
101 if ( !( left instanceof Integer ) || !( right instanceof Integer ))
102 {
103 log.error((!(left instanceof Integer) ? "Left" : "Right")
104 + " side of range operator is not a valid type. "
105 + "Currently only integers (1,2,3...) and Integer type is supported. "
106 + context.getCurrentTemplateName() + " [line " + getLine()
107 + ", column " + getColumn() + "]");
108
109 return null;
110 }
111
112
113 /*
114 * get the two integer values of the ends of the range
115 */
116
117 int l = ( (Integer) left ).intValue() ;
118 int r = ( (Integer) right ).intValue();
119
120 /*
121 * find out how many there are
122 */
123
124 int nbrElements = Math.abs( l - r );
125 nbrElements += 1;
126
127 /*
128 * Determine whether the increment is positive or negative.
129 */
130
131 int delta = ( l >= r ) ? -1 : 1;
132
133 /*
134 * Fill the range with the appropriate values.
135 */
136
137 List elements = new ArrayList(nbrElements);
138 int value = l;
139
140 for (int i = 0; i < nbrElements; i++)
141 {
142 // TODO: JDK 1.4+ -> valueOf()
143 elements.add(new Integer(value));
144 value += delta;
145 }
146
147 return elements;
148 }
149 }