Project dom4j 1.5.2 [5/2/05 10:13 PM]
 
Coverage - org/dom4j/io/SAXEventRecorder.java
  /*
   * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
   *
   * This software is open source.
   * See the bottom of this file for the licence.
   *
   * $Id: SAXEventRecorder.java,v 1.2 2004/11/14 12:48:20 maartenc Exp $
   */
 
  package org.dom4j.io;
 
  import java.io.Externalizable;
  import java.io.IOException;
  import java.io.ObjectInput;
  import java.io.ObjectOutput;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
 
  import org.xml.sax.Attributes;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.DTDHandler;
  import org.xml.sax.SAXException;
  import org.xml.sax.ext.DeclHandler;
  import org.xml.sax.ext.LexicalHandler;
  import org.xml.sax.helpers.AttributesImpl;
  import org.xml.sax.helpers.DefaultHandler;
 
  /**
   * Records SAX events such that they may be "replayed" at a later time.  Provides
   * an alternative serialization approach when externalizing a DOM4J document.  
   * Rather than serializing a document as text and re-parsing, the sax events may
   * be serialized instead.</p>
   * 
   * Example usage:</p>
   *      
   *      <code>
   *      SAXEventRecorder recorder = new SAXEventRecorder();<br/>
   *      SAXWriter saxWriter = new SAXWriter(recorder);<br/>
   *      saxWriter.write(document);<br/>
   *      out.writeObject(recorder);<br/>
   *      ...<br/>
   *      SAXEventRecorder recorder = (SAXEventRecorder)in.readObject();<br/>
   *      SAXContentHandler saxContentHandler = new SAXContentHandler();<br/>
   *      recorder.replay(saxContentHandler);<br/>
   *      Document document = saxContentHandler.getDocument();<br/>
   *      </code>
   *
   * @author Todd Wolff  (Bluestem Software)
   */
 
  public class SAXEventRecorder extends DefaultHandler implements LexicalHandler, DeclHandler, DTDHandler, Externalizable { 
 
      public static final long serialVersionUID = 1;
      
      private static final byte STRING = 0;
      private static final byte OBJECT = 1;
      private static final byte NULL = 2;
      
0x       private List events = new ArrayList();
      
0x       public SAXEventRecorder() {
0x       }
 
      public void replay(ContentHandler handler) throws SAXException {
          
          SAXEvent saxEvent;
0x           Iterator itr = events.iterator();
          
0/2 0x           while (itr.hasNext()) {
0x               saxEvent = (SAXEvent)itr.next();
0x               switch (saxEvent.event) {
                  
                  // replay to ContentHandler
                  
                  case SAXEvent.PROCESSING_INSTRUCTION:  
0x                       handler.processingInstruction((String)saxEvent.getParm(0), (String)saxEvent.getParm(1));
0x                       break;
                  case SAXEvent.START_PREFIX_MAPPING:
0x                       handler.startPrefixMapping((String)saxEvent.getParm(0), (String)saxEvent.getParm(1));  
0x                       break;
                  case SAXEvent.END_PREFIX_MAPPING: 
0x                       handler.endPrefixMapping((String)saxEvent.getParm(0)); 
0x                       break;
                  case SAXEvent.START_DOCUMENT:  
0x                       handler.startDocument();
0x                       break;
                  case SAXEvent.END_DOCUMENT:  
0x                       handler.endDocument();
0x                       break;
                  case SAXEvent.START_ELEMENT:
0x                       AttributesImpl attributes = new AttributesImpl();
0x                       List attParmList = (List)saxEvent.getParm(3); 
0/2 0x                       if (attParmList != null) {
0x                           Iterator attsItr = attParmList.iterator();
0/2 0x                           while (attsItr.hasNext()) {
0x                               String[] attParms = (String[])attsItr.next();
0x                               attributes.addAttribute(attParms[0], attParms[1], attParms[2], attParms[3], attParms[4]);           
                          }
                      }
0x                       handler.startElement((String)saxEvent.getParm(0), (String)saxEvent.getParm(1), (String)saxEvent.getParm(2), attributes);
0x                       break;
                  case SAXEvent.END_ELEMENT:  
0x                       handler.endElement((String)saxEvent.getParm(0), (String)saxEvent.getParm(1), (String)saxEvent.getParm(2));
0x                       break;
                  case SAXEvent.CHARACTERS: 
0x                       handler.characters((char[])saxEvent.getParm(0), ((Integer)saxEvent.getParm(1)).intValue(), ((Integer)saxEvent.getParm(2)).intValue()); 
0x                       break;
                  
                  // replay to LexicalHandler         
                             
                  case SAXEvent.START_DTD:
0x                       ((LexicalHandler)handler).startDTD((String)saxEvent.getParm(0), (String)saxEvent.getParm(1), (String)saxEvent.getParm(2));  
0x                       break;
                  case SAXEvent.END_DTD:  
0x                       ((LexicalHandler)handler).endDTD();
0x                       break;
                  case SAXEvent.START_ENTITY:  
0x                       ((LexicalHandler)handler).startEntity((String)saxEvent.getParm(0));
0x                       break;
                  case SAXEvent.END_ENTITY: 
0x                       ((LexicalHandler)handler).endEntity((String)saxEvent.getParm(0));                 
0x                       break;
                  case SAXEvent.START_CDATA: 
0x                       ((LexicalHandler)handler).startCDATA();                 
0x                       break;
                  case SAXEvent.END_CDATA: 
0x                       ((LexicalHandler)handler).endCDATA();                
0x                       break;
                  case SAXEvent.COMMENT:  
0x                       ((LexicalHandler)handler).comment((char[])saxEvent.getParm(0), ((Integer)saxEvent.getParm(1)).intValue(), ((Integer)saxEvent.getParm(2)).intValue());                
0x                       break;
 
                  // replay to DeclHandler   
                                   
                  case SAXEvent.ELEMENT_DECL:
0x                       ((DeclHandler)handler).elementDecl((String)saxEvent.getParm(0), (String)saxEvent.getParm(1));  
0x                       break;
                  case SAXEvent.ATTRIBUTE_DECL:  
0x                       ((DeclHandler)handler).attributeDecl((String)saxEvent.getParm(0), (String)saxEvent.getParm(1), (String)saxEvent.getParm(2), (String)saxEvent.getParm(3), (String)saxEvent.getParm(4));                
0x                       break;
                  case SAXEvent.INTERNAL_ENTITY_DECL: 
0x                       ((DeclHandler)handler).internalEntityDecl((String)saxEvent.getParm(0), (String)saxEvent.getParm(1));                
0x                       break;
                  case SAXEvent.EXTERNAL_ENTITY_DECL:  
0x                       ((DeclHandler)handler).externalEntityDecl((String)saxEvent.getParm(0), (String)saxEvent.getParm(1), (String)saxEvent.getParm(2));
0x                       break;
                      
                  default:
0x                       throw new SAXException("Unrecognized event: " + saxEvent.event);
                          
              }
 
          }
          
0x       }
      
      // ContentHandler interface
      //-------------------------------------------------------------------------
          
      public void processingInstruction(String target, String data) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.PROCESSING_INSTRUCTION);
0x           saxEvent.addParm(target);
0x           saxEvent.addParm(data);
0x           events.add(saxEvent);
0x       }
 
      public void startPrefixMapping(String prefix, String uri) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.START_PREFIX_MAPPING);
0x           saxEvent.addParm(prefix);
0x           saxEvent.addParm(uri);
0x           events.add(saxEvent);
0x       }
 
      public void endPrefixMapping(String prefix) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.END_PREFIX_MAPPING);
0x           saxEvent.addParm(prefix);
0x           events.add(saxEvent);
0x       }
 
      public void startDocument() throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.START_DOCUMENT);
0x           events.add(saxEvent);
0x       }
 
      public void endDocument() throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.END_DOCUMENT);
0x           events.add(saxEvent);
0x       }
 
      public void startElement(String namespaceURI, String localName, String qualifiedName, Attributes attributes) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.START_ELEMENT);
0x           saxEvent.addParm(namespaceURI);
0x           saxEvent.addParm(localName);
0x           saxEvent.addParm(qualifiedName);
0/4 0x           if (attributes != null && attributes.getLength() > 0) {
0x               List attParmList = new ArrayList(attributes.getLength());
0x               String[] attParms = null;
0/2 0x               for (int i = 0; i < attributes.getLength(); i++) {
0x                   attParms = new String[5];
0x                   attParms[0] = attributes.getURI(i);
0x                   attParms[1] = attributes.getLocalName(i);
0x                   attParms[2] = attributes.getQName(i);
0x                   attParms[3] = attributes.getType(i);
0x                   attParms[4] = attributes.getValue(i); 
0x                   attParmList.add(attParms);        
              }
0x               saxEvent.addParm(attParmList);
          }
0x           events.add(saxEvent);
0x       }
 
      public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.END_ELEMENT);
0x           saxEvent.addParm(namespaceURI);
0x           saxEvent.addParm(localName);
0x           saxEvent.addParm(qName);
0x           events.add(saxEvent);
0x       }
 
      public void characters(char[] ch, int start, int end) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.CHARACTERS);
0x           saxEvent.addParm(ch);
0x           saxEvent.addParm(new Integer(start));
0x           saxEvent.addParm(new Integer(end));
0x           events.add(saxEvent);
0x       }
 
      // LexicalHandler interface
      //-------------------------------------------------------------------------
 
      public void startDTD(String name, String publicId, String systemId) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.START_DTD);
0x           saxEvent.addParm(name);
0x           saxEvent.addParm(publicId);
0x           saxEvent.addParm(systemId);
0x           events.add(saxEvent);
0x       }
 
      public void endDTD() throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.END_DTD);
0x           events.add(saxEvent);
0x       }
 
      public void startEntity(String name) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.START_ENTITY);
0x           saxEvent.addParm(name);
0x           events.add(saxEvent);
0x       }
 
      public void endEntity(String name) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.END_ENTITY);
0x           saxEvent.addParm(name);
0x           events.add(saxEvent);
0x       }
 
      public void startCDATA() throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.START_CDATA);
0x           events.add(saxEvent);
0x       }
 
      public void endCDATA() throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.END_CDATA);
0x           events.add(saxEvent);
0x       }
 
      public void comment(char[] ch, int start, int end) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.COMMENT);
0x           saxEvent.addParm(ch);
0x           saxEvent.addParm(new Integer(start));
0x           saxEvent.addParm(new Integer(end));
0x           events.add(saxEvent);
0x       }
 
      // DeclHandler interface
      //-------------------------------------------------------------------------
 
      public void elementDecl(String name, String model) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.ELEMENT_DECL);
0x           saxEvent.addParm(name);
0x           saxEvent.addParm(model);
0x           events.add(saxEvent);
0x       }
 
      public void attributeDecl(String eName, String aName, String type, String valueDefault, String value) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.ATTRIBUTE_DECL);
0x           saxEvent.addParm(eName);
0x           saxEvent.addParm(aName);
0x           saxEvent.addParm(type);
0x           saxEvent.addParm(valueDefault);
0x           saxEvent.addParm(value);
0x           events.add(saxEvent);
0x       }
 
      public void internalEntityDecl(String name, String value) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.INTERNAL_ENTITY_DECL);
0x           saxEvent.addParm(name);
0x           saxEvent.addParm(value);
0x           events.add(saxEvent);
0x       }
 
      public void externalEntityDecl(String name, String publicId, String systemId) throws SAXException {
0x           SAXEvent saxEvent = new SAXEvent(SAXEvent.EXTERNAL_ENTITY_DECL);
0x           saxEvent.addParm(name);
0x           saxEvent.addParm(publicId);
0x           saxEvent.addParm(systemId);
0x           events.add(saxEvent);
0x       }
 
      // SAXEvent inner class
      //-------------------------------------------------------------------------
      
      static class SAXEvent implements Externalizable {
          
          public static final long serialVersionUID = 1;
          
          static final byte PROCESSING_INSTRUCTION = 1;
          static final byte START_PREFIX_MAPPING = 2;
          static final byte END_PREFIX_MAPPING = 3;
          static final byte START_DOCUMENT = 4;
          static final byte END_DOCUMENT = 5;
          static final byte START_ELEMENT = 6;
          static final byte END_ELEMENT = 7;
          static final byte CHARACTERS = 8;
          static final byte START_DTD = 9;
          static final byte END_DTD = 10;
          static final byte START_ENTITY = 11;
          static final byte END_ENTITY = 12;
          static final byte START_CDATA = 13;
          static final byte END_CDATA = 14;
          static final byte COMMENT = 15;
          static final byte ELEMENT_DECL = 16;
          static final byte ATTRIBUTE_DECL = 17;
          static final byte INTERNAL_ENTITY_DECL = 18;
          static final byte EXTERNAL_ENTITY_DECL = 19;
          
          byte event;
          List parms;
          
0x           public SAXEvent(){
0x           }
          
0x           SAXEvent(byte event) {
0x               this.event = event;
0x           }
          
          void addParm(Object parm) {
0/2 0x               if (parms == null) {
0x                   parms = new ArrayList(3);
              }
0x               parms.add(parm);
0x           }
          
          Object getParm(int index) {
0/4 0x               if (parms != null && index < parms.size()) {
0x                   return parms.get(index);
              } else {
0x                   return null;           
              }
          }
          
          public void writeExternal(ObjectOutput out) throws IOException {
0x               out.writeByte(event);
0/2 0x               if (parms == null) {
0x                   out.writeByte(NULL);
              } else {
0x                   out.writeByte(OBJECT);
0x                   out.writeObject(parms);
              }
0x           }
          
          public void readExternal(ObjectInput in) throws ClassNotFoundException, IOException {
0x               event = in.readByte();
0/2 0x               if (in.readByte() != NULL) {
0x                   parms = (List)in.readObject();
              } 
0x           }
              
      }
 
      public void writeExternal(ObjectOutput out) throws IOException {
0/2 0x           if (events == null) {
0x               out.writeByte(NULL);
          } else {
0x               out.writeByte(OBJECT);
0x               out.writeObject(events);
          }
0x       }
          
      public void readExternal(ObjectInput in) throws ClassNotFoundException, IOException {
0/2 0x           if (in.readByte() != NULL) {
0x               events = (List)in.readObject();
          } 
0x       }
 
  }
 
 
 
 
  /*
   * Redistribution and use of this software and associated documentation
   * ("Software"), with or without modification, are permitted provided
   * that the following conditions are met:
   *
   * 1. Redistributions of source code must retain copyright
   *    statements and notices.  Redistributions must also contain a
   *    copy of this document.
   *
   * 2. 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.
   *
   * 3. The name "DOM4J" must not be used to endorse or promote
   *    products derived from this Software without prior written
   *    permission of MetaStuff, Ltd.  For written permission,
   *    please contact dom4j-info@metastuff.com.
   *
   * 4. Products derived from this Software may not be called "DOM4J"
   *    nor may "DOM4J" appear in their names without prior written
   *    permission of MetaStuff, Ltd. DOM4J is a registered
   *    trademark of MetaStuff, Ltd.
   *
   * 5. Due credit should be given to the DOM4J Project - 
   *    http://www.dom4j.org
   *
   * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
   * ``AS IS'' AND ANY EXPRESSED 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
   * METASTUFF, LTD. OR ITS 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)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * Copyright 2001-2004 (C) MetaStuff, Ltd. All Rights Reserved.
   *
   * $Id: SAXEventRecorder.java,v 1.2 2004/11/14 12:48:20 maartenc Exp $
   */