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