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
29 /**
30 * handles the range 'operator' [ n .. m ]
31 *
32 * Please look at the Parser.jjt file which is
33 * what controls the generation of this class.
34 *
35 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
36 */
37 public class ASTIntegerRange extends SimpleNode
38 {
39 /**
40 * @param id
41 */
42 public ASTIntegerRange(int id)
43 {
44 super(id);
45 }
46
47 /**
48 * @param p
49 * @param id
50 */
51 public ASTIntegerRange(Parser p, int id)
52 {
53 super(p, id);
54 }
55
56 /**
57 * @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.node.ParserVisitor, java.lang.Object)
58 */
59 public Object jjtAccept(ParserVisitor visitor, Object data)
60 {
61 return visitor.visit(this, data);
62 }
63
64 /**
65 * does the real work. Creates an Vector of Integers with the
66 * right value range
67 *
68 * @param context app context used if Left or Right of .. is a ref
69 * @return Object array of Integers
70 * @throws MethodInvocationException
71 */
72 public Object value( InternalContextAdapter context)
73 throws MethodInvocationException
74 {
75 /*
76 * get the two range ends
77 */
78
79 Object left = jjtGetChild(0).value( context );
80 Object right = jjtGetChild(1).value( context );
81
82 /*
83 * if either is null, lets log and bail
84 */
85
86 if (left == null || right == null)
87 {
88 log.error((left == null ? "Left" : "Right")
89 + " side of range operator [n..m] has null value."
90 + " Operation not possible. "
91 + context.getCurrentTemplateName() + " [line " + getLine()
92 + ", column " + getColumn() + "]");
93 return null;
94 }
95
96 /*
97 * if not a Number, not much we can do either
98 */
99
100 if ( !( left instanceof Number ) || !( right instanceof Number ))
101 {
102 log.error((!(left instanceof Number) ? "Left" : "Right")
103 + " side of range operator is not a valid type. "
104 + "Currently only integers (1,2,3...) and the Number type are supported. "
105 + context.getCurrentTemplateName() + " [line " + getLine()
106 + ", column " + getColumn() + ']');
107
108 return null;
109 }
110
111
112 /*
113 * get the two integer values of the ends of the range
114 */
115
116 int l = ((Number) left).intValue() ;
117 int r = ((Number) right).intValue();
118
119 /*
120 * find out how many there are
121 */
122
123 int nbrElements = Math.abs( l - r );
124 nbrElements += 1;
125
126 /*
127 * Determine whether the increment is positive or negative.
128 */
129
130 int delta = ( l >= r ) ? -1 : 1;
131
132 /*
133 * Fill the range with the appropriate values.
134 */
135
136 List elements = new ArrayList(nbrElements);
137 int value = l;
138
139 for (int i = 0; i < nbrElements; i++)
140 {
141 // TODO: JDK 1.4+ -> valueOf()
142 elements.add(new Integer(value));
143 value += delta;
144 }
145
146 return elements;
147 }
148 }