ff1596f5a693a89734449ff72eede756850a93f1
[mir.git] / source / mir / generator / tal / TALTemplateParser.java
1 /*
2  * Copyright (C) 2001, 2002 The Mir-coders group
3  *
4  * This file is part of Mir.
5  *
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.
10  *
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.
15  *
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
19  *
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.
29  */
30 package mir.generator.tal;
31
32 import java.io.BufferedInputStream;
33 import java.io.File;
34 import java.io.FileInputStream;
35 import java.io.FileNotFoundException;
36 import java.io.InputStream;
37 import java.io.InputStreamReader;
38 import java.io.Reader;
39 import java.io.StringReader;
40 import java.util.Iterator;
41 import java.util.Map;
42 import java.util.HashMap;
43
44 import mir.generator.tal.interfaces.TALExpressionParser;
45 import mir.generator.tal.template.CompositeTemplateNode;
46 import mir.generator.tal.template.PlainTextTemplateNode;
47 import mir.generator.tal.template.Template;
48 import mir.generator.tal.template.TemplateNodeLibrary;
49 import mir.generator.tal.template.TemplateNode;
50 import mir.generator.tal.template.TemplateNodeLibraryRegistry;
51 import mir.util.HTMLRoutines;
52 import mir.util.xml.SectionHandler;
53 import mir.util.xml.XMLName;
54 import mir.util.xml.XMLParserEngine;
55 import mir.util.xml.XMLParserExc;
56 import mir.util.xml.XMLParserFailure;
57 import mir.util.xml.XMLReaderTool;
58
59 public class TALTemplateParser {
60   private TemplateNodeLibraryRegistry registry;
61
62   public TALTemplateParser(TemplateNodeLibraryRegistry aRegistry) {
63     registry = aRegistry;
64   }
65
66   public Template parse(String aData, TALExpressionParser aParser) throws TALExc, TALFailure {
67     return parse(new StringReader(aData), aParser);
68   }
69
70   public Template parse(File aFile, TALExpressionParser aParser) throws TALExc, TALFailure {
71     try {
72       return parse(new BufferedInputStream(new FileInputStream(aFile), 1024*128), aParser);
73     }
74     catch (FileNotFoundException e) {
75       throw new TALFailure(e);
76     }
77   }
78   public Template parse(InputStream anInputStream, TALExpressionParser aParser) throws TALExc, TALFailure {
79     return parse(new InputStreamReader(anInputStream), aParser);
80   }
81
82   public Template parse(Reader aReader, TALExpressionParser aParser) throws TALExc, TALFailure {
83     Map templateContext = new HashMap();
84     TALHandler handler = new TALHandler(aParser, templateContext);
85
86     try {
87       XMLParserEngine.getInstance().parse("html", aReader, handler);
88     }
89     catch (XMLParserExc e) {
90       throw new TALFailure(e);
91     }
92
93     return new Template(aParser, handler.getNode(), templateContext);
94   }
95
96   protected class TALHandler implements SectionHandler {
97     private CompositeTemplateNode compositeNode;
98     private StringBuffer data;
99     private StringBuffer plainData;
100     private TALExpressionParser parser;
101     private String currentTag;
102     private TemplateNodeLibrary library;
103     private XMLName tag;
104     private Map attributes;
105     private Map templateContext;
106
107     public TALHandler(TALExpressionParser aParser, Map aTemplateContext) {
108       parser = aParser;
109       data = new StringBuffer();
110       plainData = new StringBuffer();
111       compositeNode = new CompositeTemplateNode();
112       templateContext = aTemplateContext;
113     }
114
115     private void flushData() {
116       if (data.length()!=0) {
117         compositeNode.appendSubNode(new PlainTextTemplateNode(data.toString(), plainData.toString()));
118         data.delete(0, data.length());
119         plainData.delete(0, plainData.length());
120       }
121     }
122
123     public void extra(String anExtraData) throws XMLParserExc, XMLParserFailure {
124       appendCode(anExtraData);
125     }
126
127     public TemplateNodeLibrary findLibrary(XMLName aName) {
128       TemplateNodeLibrary result = null;
129
130       if (aName.getNamespaceURI()!=null) {
131         result = registry.findLibraryForUrl(aName.getNamespaceURI());
132       }
133
134       if ((result == null) && (aName.getPrefix()!=null) && (aName.getPrefix().length()>0)) {
135         result = registry.findLibraryForPrefix(aName.getPrefix());
136       }
137
138       return result;
139     }
140
141     public SectionHandler startElement(mir.util.xml.XMLName aTag, Map anAttributes) throws XMLParserExc {
142       library = findLibrary(aTag);
143
144       Iterator i = anAttributes.keySet().iterator();
145       while (library==null && i.hasNext()) {
146         library=findLibrary((XMLName) i.next());
147       }
148
149       currentTag = XMLReaderTool.normalizeXMLName(aTag);
150
151       if (library == null) {
152         appendCode("<"+currentTag);
153         i = anAttributes.entrySet().iterator();
154
155         while (i.hasNext()) {
156           Map.Entry entry = (Map.Entry) i.next();
157
158           appendCode(" "+ XMLReaderTool.normalizeXMLName((XMLName) entry.getKey()));
159           appendCode("=\"");
160           appendText((String) entry.getValue());
161           appendCode("\"");
162         }
163       }
164       else {
165         tag = aTag;
166         attributes = anAttributes;
167       }
168
169       return new TALHandler(parser, templateContext);
170     };
171
172     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
173       if (library == null) {
174         TemplateNode subNode = ((TALHandler) aHandler).getNode();
175         if (subNode instanceof CompositeTemplateNode &&
176             ((CompositeTemplateNode) subNode).isEmpty()) {
177           appendCode(" />");
178         }
179         else {
180           appendCode(">");
181           appendSubNode(subNode);
182           appendCode("</"+currentTag+">");
183         }
184       }
185       else {
186         appendSubNode(
187             library.constructTemplateNode(parser, tag, attributes, ((TALHandler) aHandler).getNode(), templateContext));
188         tag = null;
189         attributes = null;
190       }
191     };
192
193     protected void appendSubNode(TemplateNode aNode) {
194       flushData();
195
196       compositeNode.appendSubNode(aNode);
197     }
198
199     protected void appendCode(String aCode) {
200       data.append(aCode);
201     }
202
203     protected void appendText(String aText) {
204       data.append(HTMLRoutines.encodeHTML(aText));
205       plainData.append(aText);
206     }
207
208     public void finishSection() throws XMLParserExc {
209       flushData();
210     }
211
212     public TemplateNode getNode() {
213       return compositeNode;
214     }
215
216     public void characters(String aCharacters) throws XMLParserExc {
217       appendText(aCharacters);
218     }
219
220     public void startSection() throws XMLParserExc, XMLParserFailure {
221     }
222   }
223 }