View Javadoc

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 org.apache.commons.lang.text.StrBuilder;
23  import org.apache.velocity.context.Context;
24  import org.apache.velocity.exception.MethodInvocationException;
25  import org.apache.velocity.runtime.parser.ParserConstants;
26  import org.apache.velocity.runtime.parser.Token;
27  
28  /**
29   * Utilities for dealing with the AST node structure.
30   *
31   * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
32   * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
33   * @version $Id: NodeUtils.java 687386 2008-08-20 16:57:07Z nbubna $
34   */
35  public class NodeUtils
36  {
37      /**
38       * @deprecated use getSpecialText(Token t)
39       */
40      public static String specialText(Token t)
41      {
42          if (t.specialToken == null || t.specialToken.image.startsWith("##") )
43          {
44              return "";
45          }
46          return getSpecialText(t).toString();
47      }
48  
49      /**
50       * Collect all the <SPECIAL_TOKEN>s that
51       * are carried along with a token. Special
52       * tokens do not participate in parsing but
53       * can still trigger certain lexical actions.
54       * In some cases you may want to retrieve these
55       * special tokens, this is simply a way to
56       * extract them.
57       * @param t the Token
58       * @return StrBuilder with the special tokens.
59       */
60      public static StrBuilder getSpecialText(Token t)
61      {
62          StrBuilder sb = new StrBuilder();
63  
64          Token tmp_t = t.specialToken;
65  
66          while (tmp_t.specialToken != null)
67          {
68              tmp_t = tmp_t.specialToken;
69          }
70  
71          while (tmp_t != null)
72          {
73              String st = tmp_t.image;
74  
75              for(int i = 0, is = st.length(); i < is; i++)
76              {
77                  char c = st.charAt(i);
78  
79                  if ( c == '#' || c == '$' )
80                  {
81                      sb.append( c );
82                  }
83  
84                  /*
85                   *  more dreaded MORE hack :)
86                   *
87                   *  looking for ("\\")*"$" sequences
88                   */
89  
90                  if ( c == '\\')
91                  {
92                      boolean ok = true;
93                      boolean term = false;
94  
95                      int j = i;
96                      for( ok = true; ok && j < is; j++)
97                      {
98                          char cc = st.charAt( j );
99  
100                         if (cc == '\\')
101                         {
102                             /*
103                              *  if we see a \, keep going
104                              */
105                             continue;
106                         }
107                         else if( cc == '$' )
108                         {
109                             /*
110                              *  a $ ends it correctly
111                              */
112                             term = true;
113                             ok = false;
114                         }
115                         else
116                         {
117                             /*
118                              *  nah...
119                              */
120                             ok = false;
121                         }
122                     }
123 
124                     if (term)
125                     {
126                         String foo =  st.substring( i, j );
127                         sb.append( foo );
128                         i = j;
129                     }
130                 }
131             }
132 
133             tmp_t = tmp_t.next;
134         }
135         return sb;
136     }
137 
138     /**
139      *  complete node literal
140      * @param t
141      * @return A node literal.
142      */
143     public static String tokenLiteral( Token t )
144     {
145         // Look at kind of token and return "" when it's a multiline comment
146         if (t.kind == ParserConstants.MULTI_LINE_COMMENT) 
147         {
148             return "";
149         } 
150         else if (t.specialToken == null || t.specialToken.image.startsWith("##"))
151         {
152             return t.image;
153         }
154         else 
155         {
156             StrBuilder special = getSpecialText(t);
157             if (special.length() > 0)
158             {
159                 return special.append(t.image).toString();
160             }
161             return t.image;
162         }
163     } 
164     
165     /**
166      * Utility method to interpolate context variables
167      * into string literals. So that the following will
168      * work:
169      *
170      * #set $name = "candy"
171      * $image.getURI("${name}.jpg")
172      *
173      * And the string literal argument will
174      * be transformed into "candy.jpg" before
175      * the method is executed.
176      * 
177      * @deprecated this method isn't called by any class
178      * 
179      * @param argStr
180      * @param vars
181      * @return Interpoliation result.
182      * @throws MethodInvocationException
183      */
184     public static String interpolate(String argStr, Context vars) throws MethodInvocationException
185     {
186         // if there's nothing to replace, skip this (saves buffer allocation)
187         if( argStr.indexOf('$') == -1 )
188             return argStr;
189         
190         StrBuilder argBuf = new StrBuilder();
191 
192         for (int cIdx = 0, is = argStr.length(); cIdx < is;)
193         {
194             char ch = argStr.charAt(cIdx);
195             
196             if( ch == '$' )
197             {
198                 StrBuilder nameBuf = new StrBuilder();
199                 for (++cIdx ; cIdx < is; ++cIdx)
200                 {
201                     ch = argStr.charAt(cIdx);
202                     if (ch == '_' || ch == '-'
203                         || Character.isLetterOrDigit(ch))
204                         nameBuf.append(ch);
205                     else if (ch == '{' || ch == '}')
206                         continue;
207                     else
208                         break;
209                 }
210 
211                 if (nameBuf.length() > 0)
212                 {
213                     Object value = vars.get(nameBuf.toString());
214 
215                     if (value == null)
216                         argBuf.append("$").append(nameBuf.toString());
217                     else
218                         argBuf.append(value.toString());
219                 }
220                 
221             }
222             else
223             {
224                 argBuf.append(ch);
225                 ++cIdx;
226             }
227         }
228 
229         return argBuf.toString();
230     }
231 }