1 52 53 package freemarker.core; 54 55 import java.io.IOException ; 56 import java.util.*; 57 import freemarker.template.*; 58 59 62 public final class Macro extends TemplateElement implements TemplateModel { 63 private final String name; 64 private final String [] argumentNames; 65 private Map args; 66 private String 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 name, 74 List argumentNames, 75 Map args, 76 TemplateElement nestedBlock) 77 { 78 this.name = name; 79 this.argumentNames = (String [])argumentNames.toArray(new String [argumentNames.size()]); 80 this.args = args; 81 this.nestedBlock = nestedBlock; 82 } 83 84 public String getCatchAll() { 85 return catchAll; 86 } 87 88 public void setCatchAll(String value) { 89 catchAll = value; 90 } 91 92 public String [] getArgumentNames() { 93 return argumentNames; 94 } 95 96 boolean hasArgNamed(String name) { 97 return args.containsKey(name); 98 } 99 100 public String getName() { 101 return name; 102 } 103 104 void accept(Environment env) { 105 env.visitMacroDef(this); 106 } 107 108 public String getCanonicalForm() { 109 StringBuffer buf = new StringBuffer ("<#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 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 { 161 sanityCheck(env); 162 if (nestedBlock != null) { 164 env.visit(nestedBlock); 165 } 166 } 167 168 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 argName = (String ) 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 191 public TemplateModel getLocalVariable(String name) throws TemplateModelException { 192 return localVars.get(name); 193 } 194 195 Environment.Namespace getLocals() { 196 return localVars; 197 } 198 199 202 void setLocalVar(String 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 |