org.milyn.delivery.SmooksContentHandler Maven / Gradle / Ivy
/*
Milyn - Copyright (C) 2006 - 2010
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License (version 2.1) as published by the Free Software
Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details:
http://www.gnu.org/licenses/lgpl.txt
*/
package org.milyn.delivery;
import org.milyn.SmooksException;
import org.milyn.container.ExecutionContext;
import org.milyn.delivery.replay.EndElementEvent;
import org.milyn.delivery.replay.SAXEventReplay;
import org.milyn.delivery.replay.StartElementEvent;
import org.milyn.namespace.NamespaceDeclarationStack;
import org.milyn.xml.NamespaceMappings;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.DefaultHandler2;
/**
* Abstract SAX Content Handler.
*
* @author [email protected]
*/
public abstract class SmooksContentHandler extends DefaultHandler2 implements SAXEventReplay {
private ExecutionContext executionContext;
private SmooksContentHandler parentContentHandler;
private SmooksContentHandler nestedContentHandler;
private NamespaceDeclarationStack namespaceDeclarationStack;
private boolean endReplayed = false;
private SAXEventReplay lastEvent = null;
private StartElementEvent startEvent = new StartElementEvent();
private EndElementEvent endEvent = new EndElementEvent();
private int depth = 0;
public SmooksContentHandler(ExecutionContext executionContext, SmooksContentHandler parentContentHandler) {
this.executionContext = executionContext;
this.parentContentHandler = parentContentHandler;
attachHandler();
if(parentContentHandler != null) {
parentContentHandler.nestedContentHandler = this;
}
}
public NamespaceDeclarationStack getNamespaceDeclarationStack() {
if(namespaceDeclarationStack == null) {
namespaceDeclarationStack = NamespaceMappings.getNamespaceDeclarationStack(executionContext);
if(namespaceDeclarationStack == null) {
throw new IllegalStateException("NamespaceDeclarationStack instance not set on ExecutionContext.");
}
}
return namespaceDeclarationStack;
}
public void replayStartElement() {
// Replay the last sax event from the parent handler on this sax handler...
parentContentHandler.replay(this);
}
@Override
public final void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
getNamespaceDeclarationStack().pushNamespaces(qName, uri, attributes);
startEvent.set(uri, localName, qName, attributes);
lastEvent = startEvent;
depth++;
startElement(startEvent);
if(nestedContentHandler != null) {
// Replay the start element event from the parent handler onto the nested handler...
replay(nestedContentHandler);
}
}
public abstract void startElement(StartElementEvent startEvent) throws SAXException;
@Override
public final void endElement(String uri, String localName, String qName) throws SAXException {
try {
endEvent.set(uri, localName, qName);
lastEvent = endEvent;
endElement(endEvent);
depth--;
} finally {
if(!endReplayed && depth == 0 && parentContentHandler != null) {
endReplayed = true;
// Replay the last sax event from this handler onto the parent handler ...
replay(parentContentHandler);
// Reinstate the parent handler on the XMLReader so all events are
// forwarded to it again ...
XMLReader xmlReader = AbstractParser.getXMLReader(executionContext);
xmlReader.setContentHandler(parentContentHandler);
// Remove the nested handler (this handler) form the parent handler...
parentContentHandler.resetNestedContentHandler();
}
}
getNamespaceDeclarationStack().popNamespaces();
}
public abstract void endElement(EndElementEvent endEvent) throws SAXException;
public void replay(org.xml.sax.ContentHandler handler) throws SmooksException {
if(lastEvent != null) {
lastEvent.replay(handler);
}
}
private void attachHandler() {
executionContext.setAttribute(DefaultHandler2.class, this);
}
public static SmooksContentHandler getHandler(ExecutionContext executionContext) {
return (SmooksContentHandler) executionContext.getAttribute(DefaultHandler2.class);
}
public void detachHandler() {
executionContext.removeAttribute(DefaultHandler2.class);
}
public ExecutionContext getExecutionContext() {
return executionContext;
}
public SmooksContentHandler getParentContentHandler() {
return parentContentHandler;
}
public SmooksContentHandler getNestedContentHandler() {
return nestedContentHandler;
}
public void resetNestedContentHandler() {
nestedContentHandler = null;
}
public abstract void cleanup();
}