fixed/rearranged some tal stuff
[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 \r
34 import java.util.Map;\r
35 import java.util.List;\r
36 import java.util.HashMap;\r
37 import java.util.Vector;\r
38 import java.util.Iterator;\r
39 \r
40 import mir.generator.tal.interfaces.TALExpressionParser;\r
41 import mir.generator.tal.interfaces.TALLogger;\r
42 import mir.util.HTMLRoutines;\r
43 import mir.util.StringRoutines;\r
44 import mir.util.xml.XMLName;\r
45 import mir.util.xml.XMLParserExc;\r
46 import mir.util.xml.XMLReaderTool;\r
47 \r
48 public class TALBasicTemplateNodeLibrary implements TALTemplateNodeLibrary {\r
49   private String prefix;\r
50   private String uri;\r
51 \r
52   private boolean isOurTag(XMLName aName) {\r
53     return prefix.equals(aName.getPrefix()) || uri.equals(aName.getNamespaceURI());\r
54   }\r
55 \r
56   public TALBasicTemplateNodeLibrary(String aPrefix, String aUri) {\r
57     prefix = aPrefix;\r
58     uri = aUri;\r
59   }\r
60 \r
61   private static final String CONDITION_ATTRIBUTE = "condition";\r
62   private static final String REPEAT_ATTRIBUTE = "repeat";\r
63   private static final String CONTENT_ATTRIBUTE = "content";\r
64   private static final String ERROR_ATTRIBUTE = "on-error";\r
65   private static final String REPLACE_ATTRIBUTE = "replace";\r
66   private static final String DEFINITION_ATTRIBUTE = "define";\r
67   private static final String OMITTAG_ATTRIBUTE = "omit-tag";\r
68   private static final String ATTRIBUTE_ATTRIBUTE = "attributes";\r
69 \r
70   public TemplateNode constructTemplateNode(TALExpressionParser aParser, XMLName aTag, Map anAttributes, TemplateNode aChildTemplateNode) throws XMLParserExc {\r
71     TALBasicTemplateNode result = new TALBasicTemplateNode(XMLReaderTool.normalizeXMLName(aTag));\r
72     result.setBody(aChildTemplateNode);\r
73 \r
74     if (isOurTag(aTag))\r
75       result.setOmitTag(aParser.preparseTRUE());\r
76 \r
77     Iterator i = anAttributes.entrySet().iterator();\r
78     while (i.hasNext()) {\r
79       Map.Entry entry = (Map.Entry) i.next();\r
80       XMLName name = (XMLName) entry.getKey();\r
81 \r
82       if (!isOurTag(name)) {\r
83         result.addFixedAttribute(XMLReaderTool.normalizeXMLName(name), (String) entry.getValue());\r
84       }\r
85       else {\r
86         if (name.getLocalName().equalsIgnoreCase(DEFINITION_ATTRIBUTE)) {\r
87           List definitions = StringRoutines.splitStringWithEscape((String) entry.getValue(), ';', '\\');\r
88 \r
89           Iterator j = definitions.iterator();\r
90           while (j.hasNext())\r
91           {\r
92             List parts = StringRoutines.separateString((String) j.next(), " ");\r
93 \r
94             if (parts.size()==2) {\r
95               result.addDefinition(aParser.preparseReferenceExpression((String) parts.get(0)), aParser.preparseExpression((String) parts.get(1)));\r
96             }\r
97           }\r
98         }\r
99         else if (name.getLocalName().equalsIgnoreCase(CONDITION_ATTRIBUTE)) {\r
100           result.setCondition(aParser.preparseBooleanExpression((String) entry.getValue()));\r
101         }\r
102         else if (name.getLocalName().equalsIgnoreCase(CONTENT_ATTRIBUTE)) {\r
103           result.setContent(aParser.preparseStringExpression((String) entry.getValue()));\r
104         }\r
105         else if (name.getLocalName().equalsIgnoreCase(ERROR_ATTRIBUTE)) {\r
106           result.setError(aParser.preparseStringExpression((String) entry.getValue()));\r
107         }\r
108         else if (name.getLocalName().equalsIgnoreCase(OMITTAG_ATTRIBUTE)) {\r
109           if (((String) entry.getValue()).trim().length()==0)\r
110             result.setOmitTag(aParser.preparseTRUE());\r
111           else\r
112             result.setOmitTag(aParser.preparseBooleanExpression((String) entry.getValue()));\r
113         }\r
114         else if (name.getLocalName().equalsIgnoreCase(REPLACE_ATTRIBUTE)) {\r
115           result.setOmitTag(aParser.preparseTRUE());\r
116           result.setContent(aParser.preparseStringExpression((String) entry.getValue()));\r
117         }\r
118         else if (name.getLocalName().equalsIgnoreCase(REPEAT_ATTRIBUTE)) {\r
119           List parts = StringRoutines.separateString((String) entry.getValue(), " ");\r
120 \r
121           if (parts.size()==2) {\r
122             result.setRepeat(aParser.preparseReferenceExpression((String) parts.get(0)), aParser.preparseExpression((String) parts.get(1)));\r
123           }\r
124         }\r
125         else if (name.getLocalName().equalsIgnoreCase(ATTRIBUTE_ATTRIBUTE)) {\r
126           List attributes = StringRoutines.splitStringWithEscape((String) entry.getValue(), ';', '\\');\r
127 \r
128           Iterator j = attributes.iterator();\r
129           while (j.hasNext()) {\r
130             String value = (String) j.next();\r
131             List parts = StringRoutines.separateString(value, " ");\r
132 \r
133             if (parts.size()==2) {\r
134               result.addModifiedAttribute((String) parts.get(0), aParser.preparseExpression((String) parts.get(1)));\r
135             }\r
136             else {\r
137               throw new XMLParserExc(ATTRIBUTE_ATTRIBUTE + " tag should have exactly 2 parts ("+value+")");\r
138             }\r
139           }\r
140         }\r
141       }\r
142     }\r
143 \r
144     return result;\r
145   }\r
146 \r
147   public static class TALBasicTemplateNode implements TemplateNode {\r
148     private String tag;\r
149     private Map fixedAttributes;\r
150     private Map attributeModifiers;\r
151 \r
152     private List definitions;\r
153     private Object condition;\r
154 \r
155     private Object repeatVariable;\r
156     private Object repeatExpression;\r
157     private Object contentExpression;\r
158     private Object omitTagExpression;\r
159     private Object errorExpression;\r
160 \r
161     private TemplateNode body;\r
162 \r
163     public TALBasicTemplateNode(String aTag) {\r
164       tag = aTag;\r
165 \r
166       fixedAttributes = new HashMap();\r
167       attributeModifiers = new HashMap();\r
168 \r
169       definitions = new Vector();\r
170       condition = null;\r
171 \r
172       repeatVariable = null;\r
173       repeatExpression = null;\r
174       contentExpression = null;\r
175       omitTagExpression = null;\r
176 \r
177       body = null;\r
178     }\r
179 \r
180     public void setBody(TemplateNode aBody) {\r
181       body = aBody;\r
182     }\r
183 \r
184     public void addFixedAttribute(String aKey, String aValue) {\r
185       fixedAttributes.put(aKey, aValue);\r
186     }\r
187 \r
188     public void addModifiedAttribute(String aKey, Object aValue) {\r
189       attributeModifiers.put(aKey, aValue);\r
190     }\r
191 \r
192     public void addDefinition(Object aKey, Object aValue) {\r
193       definitions.add(new Definition(aKey, aValue));\r
194     }\r
195 \r
196     public void setCondition(Object aCondition) {\r
197       condition = aCondition;\r
198     }\r
199 \r
200     public void setRepeat(Object aRepeatVariable, Object aRepeatExpression) {\r
201       repeatVariable = aRepeatVariable;\r
202       repeatExpression = aRepeatExpression;\r
203     }\r
204 \r
205     public void setContent(Object aContentExpression) {\r
206       contentExpression = aContentExpression;\r
207     }\r
208 \r
209     public void setOmitTag(Object anOmitTagExpression) {\r
210       omitTagExpression = anOmitTagExpression;\r
211     }\r
212 \r
213     public void setError(Object anErrorExpression) {\r
214       errorExpression = anErrorExpression;\r
215     }\r
216 \r
217     public static class Definition {\r
218       private Object variable;\r
219       private Object expression;\r
220 \r
221       public Definition(Object aVariable, Object anExpression) {\r
222         variable = aVariable;\r
223         expression = anExpression;\r
224       }\r
225 \r
226       public Object getVariable() {\r
227         return variable;\r
228       }\r
229 \r
230       public Object getExpression() {\r
231         return expression;\r
232       }\r
233     }\r
234 \r
235     public void process(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, TALLogger aLogger) throws TemplateProcessingException {\r
236       Iterator i;\r
237 \r
238         i = definitions.iterator();\r
239         while (i.hasNext()) {\r
240           Definition d = (Definition) i.next();\r
241           aParser.processAssignment(aContext, d.getVariable(), d.getExpression());\r
242         }\r
243 \r
244         if (condition == null || aParser.evaluateBooleanExpression(aContext, condition)) {\r
245           if (repeatExpression != null) {\r
246             i = aParser.evaluateListExpression(aContext, repeatExpression);\r
247 \r
248             while (i.hasNext()) {\r
249               aParser.processDirectAssignment(aContext, repeatVariable, i.next());\r
250               innerProcess(aParser, aContext, aDestination, aLogger);\r
251             }\r
252           }\r
253           else {\r
254             innerProcess(aParser, aContext, aDestination, aLogger);\r
255           }\r
256         }\r
257     };\r
258 \r
259     private void innerProcess(TALExpressionParser aParser, Object aContext, StringBuffer aDestination, TALLogger aLogger)\r
260        throws TemplateProcessingException\r
261     {\r
262       boolean omitTag = false;\r
263       if (omitTagExpression != null)\r
264         omitTag = aParser.evaluateBooleanExpression(aContext, omitTagExpression);\r
265 \r
266       if (!omitTag) {\r
267         Map generatedAttributes = new HashMap(fixedAttributes);\r
268 \r
269         Iterator i = attributeModifiers.entrySet().iterator();\r
270         while (i.hasNext()) {\r
271           Map.Entry entry = (Map.Entry) i.next();\r
272 \r
273           generatedAttributes.put(entry.getKey(), aParser.evaluateStringExpression(aContext, entry.getValue()));\r
274         }\r
275 \r
276         aDestination.append("<");\r
277         aDestination.append(tag);\r
278 \r
279         i = generatedAttributes.entrySet().iterator();\r
280         while (i.hasNext()) {\r
281           Map.Entry entry = (Map.Entry) i.next();\r
282           aDestination.append(" ");\r
283           aDestination.append(entry.getKey());\r
284           aDestination.append("=");\r
285           aDestination.append("\"");\r
286           aDestination.append(HTMLRoutines.encodeHTML( (String) entry.getValue()));\r
287           aDestination.append("\"");\r
288         }\r
289         aDestination.append(">");\r
290       }\r
291 \r
292       StringBuffer destination = aDestination;\r
293       if (errorExpression != null) {\r
294         destination = new StringBuffer();\r
295       }\r
296       try {\r
297         if (contentExpression != null) {\r
298           destination.append(aParser.evaluateStringExpression(aContext, contentExpression));\r
299         }\r
300         else {\r
301           if (body != null)\r
302             body.process(aParser, aContext, destination, aLogger);\r
303         }\r
304       }\r
305       catch (Throwable t) {\r
306         if (!(t instanceof TemplateProcessingException))\r
307           aLogger.error("TALTemplate.TALBasicTemplateNode.processs", "exception occurred: " + t.toString());\r
308         if (errorExpression != null) {\r
309           try {\r
310             destination.delete(0, destination.length());\r
311 \r
312             aParser.processPseudoAssignment(aContext, "exception", t);\r
313             destination.append(aParser.evaluateStringExpression(aContext, errorExpression));\r
314           }\r
315           catch (Throwable s) {\r
316           }\r
317         }\r
318         else {\r
319           throw new TemplateProcessingException(t);\r
320         }\r
321       }\r
322       finally {\r
323         if (errorExpression != null) {\r
324           aDestination.append(destination);\r
325         }\r
326       }\r
327       if (!omitTag) {\r
328         aDestination.append("</");\r
329         aDestination.append(tag);\r
330         aDestination.append(">");\r
331       }\r
332     }\r
333   }\r
334 }\r