/** * Copyright (c) 2007-20010, JAGaToo Project Group all rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the 'Xith3D Project Group' nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.jagatoo.util.xml; import java.util.ArrayList; import java.util.List; import java.util.Stack; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.AttributesImpl; /** * Insert class comment here. * * @author Marvin Froehlich (aka Qudus) */ public class XMLHandlerAdapter extends org.xml.sax.helpers.DefaultHandler { private final List<XMLPath> pathStack = new ArrayList<XMLPath>(); private XMLPath path = null; private final Stack<SimpleXMLHandlerDelegate> simpleHandlerStack = new Stack<SimpleXMLHandlerDelegate>(); private SimpleXMLHandlerDelegate simpleHandler = null; private Object userObject = null; private boolean forkAllowed = false; private String currElement = null; private Object currObject = null; private Attributes currAttribs = null; private final AttributesImpl lastAttribs = new AttributesImpl(); final void delegate( SimpleXMLHandlerDelegate delegate ) throws SAXException { if ( delegate == null ) throw new IllegalArgumentException( "delegate must not be null." ); if ( !forkAllowed ) throw new IllegalStateException( "delegate() can only be called from the onElementStarted() event." ); delegate.handleForkElement( currElement, currObject, currAttribs ); simpleHandler.setAdapter( null ); simpleHandlerStack.push( delegate ); simpleHandler = delegate; simpleHandler.setAdapter( this ); if ( pathStack.size() < simpleHandlerStack.size() ) { path = new XMLPath(); pathStack.add( path ); } else { path = pathStack.get( simpleHandlerStack.size() - 1 ); path.reset(); } } private void undelegate() { simpleHandler.setAdapter( null ); simpleHandlerStack.pop(); simpleHandler = simpleHandlerStack.peek(); simpleHandler.setAdapter( this ); path = pathStack.get( simpleHandlerStack.size() - 1 ); } public void setSimpleHandler( SimpleXMLHandlerDelegate simpleHandler ) { if ( simpleHandler == null ) throw new IllegalArgumentException( "simpleHandler must not be null." ); if ( simpleHandler == this.simpleHandler ) return; if ( this.simpleHandler != null ) this.simpleHandler.setAdapter( null ); this.simpleHandlerStack.set( simpleHandlerStack.size() - 1, simpleHandler ); this.simpleHandler = simpleHandler; this.simpleHandler.setAdapter( this ); } public void setUserObject( Object userObject ) { this.userObject = userObject; } public final Object getUserObject() { return ( userObject ); } @Override public void startDocument() throws SAXException { path.reset(); ( (SimpleXMLHandler)simpleHandler ).onDocumentStarted(); } @Override public void startElement( String uri, String localName, String qName, Attributes attributes ) throws SAXException { lastAttribs.clear(); for ( int i = 0; i < attributes.getLength(); i++ ) lastAttribs.addAttribute( attributes.getURI( i ), attributes.getLocalName( i ), attributes.getQName( i ), attributes.getType( i ), attributes.getType( i ) ); SimpleXMLHandlerDelegate handler = this.simpleHandler; XMLPath path = this.path; Object object = handler.getPathObject( path, qName ); if ( object == null ) throw new RuntimeException( "The getPathObject() method must never return null." ); forkAllowed = true; currElement = qName; currObject = object; currAttribs = attributes; try { handler.onElementStarted( path, qName, object, attributes ); } finally { currAttribs = null; currObject = object; currElement = qName; forkAllowed = false; } path.pushPath( qName, object ); } @Override public void characters( char[] data, int start, int length ) throws SAXException { simpleHandler.onElementData( path, lastAttribs, data, start, length ); } @Override public void endElement( String uri, String localName, String qName ) throws SAXException { if ( path.getLevel() == 0 ) undelegate(); Object object = path.getLastPathObject(); path.popPath(); simpleHandler.onElementEnded( path, qName, object ); } @Override public void warning( SAXParseException ex ) throws SAXException { XMLPath fullPath = XMLPath.getFullPath( pathStack ); for ( int i = 0; i < simpleHandlerStack.size(); i++ ) simpleHandlerStack.get( i ).onParsingException( fullPath, SimpleXMLHandlerDelegate.ExceptionSeverity.WARNING, ex ); } @Override public void error( SAXParseException ex ) throws SAXException { XMLPath fullPath = XMLPath.getFullPath( pathStack ); for ( int i = 0; i < simpleHandlerStack.size(); i++ ) simpleHandlerStack.get( i ).onParsingException( fullPath, SimpleXMLHandlerDelegate.ExceptionSeverity.ERROR, ex ); } @Override public void fatalError( SAXParseException ex ) throws SAXException { XMLPath fullPath = XMLPath.getFullPath( pathStack ); for ( int i = 0; i < simpleHandlerStack.size(); i++ ) simpleHandlerStack.get( i ).onParsingException( fullPath, SimpleXMLHandlerDelegate.ExceptionSeverity.FATAL_ERROR, ex ); } private void release() { if ( this.simpleHandler != null ) this.simpleHandler.setAdapter( null ); this.simpleHandler = null; this.simpleHandlerStack.clear(); } @Override public void endDocument() throws SAXException { ( (SimpleXMLHandler)simpleHandler ).onDocumentEnded(); release(); } /** * {@inheritDoc} */ @Override protected void finalize() throws Throwable { super.finalize(); release(); } public XMLHandlerAdapter( SimpleXMLHandler simpleHandler ) { if ( simpleHandler == null ) throw new IllegalArgumentException( "simpleHandler must not be null" ); this.simpleHandler = simpleHandler; this.simpleHandlerStack.push( this.simpleHandler ); this.simpleHandler.setAdapter( this ); this.path = new XMLPath(); this.pathStack.add( path ); } }