1 | package org.apache.velocity.runtime.parser.node; |
2 | /* |
3 | * Copyright 2000-2001,2004 The Apache Software Foundation. |
4 | * |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
6 | * you may not use this file except in compliance with the License. |
7 | * You may obtain a copy of the License at |
8 | * |
9 | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | * |
11 | * Unless required by applicable law or agreed to in writing, software |
12 | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | * See the License for the specific language governing permissions and |
15 | * limitations under the License. |
16 | */ |
17 | |
18 | import org.apache.velocity.context.Context; |
19 | import org.apache.velocity.runtime.parser.*; |
20 | |
21 | /** |
22 | * Utilities for dealing with the AST node structure. |
23 | * |
24 | * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> |
25 | * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a> |
26 | * @version $Id: NodeUtils.java,v 1.16.4.1 2004/03/03 23:22:59 geirm Exp $ |
27 | */ |
28 | public class NodeUtils |
29 | { |
30 | /** |
31 | * Collect all the <SPECIAL_TOKEN>s that |
32 | * are carried along with a token. Special |
33 | * tokens do not participate in parsing but |
34 | * can still trigger certain lexical actions. |
35 | * In some cases you may want to retrieve these |
36 | * special tokens, this is simply a way to |
37 | * extract them. |
38 | */ |
39 | public static String specialText(Token t) |
40 | { |
41 | String specialText = ""; |
42 | |
43 | if (t.specialToken == null || t.specialToken.image.startsWith("##") ) |
44 | return specialText; |
45 | |
46 | Token tmp_t = t.specialToken; |
47 | |
48 | while (tmp_t.specialToken != null) |
49 | { |
50 | tmp_t = tmp_t.specialToken; |
51 | } |
52 | |
53 | while (tmp_t != null) |
54 | { |
55 | String st = tmp_t.image; |
56 | |
57 | StringBuffer sb = new StringBuffer(); |
58 | |
59 | for(int i = 0; i < st.length(); i++) |
60 | { |
61 | char c = st.charAt(i); |
62 | |
63 | if ( c == '#' || c == '$' ) |
64 | { |
65 | sb.append( c ); |
66 | } |
67 | |
68 | /* |
69 | * more dreaded MORE hack :) |
70 | * |
71 | * looking for ("\\")*"$" sequences |
72 | */ |
73 | |
74 | if ( c == '\\') |
75 | { |
76 | boolean ok = true; |
77 | boolean term = false; |
78 | |
79 | int j = i; |
80 | for( ok = true; ok && j < st.length(); j++) |
81 | { |
82 | char cc = st.charAt( j ); |
83 | |
84 | if (cc == '\\') |
85 | { |
86 | /* |
87 | * if we see a \, keep going |
88 | */ |
89 | continue; |
90 | } |
91 | else if( cc == '$' ) |
92 | { |
93 | /* |
94 | * a $ ends it correctly |
95 | */ |
96 | term = true; |
97 | ok = false; |
98 | } |
99 | else |
100 | { |
101 | /* |
102 | * nah... |
103 | */ |
104 | ok = false; |
105 | } |
106 | } |
107 | |
108 | if (term) |
109 | { |
110 | String foo = st.substring( i, j ); |
111 | sb.append( foo ); |
112 | i = j; |
113 | } |
114 | } |
115 | } |
116 | |
117 | specialText += sb.toString(); |
118 | |
119 | tmp_t = tmp_t.next; |
120 | } |
121 | |
122 | return specialText; |
123 | } |
124 | |
125 | /** |
126 | * complete node literal |
127 | * |
128 | */ |
129 | public static String tokenLiteral( Token t ) |
130 | { |
131 | return specialText( t ) + t.image; |
132 | } |
133 | |
134 | /** |
135 | * Utility method to interpolate context variables |
136 | * into string literals. So that the following will |
137 | * work: |
138 | * |
139 | * #set $name = "candy" |
140 | * $image.getURI("${name}.jpg") |
141 | * |
142 | * And the string literal argument will |
143 | * be transformed into "candy.jpg" before |
144 | * the method is executed. |
145 | */ |
146 | public static String interpolate(String argStr, Context vars) |
147 | { |
148 | StringBuffer argBuf = new StringBuffer(); |
149 | |
150 | for (int cIdx = 0 ; cIdx < argStr.length();) |
151 | { |
152 | char ch = argStr.charAt(cIdx); |
153 | |
154 | switch (ch) |
155 | { |
156 | case '$': |
157 | StringBuffer nameBuf = new StringBuffer(); |
158 | for (++cIdx ; cIdx < argStr.length(); ++cIdx) |
159 | { |
160 | ch = argStr.charAt(cIdx); |
161 | if (ch == '_' || ch == '-' |
162 | || Character.isLetterOrDigit(ch)) |
163 | nameBuf.append(ch); |
164 | else if (ch == '{' || ch == '}') |
165 | continue; |
166 | else |
167 | break; |
168 | } |
169 | |
170 | if (nameBuf.length() > 0) |
171 | { |
172 | Object value = vars.get(nameBuf.toString()); |
173 | |
174 | if (value == null) |
175 | argBuf.append("$").append(nameBuf.toString()); |
176 | else |
177 | argBuf.append(value.toString()); |
178 | } |
179 | break; |
180 | |
181 | default: |
182 | argBuf.append(ch); |
183 | ++cIdx; |
184 | break; |
185 | } |
186 | } |
187 | |
188 | return argBuf.toString(); |
189 | } |
190 | } |