d37f95f270337980cf1f4747ef1628a84b306bb0
[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
43 import mir.generator.tal.interfaces.TALExpressionParser;
44 import mir.generator.tal.template.CompositeTemplateNode;
45 import mir.generator.tal.template.PlainTextTemplateNode;
46 import mir.generator.tal.template.TALTemplate;
47 import mir.generator.tal.template.TALTemplateNodeLibrary;
48 import mir.generator.tal.template.TemplateNode;
49 import mir.util.HTMLRoutines;
50 import mir.util.xml.SectionHandler;
51 import mir.util.xml.XMLName;
52 import mir.util.xml.XMLParserEngine;
53 import mir.util.xml.XMLParserExc;
54 import mir.util.xml.XMLParserFailure;
55 import mir.util.xml.XMLReaderTool;
56
57 // TODO: add a templatelibrary repository and remove dependency of TALTemplateEngine
58
59 public class TALTemplateParser {
60   private TALTemplateEngine engine;
61
62   //private static final String TAL_PREFIX = "tal";
63   public TALTemplateParser(TALTemplateEngine anEngine) {
64     engine = anEngine;
65   }
66
67   public TALTemplate parse(String aData, TALExpressionParser aParser) throws TALExc, TALFailure {
68     return parse(new StringReader(aData), aParser);
69   }
70
71   public TALTemplate parse(File aFile, TALExpressionParser aParser) throws TALExc, TALFailure {
72     try {
73       return parse(new BufferedInputStream(new FileInputStream(aFile), 1024*128), aParser);
74     }
75     catch (FileNotFoundException e) {
76       throw new TALFailure(e);
77     }
78   }
79   public TALTemplate parse(InputStream anInputStream, TALExpressionParser aParser) throws TALExc, TALFailure {
80     return parse(new InputStreamReader(anInputStream), aParser);
81   }
82
83   public TALTemplate parse(Reader aReader, TALExpressionParser aParser) throws TALExc, TALFailure {
84     TALHandler handler = new TALHandler(aParser);
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 TALTemplate(aParser, handler.getNode());
94   }
95
96   protected class TALHandler implements SectionHandler {
97     private CompositeTemplateNode compositeNode;
98     private StringBuffer data;
99     private TALExpressionParser parser;
100     private String currentTag;
101     private TALTemplateNodeLibrary library;
102     private XMLName tag;
103     private Map attributes;
104
105     public TALHandler(TALExpressionParser aParser) {
106       parser = aParser;
107       data = new StringBuffer();
108       compositeNode = new CompositeTemplateNode();
109     }
110
111     private void flushData() {
112       if (data.length()!=0) {
113         compositeNode.appendSubNode(new PlainTextTemplateNode(data.toString()));
114         data.delete(0, data.length());
115       }
116     }
117
118     public void extra(String anExtraData) throws XMLParserExc, XMLParserFailure {
119       appendCode(anExtraData);
120     }
121
122     public TALTemplateNodeLibrary findLibrary(XMLName aName) {
123       TALTemplateNodeLibrary result = null;
124
125       if (aName.getNamespaceURI()!=null) {
126         result = engine.getLibraryForUrl(aName.getNamespaceURI());
127       }
128
129       if ((result == null) && (aName.getPrefix()!=null) && (aName.getPrefix().length()>0)) {
130         result = engine.getLibraryForPrefix(aName.getPrefix());
131       }
132
133       return result;
134     }
135
136     public SectionHandler startElement(mir.util.xml.XMLName aTag, Map anAttributes) throws XMLParserExc {
137       library = findLibrary(aTag);
138
139       Iterator i = anAttributes.keySet().iterator();
140       while (library==null && i.hasNext()) {
141         library=findLibrary((XMLName) i.next());
142       }
143
144       currentTag = XMLReaderTool.normalizeXMLName(aTag);
145
146       if (library == null) {
147         appendCode("<"+currentTag);
148         i = anAttributes.entrySet().iterator();
149
150         while (i.hasNext()) {
151           Map.Entry entry = (Map.Entry) i.next();
152
153           appendCode(" "+ XMLReaderTool.normalizeXMLName((XMLName) entry.getKey()));
154           appendCode("=\"");
155           appendText((String) entry.getValue());
156           appendCode("\"");
157         }
158         appendCode(">");
159       }
160       else {
161         tag = aTag;
162         attributes = anAttributes;
163       }
164
165       return new TALHandler(parser);
166     };
167
168     public void endElement(mir.util.xml.SectionHandler aHandler) throws XMLParserExc {
169       if (library == null) {
170         appendSubNode(((TALHandler) aHandler).getNode());
171         appendCode("</"+currentTag+">");
172       }
173       else {
174         appendSubNode(library.constructTemplateNode(parser, tag, attributes, ((TALHandler) aHandler).getNode()));
175         tag = null;
176         attributes = null;
177       }
178     };
179
180     protected void appendSubNode(TemplateNode aNode) {
181       flushData();
182
183       compositeNode.appendSubNode(aNode);
184     }
185
186     protected void appendCode(String aCode) {
187       data.append(aCode);
188     }
189
190     protected void appendText(String aText) {
191       data.append(HTMLRoutines.encodeHTML(aText));
192     }
193
194     public void finishSection() throws XMLParserExc {
195       flushData();
196     }
197
198     public TemplateNode getNode() {
199       return compositeNode;
200     }
201
202     public void characters(String aCharacters) throws XMLParserExc {
203       appendText(aCharacters);
204     }
205
206     public void startSection() throws XMLParserExc, XMLParserFailure {
207     }
208   }
209 }