Project dom4j 1.5.2 [5/2/05 10:13 PM]
 
Coverage - org/dom4j/io/STAXEventWriter.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: STAXEventWriter.java,v 1.6 2004/07/14 19:32:23 maartenc Exp $
   */
 
  package org.dom4j.io;
 
  import java.io.File;
  import java.io.FileWriter;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.StringWriter;
  import java.io.Writer;
  import java.util.Iterator;
 
  import javax.xml.namespace.QName;
  import javax.xml.stream.XMLEventFactory;
  import javax.xml.stream.XMLOutputFactory;
  import javax.xml.stream.XMLStreamException;
  import javax.xml.stream.events.Characters;
  import javax.xml.stream.events.DTD;
  import javax.xml.stream.events.EndDocument;
  import javax.xml.stream.events.EndElement;
  import javax.xml.stream.events.EntityReference;
  import javax.xml.stream.events.StartDocument;
  import javax.xml.stream.events.StartElement;
  import javax.xml.stream.util.XMLEventConsumer;
 
  import org.dom4j.Attribute;
  import org.dom4j.Branch;
  import org.dom4j.CDATA;
  import org.dom4j.Comment;
  import org.dom4j.Document;
  import org.dom4j.DocumentType;
  import org.dom4j.Element;
  import org.dom4j.Entity;
  import org.dom4j.Namespace;
  import org.dom4j.Node;
  import org.dom4j.ProcessingInstruction;
  import org.dom4j.Text;
 
  /**
   * Writes DOM4J {@link Node}s to a StAX event stream. In addition the
   * <code>createXXX</code> methods are provided to directly create STAX events
   * from DOM4J nodes.
   *
   * @author Christian Niles
   */
  public class STAXEventWriter {
      
      /** The event stream to which events are written. */
      private XMLEventConsumer consumer;
      
      /** The event factory used to construct events. */
0x       private XMLEventFactory factory = XMLEventFactory.newInstance();
      
0x       private XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
      
0x       public STAXEventWriter() {
0x       }
 
      /**
       * Constructs a <code>STAXEventWriter</code> that writes events to the
       * provided file.
       *
       * @param file The file to which events will be written.
       * @throws XMLStreamException If an error occurs creating an event writer from
       *     the file.
       * @throws IOException If an error occurs openin the file for writing.
       */
0x       public STAXEventWriter(File file) throws XMLStreamException, IOException {
0x           consumer = outputFactory.createXMLEventWriter(new FileWriter(file));
0x       }
      
      /**
       * Constructs a <code>STAXEventWriter</code> that writes events to the
       * provided character stream.
       *
       * @param writer The character stream to which events will be written.
       * @throws XMLStreamException If an error occurs constructing an event writer
       *     from the character stream.
       */
0x       public STAXEventWriter(Writer writer) throws XMLStreamException {
0x           consumer = outputFactory.createXMLEventWriter(writer);
0x       }
 
      /**
       * Constructs a <code>STAXEventWriter</code> that writes events to the
       * provided stream.
       *
       * @param stream The output stream to which events will be written.
       * @throws XMLStreamException If an error occurs constructing an event writer
       *     from the stream.
       */
0x       public STAXEventWriter(OutputStream stream) throws XMLStreamException {
0x           consumer = outputFactory.createXMLEventWriter(stream);
0x       }
      
      /**
       * Constructs a <code>STAXEventWriter</code> that writes events to the
       * provided event stream.
       *
       * @param consumer The event stream to which events will be written.
       */
0x       public STAXEventWriter(XMLEventConsumer consumer) {
0x           this.consumer = consumer;
0x       }
      
      /**
       * Returns a reference to the underlying event consumer to which events are
       * written.
       *
       * @return The underlying event consumer to which events are written.
       */
      public XMLEventConsumer getConsumer() {
0x           return consumer;
      }
      
      /**
       * Sets the underlying event consumer to which events are written.
       *
       * @param consumer The event consumer to which events should be written.
       */
      public void setConsumer(XMLEventConsumer consumer) {
0x           this.consumer = consumer;
0x       }
      
      /**
       * Returns a reference to the event factory used to construct STAX events.
       *
       * @return The event factory used to construct STAX events.
       */
      public XMLEventFactory getEventFactory() {
0x           return factory;
      }
      
      /**
       * Sets the event factory used to construct STAX events.
       *
       * @param factory The new event factory.
       */
      public void setEventFactory(XMLEventFactory factory) {
0x           this.factory = factory;
0x       }
      
      /**
       * Writes a DOM4J {@link Node} to the stream. This method is simply a
       * gateway to the overloaded methods such as {@link #writeElement(Element)}.
       *
       * @param n The DOM4J {@link Node} to write to the stream.
       * @throws XMLStreamException If an error occurs writing to the stream.
       */
      public void writeNode(Node n) throws XMLStreamException {
0x           switch (n.getNodeType()) {
              
              case Node.ELEMENT_NODE :
0x                   writeElement((Element) n);
0x                   break;
                  
              case Node.TEXT_NODE :
0x                   writeText((Text) n);
0x                   break;
                  
              case Node.ATTRIBUTE_NODE :
0x                   writeAttribute((Attribute) n);
0x                   break;
                  
              case Node.NAMESPACE_NODE :
0x                   writeNamespace((Namespace) n);
0x                   break;
                  
              case Node.COMMENT_NODE :
0x                   writeComment((Comment) n);
0x                   break;
                  
              case Node.CDATA_SECTION_NODE :
0x                   writeCDATA((CDATA) n);
0x                   break;
                  
              case Node.PROCESSING_INSTRUCTION_NODE :
0x                   writeProcessingInstruction((ProcessingInstruction) n);
0x                   break;
                  
              case Node.ENTITY_REFERENCE_NODE :
0x                   writeEntity((Entity) n);
0x                   break;
                  
              case Node.DOCUMENT_NODE :
0x                   writeDocument((Document) n);
0x                   break;
                  
              case Node.DOCUMENT_TYPE_NODE :
0x                   writeDocumentType((DocumentType) n);
0x                   break;
                  
              default :
0x                   throw new XMLStreamException("Unsupported DOM4J Node: " + n);
          }
0x       }
      
      /**
       * Writes each child node within the provided {@link Branch} instance. This
       * method simply iterates through the {@link Branch}'s nodes and calls
       * {@link #writeNode(Node)}.
       *
       * @param branch The node whose children will be written to the stream.
       * @throws XMLStreamException If an error occurs writing to the stream.
       */
      public void writeChildNodes(Branch branch) throws XMLStreamException {
0/2 0x           for (int i = 0, s = branch.nodeCount(); i < s; i++) {
0x               Node n = branch.node(i);
0x               writeNode(n);
          }
0x       }
      
      /**
       * Writes a DOM4J {@link Element} node and its children to the stream.
       *
       * @param elem The {@link Element} node to write to the stream.
       * @throws XMLStreamException If an error occurs writing to the stream.
       */
      public void writeElement(Element elem) throws XMLStreamException {
0x           consumer.add(createStartElement(elem));
0x           writeChildNodes(elem);
0x           consumer.add(createEndElement(elem));
0x       }
      
      /**
       * Constructs a STAX {@link StartElement} event from a DOM4J
       * {@link Element}.
       *
       * @param elem The {@link Element} from which to construct the event.
       * @return The newly constructed {@link StartElement} event.
       */
      public StartElement createStartElement(Element elem) {
          
          // create name
0x           QName tagName = createQName(elem.getQName());
          
          // create attribute & namespace iterators
0x           Iterator attrIter = new AttributeIterator(elem.attributeIterator());
0x           Iterator nsIter = new NamespaceIterator(
                  elem.declaredNamespaces().iterator());
          
          // create start event
0x           return factory.createStartElement(tagName, attrIter, nsIter);
      }
      
      /**
       * Constructs a STAX {@link EndElement} event from a DOM4J {@link Element}.
       *
       * @param elem The {@link Element} from which to construct the event.
       * @return The newly constructed {@link EndElement} event.
       */
      public EndElement createEndElement(Element elem) {
0x           QName tagName = createQName(elem.getQName());
0x           Iterator nsIter = new NamespaceIterator(
          elem.declaredNamespaces().iterator());
          
0x           return factory.createEndElement(tagName, nsIter);
      }
      
      /**
       * Writes a DOM4J {@link Attribute} to the stream.
       *
       * @param attr The {@link Attribute} to write to the stream.
       * @throws XMLStreamException If an error occurs writing to the stream.
       */
      public void writeAttribute(Attribute attr) throws XMLStreamException {
0x           consumer.add(createAttribute(attr));
0x       }
      
      /**
       * Constructs a STAX {@link javax.xml.stream.events.Attribute} event from
       * a DOM4J {@link Attribute}.
       *
       * @param attr The {@link Attribute} from which to construct the event.
       * @return The newly constructed {@link javax.xml.stream.events.Attribute}
       *         event.
       */
      public javax.xml.stream.events.Attribute createAttribute(Attribute attr) {
0x           QName attrName = createQName(attr.getQName());
0x           String value = attr.getValue();
          
0x           return factory.createAttribute(attrName, value);
      }
      
      /**
       * Writes a DOM4J {@link Namespace} to the stream.
       *
       * @param ns The {@link Namespace} to write to the stream.
       * @throws XMLStreamException If an error occurs writing to the stream.
       */
      public void writeNamespace(Namespace ns) throws XMLStreamException {
0x           consumer.add(createNamespace(ns));
0x       }
      
      /**
       * Constructs a STAX {@link javax.xml.stream.events.Namespace} event from
       * a DOM4J {@link Namespace}.
       *
       * @param ns The {@link Namespace} from which to construct the event.
       * @return The constructed {@link javax.xml.stream.events.Namespace} event.
       */
      public javax.xml.stream.events.Namespace createNamespace(Namespace ns) {
0x           String prefix = ns.getPrefix();
0x           String uri = ns.getURI();
          
0x           return factory.createNamespace(prefix, uri);
      }
      
      /**
       * Writes a DOM4J {@link Text} to the stream.
       *
       * @param text The {@link Text} to write to the stream.
       * @throws XMLStreamException If an error occurs writing to the stream.
       */
      public void writeText(Text text) throws XMLStreamException {
0x           consumer.add(createCharacters(text));
0x       }
      
      /**
       * Constructs a STAX {@link Characters} event from a DOM4J {@link Text}.
       *
       * @param text The {@link Text} from which to construct the event.
       * @return The constructed {@link Characters} event.
       */
      public Characters createCharacters(Text text) {
0x           return factory.createCharacters(text.getText());
      }
      
      /**
       * Writes a DOM4J {@link CDATA} to the event stream.
       *
       * @param cdata The {@link CDATA} to write to the stream.
       * @throws XMLStreamException If an error occurs writing to the stream.
       */
      public void writeCDATA(CDATA cdata) throws XMLStreamException {
0x           consumer.add(createCharacters(cdata));
0x       }
      
      /**
       * Constructs a STAX {@link Characters} event from a DOM4J {@link CDATA}.
       *
       * @param cdata The {@link CDATA} from which to construct the event.
       * @return The newly constructed {@link Characters} event.
       */
      public Characters createCharacters(CDATA cdata) {
0x           return factory.createCData(cdata.getText());
      }
      
      /**
       * Writes a DOM4J {@link Comment} to the stream.
       *
       * @param comment The {@link Comment} to write to the stream.
       * @throws XMLStreamException If an error occurs writing to the stream.
       */
      public void writeComment(Comment comment) throws XMLStreamException {
0x           consumer.add(createComment(comment));
0x       }
      
      /**
       * Constructs a STAX {@link javax.xml.stream.events.Comment} event from a
       * DOM4J {@link Comment}.
       *
       * @param comment The {@link Comment} from which to construct the event.
       * @return The constructed {@link javax.xml.stream.events.Comment} event.
       */
      public javax.xml.stream.events.Comment createComment(Comment comment) {
0x           return factory.createComment(comment.getText());
      }
      
      /**
       * Writes a DOM4J {@link ProcessingInstruction} to the stream.
       *
       * @param pi The {@link ProcessingInstruction} to write to the stream.
       * @throws XMLStreamException If an error occurs writing to the stream.
       */
      public void writeProcessingInstruction(ProcessingInstruction pi) throws XMLStreamException {
0x           consumer.add(createProcessingInstruction(pi));
0x       }
      
      /**
       * Constructs a STAX {@link javax.xml.stream.events.ProcessingInstruction}
       * event from a DOM4J {@link ProcessingInstruction}.
       *
       * @param pi The {@link ProcessingInstruction} from which to construct the
       *        event.
       * @return The constructed
       *         {@link javax.xml.stream.events.ProcessingInstruction} event.
       */
      public javax.xml.stream.events.ProcessingInstruction createProcessingInstruction(
              ProcessingInstruction pi) {
          
0x           String target = pi.getTarget();
0x           String data = pi.getText();
          
0x           return factory.createProcessingInstruction(target, data);
      }
      
      /**
       * Writes a DOM4J {@link Entity} to the stream.
       *
       * @param entity The {@link Entity} to write to the stream.
       * @throws XMLStreamException If an error occurs writing to the stream.
       */
      public void writeEntity(Entity entity) throws XMLStreamException {
0x           consumer.add(createEntityReference(entity));
0x       }
      
      /**
       * Constructs a STAX {@link EntityReference} event from a DOM4J
       * {@link Entity}.
       *
       * @param entity The {@link Entity} from which to construct the event.
       * @return The constructed {@link EntityReference} event.
       */
      private EntityReference createEntityReference(Entity entity) {
0x           return factory.createEntityReference(entity.getName(), null);
      }
      
      /**
       * Writes a DOM4J {@link DocumentType} to the stream.
       *
       * @param docType The {@link DocumentType} to write to the stream.
       * @throws XMLStreamException If an error occurs writing to the stream.
       */
      public void writeDocumentType(DocumentType docType) throws XMLStreamException {
0x           consumer.add(createDTD(docType));
0x       }
      
      /**
       * Constructs a STAX {@link DTD} event from a DOM4J {@link DocumentType}.
       *
       * @param docType The {@link DocumentType} from which to construct the
       *        event.
       * @return The constructed {@link DTD} event.
       */
      public DTD createDTD(DocumentType docType) {
0x           StringWriter decl = new StringWriter();
          try {
0x               docType.write(decl);
          } catch (IOException e) {
0x               throw new RuntimeException("Error writing DTD", e);
0x           }
          
0x           return factory.createDTD(decl.toString());
      }
      
      /**
       * Writes a DOM4J {@link Document} node, and all its contents, to the
       * stream.
       *
       * @param doc The {@link Document} to write to the stream.
       * @throws XMLStreamException If an error occurs writing to the stream.
       */
      public void writeDocument(Document doc) throws XMLStreamException {
0x           consumer.add(createStartDocument(doc));
          
0x           writeChildNodes(doc);
          
0x           consumer.add(createEndDocument(doc));
0x       }
      
      /**
       * Constructs a STAX {@link StartDocument} event from a DOM4J
       * {@link Document}.
       *
       * @param doc The {@link Document} from which to construct the event.
       * @return The constructed {@link StartDocument} event.
       */
      public StartDocument createStartDocument(Document doc) {
0x           String encoding = doc.getXMLEncoding();
0/2 0x           if (encoding != null) {
0x               return factory.createStartDocument(encoding);
          } else {
0x               return factory.createStartDocument();
          }
      }