• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.apache.velocity.runtime.directive;
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.velocity.context.InternalContextAdapter;
23 import org.apache.velocity.exception.TemplateInitException;
24 import org.apache.velocity.exception.VelocityException;
25 import org.apache.velocity.runtime.RuntimeConstants;
26 import org.apache.velocity.runtime.RuntimeServices;
27 import org.apache.velocity.runtime.parser.ParseException;
28 import org.apache.velocity.runtime.parser.Token;
29 import org.apache.velocity.runtime.parser.node.Node;
30 import org.apache.velocity.runtime.parser.node.ParserTreeConstants;
31 import org.apache.velocity.util.StringUtils;
32 
33 import java.io.Writer;
34 import java.util.ArrayList;
35 
36 /**
37  * Directive that puts an unrendered AST block in the context
38  * under the specified key, postponing rendering until the
39  * reference is used and rendered.
40  *
41  * @author Andrew Tetlaw
42  * @author Nathan Bubna
43  * @version $Id: Define.java 686842 2008-08-18 18:29:31Z nbubna $
44  */
45 public class Define extends Block
46 {
47     /**
48      * Return name of this directive.
49      */
50     @Override
getName()51     public String getName()
52     {
53         return "define";
54     }
55 
56     /**
57      *  simple init - get the key
58      */
59     @Override
init(RuntimeServices rs, InternalContextAdapter context, Node node)60     public void init(RuntimeServices rs, InternalContextAdapter context, Node node)
61         throws TemplateInitException
62     {
63         super.init(rs, context, node);
64 
65         // the first child is the block name (key), the second child is the block AST body
66         if ( node.jjtGetNumChildren() != 2 )
67         {
68             throw new VelocityException("parameter missing: block name at "
69                  + StringUtils.formatFileString(this),
70                 null,
71                 rsvc.getLogContext().getStackTrace());
72         }
73 
74         /*
75          * first token is the name of the block. We don't even check the format,
76          * just assume it looks like this: $block_name. Should we check if it has
77          * a '$' or not?
78          */
79         key = node.jjtGetChild(0).getFirstTokenImage().substring(1);
80 
81         /*
82          * default max depth of two is used because intentional recursion is
83          * unlikely and discouraged, so make unintentional ones end fast
84          */
85         maxDepth = rsvc.getInt(RuntimeConstants.DEFINE_DIRECTIVE_MAXDEPTH, 2);
86     }
87 
88     /**
89      * directive.render() simply makes an instance of the Block inner class
90      * and places it into the context as indicated.
91      */
92     @Override
render(InternalContextAdapter context, Writer writer, Node node)93     public boolean render(InternalContextAdapter context, Writer writer, Node node)
94     {
95         /* put a Block.Reference instance into the context,
96          * using the user-defined key, for later inline rendering.
97          */
98         context.put(key, new Reference(context, this));
99         return true;
100     }
101 
102     /**
103      * Called by the parser to validate the argument types
104      */
105     @Override
checkArgs(ArrayList<Integer> argtypes, Token t, String templateName)106     public void checkArgs(ArrayList<Integer> argtypes, Token t, String templateName)
107     throws ParseException
108     {
109       if (argtypes.size() != 1)
110       {
111           throw new MacroParseException("The #define directive requires one argument",
112              templateName, t);
113       }
114 
115       if (argtypes.get(0) == ParserTreeConstants.JJTWORD)
116       {
117           throw new MacroParseException("The argument to #define is of the wrong type",
118               templateName, t);
119       }
120     }
121 }
122