/** * Copyright (C) 2005 Orbeon, Inc. * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation; either version * 2.1 of the License, or (at your option) any later version. * * This program 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. * * The full text of the license is available at http://www.gnu.org/copyleft/lesser.html */ package org.orbeon.oxf.xml.saxrewrite; import org.orbeon.oxf.xml.XMLReceiver; import org.xml.sax.Attributes; import org.xml.sax.Locator; import org.xml.sax.SAXException; /** * Base state. Simply forwards data to the destination content handler and returns itself. That is unless the (element) * depth becomes negative after an end element event. In this case the previous state is returned. This means btw that * we are really only considering state changes on start and end element events. */ public abstract class State { /** * At the moment are state transitions only happen on start element and end element events. * Therefore we track element depth and by default when the depth becomes negative we switch * to the previous state. */ private int depth = 0; /** * The destination of the rewrite transformation. */ protected final XMLReceiver xmlReceiver; /** * What you think. */ protected final State previousState; /** * * @param previousState previous state * @param xmlReceiver destination for the rewrite transformation * @see #previousState * @see #xmlReceiver */ public State(final State previousState, final XMLReceiver xmlReceiver) { this.previousState = previousState; this.xmlReceiver = xmlReceiver; } /** * Just forwards the event to the content handler. * * @see #endElement( String, String, String ) */ protected void endElementStart(final String ns, final String lnam, final String qnam) throws SAXException { xmlReceiver.endElement(ns, lnam, qnam); } /** * @return What you think */ protected int getDepth() { return depth; } /** * @see #startElement(String, String, String, Attributes) */ protected abstract State startElementStart (final String ns, final String lnam, final String qnam, final Attributes atts) throws SAXException; public State characters(final char[] ch, final int strt, final int len) throws SAXException { xmlReceiver.characters(ch, strt, len); return this; } public State endDocument() throws SAXException { xmlReceiver.endDocument(); return this; } /** * Template method. Calls endElementStart and then decrements depth. If the depth == 0 then the previous state is * returned. Otherwise this state is returned. */ public final State endElement(final String ns, final String lnam, final String qnam) throws SAXException { endElementStart(ns, lnam, qnam); depth--; return depth == 0 ? previousState : this; } public State endPrefixMapping(final String pfx) throws SAXException { xmlReceiver.endPrefixMapping(pfx); return this; } public State ignorableWhitespace(final char[] ch, final int strt, final int len) throws SAXException { xmlReceiver.ignorableWhitespace(ch, strt, len); return this; } public State processingInstruction(final String trgt, final String dat) throws SAXException { xmlReceiver.processingInstruction(trgt, dat); return this; } public State setDocumentLocator(final Locator lctr) { xmlReceiver.setDocumentLocator(lctr); return this; } public State skippedEntity(final String nam) throws SAXException { xmlReceiver.skippedEntity(nam); return this; } public State startDocument() throws SAXException { xmlReceiver.startDocument(); return this; } /** * Template method. Calls startElementStart. If startElementStart returns this increments * depth. Lastly, returns the value returned by startElementStart. */ public final State startElement (final String ns, final String lnam, final String qnam, final Attributes atts) throws SAXException { final State ret = startElementStart(ns, lnam, qnam, atts); if (ret == this) depth++; return ret; } public State startPrefixMapping(final String pfx, final String uri) throws SAXException { xmlReceiver.startPrefixMapping(pfx, uri); return this; } public State startDTD(String name, String publicId, String systemId) throws SAXException { xmlReceiver.startDTD(name, publicId, systemId); return this; } public State endDTD() throws SAXException { xmlReceiver.endDTD(); return this; } public State startEntity(String name) throws SAXException { xmlReceiver.startEntity(name); return this; } public State endEntity(String name) throws SAXException { xmlReceiver.endEntity(name); return this; } public State startCDATA() throws SAXException { xmlReceiver.startCDATA(); return this; } public State endCDATA() throws SAXException { xmlReceiver.endCDATA(); return this; } public State comment(char[] ch, int start, int length) throws SAXException { xmlReceiver.comment(ch, start, length); return this; } }