2 * Copyright (C) 2001, 2002 The Mir-coders group
4 * This file is part of Mir.
6 * Mir is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Mir is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Mir; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * In addition, as a special exception, The Mir-coders gives permission to link
21 * the code of this program with any library licensed under the Apache Software License,
22 * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23 * (or with modified versions of the above that use the same license as the above),
24 * and distribute linked combinations including the two. You must obey the
25 * GNU General Public License in all respects for all of the code used other than
26 * the above mentioned libraries. If you modify this file, you may extend this
27 * exception to your version of the file, but you are not obligated to do so.
28 * If you do not wish to do so, delete this exception statement from your version.
30 package mir.generator.tal.template;
33 import java.util.Iterator;
34 import java.util.List;
35 import java.util.HashMap;
37 import mir.generator.tal.interfaces.TALExpressionParser;
38 import mir.generator.tal.interfaces.TALLogger;
39 import mir.util.xml.XMLName;
40 import mir.util.xml.XMLParserExc;
41 import mir.util.xml.XMLReaderTool;
42 import mir.util.StringRoutines;
43 import mir.util.HTMLRoutines;
45 public class MacroTemplateNodeLibrary implements TemplateNodeLibrary {
47 private static final String DEFINE_MACRO_ATTRIBUTE = "define-macro";
48 private static final String USE_MACRO_ATTRIBUTE = "use-macro";
49 private static final String DEFINE_SLOT_ATTRIBUTE = "define-slot";
50 private static final String FILL_SLOT_ATTRIBUTE = "fill-macro";
52 public static final String MACRO_DEFINITIONS_KEY = "$" + MacroTemplateNodeLibrary.class.getName() + "$macro_definitions";
53 public static final String ORPHANED_SLOTS_KEY = "$" + MacroTemplateNodeLibrary.class.getName() + "$macro_definitions";
55 private String prefix;
59 private boolean isOurTag(XMLName aName) {
60 return prefix.equals(aName.getPrefix()) || uri.equals(aName.getNamespaceURI());
63 public MacroTemplateNodeLibrary(String aPrefix, String aUri) {
68 public TemplateNode constructTemplateNode(TALExpressionParser anExpressionParser, XMLName aTag, Map anAttributes,
69 TemplateNode aChildTemplateNode, Map aTemplateContext) throws XMLParserExc {
71 StringBuffer prefix = new StringBuffer();
72 boolean useSurroundingTag = !(isOurTag(aTag));
74 prefix.append("<").append(XMLReaderTool.normalizeXMLName(aTag));
75 String suffix = "</"+XMLReaderTool.normalizeXMLName(aTag)+">";
77 String macroDefinition = null;
78 String slotDefinition = null;
79 String slotFill = null;
80 Object macroCallExpression = null;
82 Iterator i = anAttributes.entrySet().iterator();
85 Map.Entry entry = (Map.Entry) i.next();
86 XMLName name = (XMLName) entry.getKey();
88 if (!isOurTag(name)) {
89 prefix.append(" ").append(XMLReaderTool.normalizeXMLName(name));
90 prefix.append("=\"").append(HTMLRoutines.encodeHTML( (String) entry.getValue())).append('"');
93 if (name.getLocalName().equalsIgnoreCase(DEFINE_MACRO_ATTRIBUTE)) {
94 macroDefinition = (String) entry.getValue();
96 else if (name.getLocalName().equalsIgnoreCase(USE_MACRO_ATTRIBUTE)) {
97 macroCallExpression = anExpressionParser.preparseStringExpression((String) entry.getValue());
99 else if (name.getLocalName().equalsIgnoreCase(DEFINE_SLOT_ATTRIBUTE)) {
100 slotDefinition = (String) entry.getValue();
102 else if (name.getLocalName().equalsIgnoreCase(FILL_SLOT_ATTRIBUTE)) {
103 slotFill = (String) entry.getValue();
109 MacroTemplateNode result;
110 if (useSurroundingTag) {
111 result = new MacroTemplateNode(aChildTemplateNode, prefix.toString(), suffix, slotDefinition, slotFill);
114 result = new MacroTemplateNode(aChildTemplateNode, "", "", slotDefinition, slotFill);
117 if (macroCallExpression!=null) {
118 result.setMacroCall(macroCallExpression);
121 if (macroDefinition!=null) {
122 macroDefinition = macroDefinition.trim();
123 if (macroDefinition.length()==0) {
124 throw new XMLParserExc("Empty macro name");
127 Map definitions = (Map) aTemplateContext.get(MACRO_DEFINITIONS_KEY);
128 if (definitions==null) {
129 definitions=new HashMap();
130 aTemplateContext.put(MACRO_DEFINITIONS_KEY, definitions);
133 if (definitions.containsKey(macroDefinition)) {
134 throw new XMLParserExc("Duplicate macro name: " + macroDefinition);
137 definitions.put(macroDefinition, result);
139 Map slots = (Map) aTemplateContext.get(ORPHANED_SLOTS_KEY);
147 private class MacroTemplateNode implements TemplateNode {
148 private TemplateNode childNode;
149 private String prefix;
150 private String suffix;
152 private Object macroCallTemplateExpression = null;
154 private String slotDefinition;
155 private String slotFill;
157 public MacroTemplateNode(TemplateNode aChildNode, String aPrefix, String aSuffix,
158 String aSlotDefinition, String aSlotFill) {
159 childNode = aChildNode;
163 slotDefinition = aSlotDefinition;
164 slotFill = aSlotFill;
167 public void setMacroCall(Object anExpression) {
168 macroCallTemplateExpression = anExpression;
172 public void process(TALExpressionParser aParser, Object aContext, StringBuffer aDestination,
173 TALLogger aLogger, Map aTemplateContext, TemplateLibrary aLibrary) throws TemplateProcessingException {
175 if (macroCallTemplateExpression!=null) {
176 String macroPath = aParser.evaluateStringExpression(aContext, macroCallTemplateExpression);
177 List parts = StringRoutines.separateString(macroPath, "#");
178 if (parts.size()!=2) {
179 throw new TemplateProcessingException("Invalid macro path '" + macroPath + "'");
182 Template template = aLibrary.lookupTemplate((String) parts.get(0));
183 Map definitions = (Map) template.getContext().get(MACRO_DEFINITIONS_KEY);
184 if (template==null) {
185 throw new TemplateProcessingException("Cannot find template '" + (String) parts.get(0) + "'");
187 if (definitions==null || !definitions.containsKey(parts.get(1))) {
188 throw new TemplateProcessingException("No macro '"+(String) parts.get(1)+"' found in template '" + (String) parts.get(0) + "'");
191 MacroTemplateNode macro = (MacroTemplateNode) definitions.get(parts.get(1));
193 macro.process(aParser, aContext, aDestination, aLogger, aTemplateContext, aLibrary);
196 aDestination.append(prefix);
198 childNode.process(aParser, aContext, aDestination, aLogger, aTemplateContext, aLibrary);
199 aDestination.append(suffix);
203 public String getPlainText() {
204 return childNode.getPlainText();