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 java.io.IOException;
23  import java.io.Writer;
24  
25  import org.apache.commons.lang.builder.ToStringBuilder;
26  import org.apache.velocity.context.InternalContextAdapter;
27  import org.apache.velocity.exception.MethodInvocationException;
28  import org.apache.velocity.exception.ParseErrorException;
29  import org.apache.velocity.exception.ResourceNotFoundException;
30  import org.apache.velocity.exception.TemplateInitException;
31  import org.apache.velocity.runtime.directive.Directive;
32  import org.apache.velocity.runtime.parser.ParseException;
33  import org.apache.velocity.runtime.parser.Parser;
34  import org.apache.velocity.runtime.parser.ParserVisitor;
35  import org.apache.velocity.util.ExceptionUtils;
36  
37  /**
38   * This class is responsible for handling the pluggable
39   * directives in VTL.
40   *
41   * For example :  #foreach()
42   *
43   * Please look at the Parser.jjt file which is
44   * what controls the generation of this class.
45   *
46   * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
47   * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
48   * @author <a href="mailto:kav@kav.dk">Kasper Nielsen</a>
49   * @version $Id: ASTDirective.java 471381 2006-11-05 08:56:58Z wglass $
50   */
51  public class ASTDirective extends SimpleNode
52  {
53      private Directive directive = null;
54      private String directiveName = "";
55      private boolean isDirective;
56  
57      /**
58       * @param id
59       */
60      public ASTDirective(int id)
61      {
62          super(id);
63      }
64  
65      /**
66       * @param p
67       * @param id
68       */
69      public ASTDirective(Parser p, int id)
70      {
71          super(p, id);
72      }
73  
74  
75      /**
76       * @see org.apache.velocity.runtime.parser.node.SimpleNode#jjtAccept(org.apache.velocity.runtime.parser.ParserVisitor, java.lang.Object)
77       */
78      public Object jjtAccept(ParserVisitor visitor, Object data)
79      {
80          return visitor.visit(this, data);
81      }
82  
83      /**
84       * @see org.apache.velocity.runtime.parser.node.SimpleNode#init(org.apache.velocity.context.InternalContextAdapter, java.lang.Object)
85       */
86      public Object init( InternalContextAdapter context, Object data)
87      throws TemplateInitException
88      {
89          super.init( context, data );
90  
91          /*
92           *  only do things that are not context dependant
93           */
94  
95          if (parser.isDirective( directiveName ))
96          {
97              isDirective = true;
98  
99              try
100             {
101                 directive = (Directive) parser.getDirective( directiveName )
102                     .getClass().newInstance();
103             } 
104             catch (InstantiationException e)
105             {
106                 throw ExceptionUtils.createRuntimeException("Couldn't initialize " +
107                         "directive of class " +
108                         parser.getDirective(directiveName).getClass().getName(),
109                         e);
110             }
111             catch (IllegalAccessException e)
112             {
113                 throw ExceptionUtils.createRuntimeException("Couldn't initialize " +
114                         "directive of class " +
115                         parser.getDirective(directiveName).getClass().getName(),
116                         e);
117             }
118                 
119             directive.init(rsvc, context,this);
120 
121             directive.setLocation( getLine(), getColumn() );
122         }
123         else if (rsvc.isVelocimacro( directiveName, context.getCurrentTemplateName()  ))
124         {
125             /*
126              *  we seem to be a Velocimacro.
127              */
128 
129             isDirective = true;
130             directive = rsvc.getVelocimacro( directiveName,  context.getCurrentTemplateName());
131 
132             try 
133             {
134                 directive.init( rsvc, context, this );
135             }
136             
137             /**
138              * correct the line/column number if an exception is caught
139              */
140             catch (TemplateInitException die)
141             {
142                 throw new TemplateInitException(die.getMessage(),
143                         (ParseException) die.getWrappedThrowable(),
144                         die.getTemplateName(),
145                         die.getColumnNumber() + getColumn(),
146                         die.getLineNumber() + getLine());
147             }
148             directive.setLocation( getLine(), getColumn() );
149         }
150         else
151         {
152             isDirective = false;
153         }
154 
155         return data;
156     }
157 
158     /**
159      * @see org.apache.velocity.runtime.parser.node.SimpleNode#render(org.apache.velocity.context.InternalContextAdapter, java.io.Writer)
160      */
161     public boolean render( InternalContextAdapter context, Writer writer)
162         throws IOException,MethodInvocationException, ResourceNotFoundException, ParseErrorException
163     {
164         /*
165          *  normal processing
166          */
167 
168         if (isDirective)
169         {
170             directive.render(context, writer, this);
171         }
172         else
173         {
174             if (context.getAllowRendering())
175             {
176                 writer.write( "#");
177                 writer.write( directiveName );
178             }
179         }
180 
181         return true;
182     }
183 
184     /**
185      *   Sets the directive name.  Used by the parser.  This keeps us from having to
186      *   dig it out of the token stream and gives the parse the change to override.
187      * @param str
188      */
189     public void setDirectiveName( String str )
190     {
191         directiveName = str;
192     }
193 
194     /**
195      *  Gets the name of this directive.
196      *  @return The name of this directive.
197      */
198     public String getDirectiveName()
199     {
200         return directiveName;
201     }
202     
203     public String toString()
204     {
205         return new ToStringBuilder(this)
206             .appendSuper(super.toString())
207             .append("directiveName", getDirectiveName())
208             .toString();
209     }
210 
211 }
212 
213