/*
* $Id: TemplateParser.java,v 1.14 2002/09/16 08:05:06 jkl Exp $
*
* Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
*
* Use is subject to license terms, as defined in
* Anvil Sofware License, Version 1.1. See LICENSE
* file, or http://njet.org/license-1.1.txt
*/
package anvil.script.parser;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import anvil.java.io.GenericInputStream;
import anvil.ErrorListener;
import anvil.ErrorListenerImpl;
import anvil.ForgingException;
import anvil.Location;
import anvil.parser.DocumentHandler;
import anvil.parser.InputSource;
import anvil.parser.Locator;
import anvil.parser.Parser;
import anvil.parser.Tag;
import anvil.script.ModuleEnvelope;
import anvil.script.statements.ModuleStatement;
import anvil.script.statements.Statement;
/**
* class TemplateParser
*
* @author: Jani Lehtim�ki
*/
public class TemplateParser extends Statement implements DocumentHandler, ErrorListener
{
private ModuleEnvelope _envelope;
private String _namespace;
private URL _url;
private InputStream _input;
private ErrorListener _errorListener = null;
private Locator _locator = null;
private Statement _current = null;
private ModuleStatement _script = null;
private String _document = null;
public TemplateParser(ModuleEnvelope envelope, String namespace, URL url, byte[] content)
{
super(null, null);
_envelope = envelope;
_namespace = namespace;
_url = url;
_input = new GenericInputStream(content);
}
public String name()
{
return "document";
}
public int typeOf()
{
return Statement.ST_DOCUMENT;
}
public boolean hasEnd()
{
return true;
}
public ModuleEnvelope getEnvelope()
{
return _envelope;
}
public Location getLocation()
{
return _locator.getLocation();
}
public String getDocument()
{
return _document;
}
public void setDocumentLocator(Locator locator)
{
_locator = locator;
}
public void pop()
{
if (_current != null) {
_current = _current.getParentStatement();
if (_current != null && _current.typeOf() == ST_IMPLICIT_BLOCK) {
_current = _current.getParentStatement();
}
} else {
_current = null;
}
}
public void push(Statement stmt)
{
_current = stmt;
}
public Statement peek()
{
return _current;
}
public void startDocument()
{
push(this);
}
public void endDocument()
{
Statement stmt = _current;
while(stmt != null && stmt != this) {
error(stmt.getLocation(), "Unexpected end of file, " + stmt.name() + " open");
stmt = stmt.getParentStatement();
}
}
public void handleCharacters(String characters)
{
Statement statement = peek();
if (statement != null) {
statement.onCharacters(this, characters);
}
}
public void handleComment(String characters)
{
if (characters.startsWith("--/**") && characters.endsWith("*/--")) {
_document = characters.substring(5, characters.length() - 4);
} else {
_document = null;
Statement statement = peek();
if (statement != null) {
statement.onCharacters(this, "<!"+characters+'>');
}
}
}
public void handleTag(Tag tag)
{
int type = ST_INVALID;
String ns = tag.getNamespace();
if (_namespace != null) {
if (ns == null) {
type = ST_TAG;
} else {
if (ns.equals(_namespace)) {
type = Statement.getTagId(tag);
if (type == ST_INVALID) {
error(getLocation(), "Unrecognized tag: "+tag);
return;
}
} else {
type = ST_TAG;
}
}
} else {
if (ns == null) {
type = Statement.getTagId(tag);
if (type == ST_INVALID) {
type = ST_TAG;
}
} else {
type = ST_TAG;
}
}
Statement statement = peek();
if (statement != null) {
if (!statement.onTag(this, type, tag)) {
error(getLocation(), "Unexpected element: "+tag);
}
}
_document = null;
}
public void handleProcessingInstruction(String data)
{
Statement statement = peek();
if (statement != null) {
if (!statement.onProcessingInstruction(this, data)) {
error(getLocation(), "Unexpected processing instruction: "+data);
}
}
_document = null;
}
public void onCharacters(TemplateParser handler, String cdata)
{
}
public boolean onTag(TemplateParser handler, int type, Tag tag)
{
switch(type) {
case Statement.ST_TAG:
//ignore
break;
case Statement.ST_MODULE:
_script = new ModuleStatement(_envelope, getLocation());
handler.push(_script);
_script.parse(handler, tag);
break;
case Statement.ST_ENDMODULE:
handler.pop();
break;
default:
return false;
}
return true;
}
public boolean onProcessingInstruction(TemplateParser parser, String data)
{
if (data.startsWith("anvil ")) {
String ns = Parser.getAttributeValue(data, "namespace");
if (ns != null) {
_namespace = ns;
}
return true;
} else {
return super.onProcessingInstruction(parser, data);
}
}
public void unexpectedElement(String name)
{
error(getLocation(), "Unexpected element: "+name);
}
public void error(Location location, Throwable throwable)
{
if (_errorListener == null) {
_errorListener = new ErrorListenerImpl();
}
_errorListener.error(location, throwable);
}
public void error(Location location, String message)
{
if (_errorListener == null) {
_errorListener = new ErrorListenerImpl();
}
_errorListener.error(location, message);
}
public int errors()
{
if (_errorListener == null) {
return 0;
} else {
return _errorListener.errors();
}
}
public Enumeration getEvents()
{
if (_errorListener == null) {
_errorListener = new ErrorListenerImpl();
}
return _errorListener.getEvents();
}
public void merge(ErrorListener listener)
{
if (_errorListener == null) {
_errorListener = new ErrorListenerImpl();
}
_errorListener.merge(listener);
}
public ModuleStatement parseTemplate() throws IOException, ForgingException
{
Parser parser = new Parser();
parser.parse(this, _url, _input);
ModuleStatement script = _script;
if (script == null) {
error(getLocation(), "Document doesn't contain template");
}
if (_errorListener != null) {
throw new ForgingException(_errorListener);
}
return script;
}
}