001: /*
002: * $Id: TemplateParser.java,v 1.14 2002/09/16 08:05:06 jkl Exp $
003: *
004: * Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
005: *
006: * Use is subject to license terms, as defined in
007: * Anvil Sofware License, Version 1.1. See LICENSE
008: * file, or http://njet.org/license-1.1.txt
009: */
010: package anvil.script.parser;
011:
012: import java.io.IOException;
013: import java.io.InputStream;
014: import java.net.URL;
015: import java.util.Enumeration;
016:
017: import anvil.java.io.GenericInputStream;
018: import anvil.ErrorListener;
019: import anvil.ErrorListenerImpl;
020: import anvil.ForgingException;
021: import anvil.Location;
022: import anvil.parser.DocumentHandler;
023: import anvil.parser.InputSource;
024: import anvil.parser.Locator;
025: import anvil.parser.Parser;
026: import anvil.parser.Tag;
027: import anvil.script.ModuleEnvelope;
028: import anvil.script.statements.ModuleStatement;
029: import anvil.script.statements.Statement;
030:
031: /**
032: * class TemplateParser
033: *
034: * @author: Jani Lehtimäki
035: */
036: public class TemplateParser extends Statement implements
037: DocumentHandler, ErrorListener {
038:
039: private ModuleEnvelope _envelope;
040: private String _namespace;
041: private URL _url;
042: private InputStream _input;
043: private ErrorListener _errorListener = null;
044: private Locator _locator = null;
045: private Statement _current = null;
046: private ModuleStatement _script = null;
047: private String _document = null;
048:
049: public TemplateParser(ModuleEnvelope envelope, String namespace,
050: URL url, byte[] content) {
051: super (null, null);
052: _envelope = envelope;
053: _namespace = namespace;
054: _url = url;
055: _input = new GenericInputStream(content);
056: }
057:
058: public String name() {
059: return "document";
060: }
061:
062: public int typeOf() {
063: return Statement.ST_DOCUMENT;
064: }
065:
066: public boolean hasEnd() {
067: return true;
068: }
069:
070: public ModuleEnvelope getEnvelope() {
071: return _envelope;
072: }
073:
074: public Location getLocation() {
075: return _locator.getLocation();
076: }
077:
078: public String getDocument() {
079: return _document;
080: }
081:
082: public void setDocumentLocator(Locator locator) {
083: _locator = locator;
084: }
085:
086: public void pop() {
087: if (_current != null) {
088: _current = _current.getParentStatement();
089: if (_current != null
090: && _current.typeOf() == ST_IMPLICIT_BLOCK) {
091: _current = _current.getParentStatement();
092: }
093: } else {
094: _current = null;
095: }
096: }
097:
098: public void push(Statement stmt) {
099: _current = stmt;
100: }
101:
102: public Statement peek() {
103: return _current;
104: }
105:
106: public void startDocument() {
107: push(this );
108: }
109:
110: public void endDocument() {
111: Statement stmt = _current;
112: while (stmt != null && stmt != this ) {
113: error(stmt.getLocation(), "Unexpected end of file, "
114: + stmt.name() + " open");
115: stmt = stmt.getParentStatement();
116: }
117: }
118:
119: public void handleCharacters(String characters) {
120: Statement statement = peek();
121: if (statement != null) {
122: statement.onCharacters(this , characters);
123: }
124: }
125:
126: public void handleComment(String characters) {
127: if (characters.startsWith("--/**")
128: && characters.endsWith("*/--")) {
129: _document = characters
130: .substring(5, characters.length() - 4);
131: } else {
132: _document = null;
133: Statement statement = peek();
134: if (statement != null) {
135: statement.onCharacters(this , "<!" + characters + '>');
136: }
137: }
138: }
139:
140: public void handleTag(Tag tag) {
141: int type = ST_INVALID;
142: String ns = tag.getNamespace();
143:
144: if (_namespace != null) {
145:
146: if (ns == null) {
147: type = ST_TAG;
148: } else {
149: if (ns.equals(_namespace)) {
150: type = Statement.getTagId(tag);
151: if (type == ST_INVALID) {
152: error(getLocation(), "Unrecognized tag: " + tag);
153: return;
154: }
155: } else {
156: type = ST_TAG;
157: }
158: }
159:
160: } else {
161:
162: if (ns == null) {
163: type = Statement.getTagId(tag);
164: if (type == ST_INVALID) {
165: type = ST_TAG;
166: }
167: } else {
168: type = ST_TAG;
169: }
170:
171: }
172:
173: Statement statement = peek();
174: if (statement != null) {
175: if (!statement.onTag(this , type, tag)) {
176: error(getLocation(), "Unexpected element: " + tag);
177: }
178: }
179:
180: _document = null;
181: }
182:
183: public void handleProcessingInstruction(String data) {
184: Statement statement = peek();
185: if (statement != null) {
186: if (!statement.onProcessingInstruction(this , data)) {
187: error(getLocation(),
188: "Unexpected processing instruction: " + data);
189: }
190: }
191: _document = null;
192: }
193:
194: public void onCharacters(TemplateParser handler, String cdata) {
195: }
196:
197: public boolean onTag(TemplateParser handler, int type, Tag tag) {
198: switch (type) {
199: case Statement.ST_TAG:
200: //ignore
201: break;
202:
203: case Statement.ST_MODULE:
204: _script = new ModuleStatement(_envelope, getLocation());
205: handler.push(_script);
206: _script.parse(handler, tag);
207: break;
208:
209: case Statement.ST_ENDMODULE:
210: handler.pop();
211: break;
212:
213: default:
214: return false;
215: }
216:
217: return true;
218: }
219:
220: public boolean onProcessingInstruction(TemplateParser parser,
221: String data) {
222: if (data.startsWith("anvil ")) {
223: String ns = Parser.getAttributeValue(data, "namespace");
224: if (ns != null) {
225: _namespace = ns;
226: }
227: return true;
228: } else {
229: return super .onProcessingInstruction(parser, data);
230: }
231:
232: }
233:
234: public void unexpectedElement(String name) {
235: error(getLocation(), "Unexpected element: " + name);
236: }
237:
238: public void error(Location location, Throwable throwable) {
239: if (_errorListener == null) {
240: _errorListener = new ErrorListenerImpl();
241: }
242: _errorListener.error(location, throwable);
243: }
244:
245: public void error(Location location, String message) {
246: if (_errorListener == null) {
247: _errorListener = new ErrorListenerImpl();
248: }
249: _errorListener.error(location, message);
250: }
251:
252: public int errors() {
253: if (_errorListener == null) {
254: return 0;
255: } else {
256: return _errorListener.errors();
257: }
258: }
259:
260: public Enumeration getEvents() {
261: if (_errorListener == null) {
262: _errorListener = new ErrorListenerImpl();
263: }
264: return _errorListener.getEvents();
265: }
266:
267: public void merge(ErrorListener listener) {
268: if (_errorListener == null) {
269: _errorListener = new ErrorListenerImpl();
270: }
271: _errorListener.merge(listener);
272: }
273:
274: public ModuleStatement parseTemplate() throws IOException,
275: ForgingException {
276: Parser parser = new Parser();
277: parser.parse(this , _url, _input);
278: ModuleStatement script = _script;
279: if (script == null) {
280: error(getLocation(), "Document doesn't contain template");
281: }
282: if (_errorListener != null) {
283: throw new ForgingException(_errorListener);
284: }
285: return script;
286: }
287:
288: }
|