KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > freemarker > core > Macro


1 /*
2  * Copyright (c) 2003 The Visigoth Software Society. All rights
3  * reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  *
17  * 3. The end-user documentation included with the redistribution, if
18  * any, must include the following acknowledgement:
19  * "This product includes software developed by the
20  * Visigoth Software Society (http://www.visigoths.org/)."
21  * Alternately, this acknowledgement may appear in the software itself,
22  * if and wherever such third-party acknowledgements normally appear.
23  *
24  * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
25  * project contributors may be used to endorse or promote products derived
26  * from this software without prior written permission. For written
27  * permission, please contact visigoths@visigoths.org.
28  *
29  * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
30  * nor may "FreeMarker" or "Visigoth" appear in their names
31  * without prior written permission of the Visigoth Software Society.
32  *
33  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
34  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36  * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
37  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
38  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
39  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
40  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
42  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
43  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  * ====================================================================
46  *
47  * This software consists of voluntary contributions made by many
48  * individuals on behalf of the Visigoth Software Society. For more
49  * information on the Visigoth Software Society, please see
50  * http://www.visigoths.org/
51  */

52
53 package freemarker.core;
54
55 import java.io.IOException JavaDoc;
56 import java.util.*;
57 import freemarker.template.*;
58
59 /**
60  * An element representing a macro declaration.
61  */

62 public final class Macro extends TemplateElement implements TemplateModel {
63     private final String JavaDoc name;
64     private final String JavaDoc[] argumentNames;
65     private Map args;
66     private String JavaDoc catchAll;
67     boolean isFunction;
68     static final Macro DO_NOTHING_MACRO = new Macro(".pass",
69                                                     Collections.EMPTY_LIST,
70                                                     freemarker.template.utility.Collections12.EMPTY_MAP,
71                                                     TextBlock.EMPTY_BLOCK);
72     
73     Macro(String JavaDoc name,
74           List argumentNames,
75           Map args,
76           TemplateElement nestedBlock)
77     {
78         this.name = name;
79         this.argumentNames = (String JavaDoc[])argumentNames.toArray(new String JavaDoc[argumentNames.size()]);
80         this.args = args;
81         this.nestedBlock = nestedBlock;
82     }
83
84     public String JavaDoc getCatchAll() {
85         return catchAll;
86     }
87     
88     public void setCatchAll(String JavaDoc value) {
89         catchAll = value;
90     }
91
92     public String JavaDoc[] getArgumentNames() {
93         return argumentNames;
94     }
95
96     boolean hasArgNamed(String JavaDoc name) {
97         return args.containsKey(name);
98     }
99
100     public String JavaDoc getName() {
101         return name;
102     }
103
104     void accept(Environment env) {
105         env.visitMacroDef(this);
106     }
107
108     public String JavaDoc getCanonicalForm() {
109         StringBuffer JavaDoc buf = new StringBuffer JavaDoc("<#macro ");
110         buf.append(name);
111         buf.append("(");
112         int size = argumentNames.length;
113         for (int i = 0; i<size; i++) {
114             buf.append(argumentNames[i]);
115             if (i != (size-1)) {
116                 buf.append(",");
117             }
118         }
119         buf.append(")>");
120         if (nestedBlock != null) {
121             buf.append(nestedBlock.getCanonicalForm());
122         }
123         buf.append("</#macro>");
124         return buf.toString();
125     }
126
127     public String JavaDoc getDescription() {
128         return "macro " + name;
129     }
130
131     public boolean isFunction() {
132         return isFunction;
133     }
134
135     class Context implements LocalContext {
136         Environment.Namespace localVars;
137         TemplateElement body;
138         Environment.Namespace bodyNamespace;
139         List bodyParameterNames;
140         Context prevMacroContext;
141         ArrayList prevLocalContextStack;
142         
143         Context(Environment env,
144                 TemplateElement body,
145                 List bodyParameterNames)
146         {
147             this.localVars = env.new Namespace();
148             this.prevMacroContext = env.getCurrentMacroContext();
149             this.bodyNamespace = env.getCurrentNamespace();
150             this.prevLocalContextStack = env.getLocalContextStack();
151             this.body = body;
152             this.bodyParameterNames = bodyParameterNames;
153         }
154                 
155         
156         Macro getMacro() {
157             return Macro.this;
158         }
159
160         void runMacro(Environment env) throws TemplateException, IOException JavaDoc {
161             sanityCheck(env);
162             // Set default values for unspecified parameters
163
if (nestedBlock != null) {
164                 env.visit(nestedBlock);
165             }
166         }
167
168         // Set default parameters, check if all the required parameters are defined.
169
void sanityCheck(Environment env) throws TemplateException {
170             for (Iterator it = args.entrySet().iterator(); it.hasNext();) {
171                 Map.Entry entry = (Map.Entry) it.next();
172                 String JavaDoc argName = (String JavaDoc) entry.getKey();
173                 if (localVars.get(argName)==null) {
174                     Expression valueExp = (Expression) entry.getValue();
175                     if (valueExp != null) {
176                         TemplateModel tm = valueExp.getAsTemplateModel(env);
177                         assertNonNull(tm, valueExp, env);
178                         localVars.put(argName, tm);
179                     }
180                     else {
181                         throw new TemplateException("Error executing macro: " + name + "\nrequired parameter: " + argName + " is not specified.", env);
182                     }
183                 }
184             }
185         }
186
187         /**
188          * @return the local variable of the given name
189          * or null if it doesn't exist.
190          */

191         public TemplateModel getLocalVariable(String JavaDoc name) throws TemplateModelException {
192              return localVars.get(name);
193         }
194
195         Environment.Namespace getLocals() {
196             return localVars;
197         }
198         
199         /**
200          * Set a local variable in this macro
201          */

202         void setLocalVar(String JavaDoc name, TemplateModel var) {
203             localVars.put(name, var);
204         }
205
206         public Set getLocalVariableNames() throws TemplateModelException {
207             HashSet result = new HashSet();
208             for (TemplateModelIterator it = localVars.keys().iterator(); it.hasNext();) {
209                 result.add(it.next().toString());
210             }
211             return result;
212         }
213     }
214 }
215
Popular Tags