whoops
[mir.git] / source / mir / generator / tal / template / TALBasicTemplateNodeLibrary.java
1 /*\r
2  * Copyright (C) 2001, 2002 The Mir-coders group\r
3  *\r
4  * This file is part of Mir.\r
5  *\r
6  * Mir is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 2 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Mir is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with Mir; if not, write to the Free Software\r
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19  *\r
20  * In addition, as a special exception, The Mir-coders gives permission to link\r
21  * the code of this program with  any library licensed under the Apache Software License,\r
22  * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library\r
23  * (or with modified versions of the above that use the same license as the above),\r
24  * and distribute linked combinations including the two.  You must obey the\r
25  * GNU General Public License in all respects for all of the code used other than\r
26  * the above mentioned libraries.  If you modify this file, you may extend this\r
27  * exception to your version of the file, but you are not obligated to do so.\r
28  * If you do not wish to do so, delete this exception statement from your version.\r
29  */\r
30 \r
31 package mir.generator.tal.template;\r
32 \r
33 import java.util.Map;\r
34 import java.util.List;\r
35 import java.util.HashMap;\r
36 import java.util.Vector;\r
37 import java.util.Iterator;\r
38 \r
39 import mir.generator.tal.interfaces.TALExpressionParser;\r
40 import mir.generator.tal.interfaces.TALLogger;\r
41 import mir.util.HTMLRoutines;\r
42 import mir.util.StringRoutines;\r
43 import mir.util.xml.XMLName;\r
44 import mir.util.xml.XMLParserExc;\r
45 import mir.util.xml.XMLReaderTool;\r
46 \r
47 public class TALBasicTemplateNodeLibrary implements TALTemplateNodeLibrary {\r
48   private String prefix;\r
49   private String uri;\r
50 \r
51   private boolean isOurTag(XMLName aName) {\r
52     return prefix.equals(aName.getPrefix()) || uri.equals(aName.getNamespaceURI());\r
53   }\r
54 \r
55   public TALBasicTemplateNodeLibrary(String aPrefix, String aUri) {\r
56     prefix = aPrefix;\r
57     uri = aUri;\r
58   }\r
59 \r
60   private static final String CONDITION_ATTRIBUTE = "condition";\r
61   private static final String REPEAT_ATTRIBUTE = "repeat";\r
62   private static final String CONTENT_ATTRIBUTE = "content";\r
63   private static final String ERROR_ATTRIBUTE = "on-error";\r
64   private static final String REPLACE_ATTRIBUTE = "replace";\r
65   private static final String DEFINITION_ATTRIBUTE = "define";\r
66   private static final String OMITTAG_ATTRIBUTE = "omit-tag";\r
67   private static final String ATTRIBUTE_ATTRIBUTE = "attributes";\r
68 \r
69   public TemplateNode constructTemplateNode(TALExpressionParser aParser, XMLName aTag, Map anAttributes, TemplateNode aChildTemplateNode) throws XMLParserExc {\r
70     TALBasicTemplateNode result = new TALBasicTemplateNode(XMLReaderTool.normalizeXMLName(aTag));\r
71     result.setBody(aChildTemplateNode);\r
72 \r
73     if (isOurTag(aTag))\r
74       result.setOmitTag(aParser.preparseTRUE());\r
75 \r
76     Iterator i = anAttributes.entrySet().iterator();\r
77     while (i.hasNext()) {\r
78       Map.Entry entry = (Map.Entry) i.next();\r
79       XMLName name = (XMLName) entry.getKey();\r
80 \r
81       if (!isOurTag(name)) {\r
82         result.addFixedAttribute(XMLReaderTool.normalizeXMLName(name), (String) entry.getValue());\r
83       }\r
84       else {\r
85         if (name.getLocalName().equalsIgnoreCase(DEFINITION_ATTRIBUTE)) {\r
86           List definitions = StringRoutines.splitStringWithEscape((String) entry.getValue(), ';', '\\');\r
87 \r
88           Iterator j = definitions.iterator();\r
89           while (j.hasNext())\r
90           {\r
91             List parts = StringRoutines.separateString((String) j.next(), " ");\r
92 \r
93             if (parts.size()==2) {\r
94               result.addDefinition(aParser.preparseReferenceExpression((String) parts.get(0)), aParser.preparseExpression((String) parts.get(1)));\r
95             }\r
96           }\r
97         }\r
98         else if (name.getLocalName().equalsIgnoreCase(CONDITION_ATTRIBUTE)) {\r
99           result.setCondition(aParser.preparseBooleanExpression((String) entry.getValue()));\r
100         }\r
101         else if (name.getLocalName().equalsIgnoreCase(CONTENT_ATTRIBUTE)) {\r
102           result.setContent(aParser.preparseStringExpression((String) entry.getValue()));\r
103         }\r
104         else if (name.getLocalName().equalsIgnoreCase(ERROR_ATTRIBUTE)) {\r
105           result.setError(aParser.preparseStringExpression((String) entry.getValue()));\r
106         }\r
107         else if (name.getLocalName().equalsIgnoreCase(OMITTAG_ATTRIBUTE)) {\r
108           if (((String) entry.getValue()).trim().length()==0)\r
109             result.setOmitTag(aParser.preparseTRUE());\r
110           else\r
111             result.setOmitTag(aParser.preparseBooleanExpression((String) entry.getValue()));\r
112         }\r
113         else if (name.getLocalName().equalsIgnoreCase(REPLACE_ATTRIBUTE)) {\r
114           result.setOmitTag(aParser.preparseTRUE());\r
115           result.setContent(aParser.preparseStringExpression((String) entry.getValue()));\r
116         }\r
117         else if (name.getLocalName().equalsIgnoreCase(REPEAT_ATTRIBUTE)) {\r
118           List parts = StringRoutines.separateString((String) entry.getValue(), " ");\r
119 \r
120           if (parts.size()==2) {\r
121             result.setRepeat(aParser.preparseReferenceExpression((String) parts.get(0)), aParser.preparseExpression((String) parts.get(1)));\r
122           }\r
123         }\r
124         else if (name.getLocalName().equalsIgnoreCase(ATTRIBUTE_ATTRIBUTE)) {\r
125           List attributes = StringRoutines.splitStringWithEscape((String) entry.getValue(), ';', '\\');\r
126 \r
127           Iterator j = attributes.iterator();\r
128           while (j.hasNext()) {\r
129             String value = (String) j.next();\r
130             List parts = StringRoutines.separateString(value, " ");\r
131 \r
132             if (parts.size()==2) {\r
133               result.addModifiedAttribute((String) parts.get(0), aParser.preparseExpression((String) parts.get(1)));\r
134             }\r
135             else {\r
136               throw new XMLParserExc(ATTRIBUTE_ATTRIBUTE + " tag should have exactly 2 parts ("+value+")");\r
137             }\r
138           }\r
139         }\r
140       }\r
141     }\r
142 \r
143     return result;\r
144   }\r
145 \r
146   public static class TALBasicTemplateNode implements TemplateNode {\r
147     private String tag;\r
148     private Map fixedAttributes;\r
149     private Map attributeModifiers;\r
150 \r
151     private List definitions;\r
152     private Object condition;\r
153 \r
154     private Object repeatVariable;\r
155     private Object repeatExpression;\r
156     private Object contentExpression;\r
157     private Object omitTagExpression;\r
158     private Object errorExpression;\r
159 \r
160     private TemplateNode body;\r
161 \r
162     public TALBasicTemplateNode(String aTag) {\r
163       tag = aTag;\r
164 \r
165       fixedAttributes = new HashMap();\r
166       attributeModifiers = new HashMap();\r
167 \r
168       definitions = new Vector();\r
169       condition = null;\r
170 \r
171       repeatVariable = null;\r
172       repeatExpression = null;\r
173       contentExpression = null;\r
174       omitTagExpression = null;\r
175 \r
176       body = null;\r
177     }\r
178 \r
179     public void setBody(TemplateNode aBody) {\r
180       body = aBody;\r
181     }\r
182 \r
183     public void addFixedAttribute(String aKey, String aValue) {\r
184       fixedAttributes.put(aKey, aValue);\r
185     }\r
186 \r
187     public void addModifiedAttribute(String aKey, Object aValue) {\r
188       attributeModifiers.put(aKey, aValue);\r
189     }\r
190 \r
191     public void addDefinition(Object aKey, Object aValue) {\r
192       definitions.add(new Definition(aKey, aValue));\r
193     }\r
194 \r
195     public void setCondition(Object aCondition) {\r
196       condition = aCondition;\r
197     }\r
198 \r
199     public void setRepeat(Object aRepeatVariable, Object aRepeatExpression) {\r
200       repeatVariable = aRepeatVariable;\r
201       repeatExpression = aRepeatExpression;\r
202     }\r
203 \r
204     public void setContent(Object aContentExpression) {\r
205       contentExpression = aContentExpression;\r
206     }\r
207 \r
208     public void setOmitTag(Object anOmitTagExpression) {\r
209       omitTagExpression = anOmitTagExpression;\r
210     }\r
211 \r
212     public void setError(Object anErrorExpression) {\r
213       errorExpression = anErrorExpression;\r
214     }\r
215 \r
216     public static class Definition {\r
217       private Object variable;\r
218       private Object expression;\r
219 \r
220       public Definition(Object aVariable, Object anExpression) {\r
221         variable = aVariable;\r
222         expression = anExpression;\r
223       }\r
224 \r
225       public Object getVariable() {\r
226         return variable;\r
227       }\r
228 \r
229       public Object getExpression() {\r
230         return expression;\r
231       }\r
232     }\r
233 \r
234     public void process(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, TALLogger aLogger) throws TemplateProcessingException {\r
235       if (errorExpression != null) {\r
236         StringBuffer destination = new StringBuffer();\r
237 \r
238         try {\r
239           outerProcess(aParser, aContext, aDestination, aLogger);\r
240         }\r
241         catch (Throwable t) {\r
242           try {\r
243             destination.delete(0, destination.length());\r
244             aParser.processPseudoAssignment(aContext, "exception", t);\r
245             destination.append(aParser.evaluateStringExpression(aContext, errorExpression));\r
246           }\r
247           catch (Throwable s) {\r
248             throw new TemplateProcessingException(s);\r
249           }\r
250         }\r
251         finally {\r
252           aDestination.append(destination);\r
253         }\r
254       }\r
255       else {\r
256         outerProcess(aParser, aContext, aDestination, aLogger);\r
257       }\r
258     }\r
259 \r
260     public void outerProcess(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, TALLogger aLogger) throws TemplateProcessingException {\r
261       Iterator i;\r
262 \r
263       i = definitions.iterator();\r
264       while (i.hasNext()) {\r
265         Definition d = (Definition) i.next();\r
266         aParser.processAssignment(aContext, d.getVariable(), d.getExpression());\r
267       }\r
268 \r
269       if (condition == null || aParser.evaluateBooleanExpression(aContext, condition)) {\r
270         if (repeatExpression != null) {\r
271           i = aParser.evaluateListExpression(aContext, repeatExpression);\r
272 \r
273           while (i.hasNext()) {\r
274             aParser.processDirectAssignment(aContext, repeatVariable, i.next());\r
275             innerProcess(aParser, aContext, aDestination, aLogger);\r
276           }\r
277         }\r
278         else {\r
279           innerProcess(aParser, aContext, aDestination, aLogger);\r
280         }\r
281       }\r
282     };\r
283 \r
284     private void innerProcess(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, TALLogger aLogger)\r
285         throws TemplateProcessingException {\r
286 \r
287       boolean omitTag = false;\r
288 \r
289       if (omitTagExpression != null)\r
290         omitTag = aParser.evaluateBooleanExpression(aContext, omitTagExpression);\r
291 \r
292       if (!omitTag) {\r
293         Map generatedAttributes = new HashMap(fixedAttributes);\r
294 \r
295         Iterator i = attributeModifiers.entrySet().iterator();\r
296         while (i.hasNext()) {\r
297           Map.Entry entry = (Map.Entry) i.next();\r
298 \r
299           generatedAttributes.put(entry.getKey(), aParser.evaluateStringExpression(aContext, entry.getValue()));\r
300         }\r
301 \r
302         aDestination.append("<");\r
303         aDestination.append(tag);\r
304 \r
305         i = generatedAttributes.entrySet().iterator();\r
306         while (i.hasNext()) {\r
307           Map.Entry entry = (Map.Entry) i.next();\r
308           aDestination.append(" ");\r
309           aDestination.append(entry.getKey());\r
310           aDestination.append("=");\r
311           aDestination.append("\"");\r
312           aDestination.append(HTMLRoutines.encodeHTML( (String) entry.getValue()));\r
313           aDestination.append("\"");\r
314         }\r
315         aDestination.append(">");\r
316       }\r
317 \r
318       if (contentExpression != null) {\r
319         aDestination.append(aParser.evaluateStringExpression(aContext, contentExpression));\r
320       }\r
321       else {\r
322         if (body != null) {\r
323           body.process(aParser, aContext, aDestination, aLogger);\r
324         }\r
325       }\r
326       if (!omitTag) {\r
327         aDestination.append("</");\r
328         aDestination.append(tag);\r
329         aDestination.append(">");\r
330       }\r
331     }\r
332   }\r
333 }\r