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