1 52 53 package freemarker.core; 54 55 import java.io.*; 56 import java.util.*; 57 import freemarker.template.*; 58 59 62 final class UnifiedCall extends TemplateElement { 63 64 private Expression nameExp; 65 private Map namedArgs; 66 private List positionalArgs, bodyParameterNames; 67 boolean legacySyntax, notransform; 68 69 70 UnifiedCall(Expression nameExp, 71 Map namedArgs, 72 TemplateElement nestedBlock, 73 List bodyParameterNames) 74 { 75 this.nameExp = nameExp; 76 this.namedArgs = namedArgs; 77 this.nestedBlock = nestedBlock; 78 this.bodyParameterNames = bodyParameterNames; 79 notransform = legacySyntax 80 || (positionalArgs != null && positionalArgs.isEmpty()) 81 || (bodyParameterNames != null && !bodyParameterNames.isEmpty()); 82 } 83 84 UnifiedCall(Expression nameExp, 85 List positionalArgs, 86 TemplateElement nestedBlock, 87 List bodyParameterNames) 88 { 89 this.nameExp = nameExp; 90 this.positionalArgs = positionalArgs; 91 if (nestedBlock == TextBlock.EMPTY_BLOCK) { 92 nestedBlock = null; 93 } 94 this.nestedBlock = nestedBlock; 95 this.bodyParameterNames = bodyParameterNames; 96 } 97 98 99 void accept(Environment env) throws TemplateException, IOException { 100 TemplateModel tm = nameExp.getAsTemplateModel(env); 101 if (tm == Macro.DO_NOTHING_MACRO) return; if (!notransform && (tm instanceof TemplateTransformModel)) { 103 Map args; 104 if (namedArgs != null && !namedArgs.isEmpty()) { 105 args = new HashMap(); 106 for (Iterator it = namedArgs.entrySet().iterator(); it.hasNext();) { 107 Map.Entry entry = (Map.Entry) it.next(); 108 String key = (String ) entry.getKey(); 109 Expression valueExp = (Expression) entry.getValue(); 110 TemplateModel value = valueExp.getAsTemplateModel(env); 111 args.put(key, value); 112 } 113 } else { 114 args = EmptyMap.instance; 115 } 116 env.visit(nestedBlock, (TemplateTransformModel) tm, args); 117 return; 118 } 119 if (tm instanceof Macro) { 120 Macro macro = (Macro) tm; 121 if (macro.isFunction && !legacySyntax) { 122 throw new TemplateException("Routine " 123 + macro.getName() 124 + " is a function. " 125 + "A function can only be called within the evaluation of an expression.", 126 env); 127 } 128 env.visit(macro, 129 namedArgs, 130 positionalArgs, 131 bodyParameterNames, 132 nestedBlock); 133 return; 134 } 135 if (tm == null) { 136 throw new InvalidReferenceException(this.getStartLocation() + " " + nameExp + " not found.", env); 137 } else if (notransform) { 138 throw new TemplateException(getStartLocation() + ": " + nameExp + " is not a Macro.", env); 139 } else { 140 throw new TemplateException(getStartLocation() + ": " + nameExp + " is not a Macro or Transform.", env); 141 } 142 } 143 144 public String getCanonicalForm() { 145 StringBuffer buf = new StringBuffer ("<@"); 146 buf.append(nameExp.getCanonicalForm()); 147 if (positionalArgs != null) { 148 for (int i=0; i<positionalArgs.size(); i++) { 149 Expression arg = (Expression) positionalArgs.get(i); 150 if (i!=0) { 151 buf.append(','); 152 } 153 buf.append(' '); 154 buf.append(arg.getCanonicalForm()); 155 } 156 } 157 else { 158 ArrayList keys = new ArrayList(namedArgs.keySet()); 159 Collections.sort(keys); 160 for (int i=0; i<keys.size();i++) { 161 Expression arg = (Expression) namedArgs.get(keys.get(i)); 162 buf.append(' '); 163 buf.append(keys.get(i)); 164 buf.append('='); 165 buf.append(arg.getCanonicalForm()); 166 } 167 } 168 if (nestedBlock == null) { 169 buf.append("/>"); 170 } 171 else { 172 buf.append('>'); 173 buf.append(nestedBlock.getCanonicalForm()); 174 buf.append("</@"); 175 if (nameExp instanceof Identifier || (nameExp instanceof Dot && ((Dot) nameExp).onlyHasIdentifiers())) { 176 buf.append(nameExp); 177 } 178 buf.append('>'); 179 } 180 return buf.toString(); 181 } 182 183 public String getDescription() { 184 return "user-directive " + nameExp; 185 } 186 196 } 197 | Popular Tags |