Clover coverage report - dom4j - 1.6.1
Coverage timestamp: ma mei 16 2005 14:23:01 GMT+01:00
file stats: LOC: 679   Methods: 24
NCLOC: 270   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
STAXEventReader.java 32,7% 47,6% 41,7% 43,1%
coverage coverage
 1    /*
 2    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
 3    *
 4    * This software is open source.
 5    * See the bottom of this file for the licence.
 6    */
 7   
 8    package org.dom4j.io;
 9   
 10    import java.io.InputStream;
 11    import java.io.Reader;
 12    import java.util.Iterator;
 13   
 14    import javax.xml.namespace.QName;
 15    import javax.xml.stream.XMLEventReader;
 16    import javax.xml.stream.XMLInputFactory;
 17    import javax.xml.stream.XMLStreamConstants;
 18    import javax.xml.stream.XMLStreamException;
 19    import javax.xml.stream.events.Attribute;
 20    import javax.xml.stream.events.Characters;
 21    import javax.xml.stream.events.Comment;
 22    import javax.xml.stream.events.EndElement;
 23    import javax.xml.stream.events.EntityReference;
 24    import javax.xml.stream.events.Namespace;
 25    import javax.xml.stream.events.ProcessingInstruction;
 26    import javax.xml.stream.events.StartDocument;
 27    import javax.xml.stream.events.StartElement;
 28    import javax.xml.stream.events.XMLEvent;
 29   
 30    import org.dom4j.CharacterData;
 31    import org.dom4j.Document;
 32    import org.dom4j.DocumentFactory;
 33    import org.dom4j.Element;
 34    import org.dom4j.Entity;
 35    import org.dom4j.Node;
 36   
 37    /**
 38    * Reads a DOM4J {@link Document}, as well as other {@link Node}s, from a StAX
 39    * {@link XMLEventReader}.
 40    *
 41    * @author Christian Niles
 42    */
 43    public class STAXEventReader {
 44    /** Reference to the DocumentFactory used to build DOM4J nodes. */
 45    private DocumentFactory factory;
 46   
 47    /** A StAX input factory, used to construct streams from IO streams. */
 48    private XMLInputFactory inputFactory = XMLInputFactory.newInstance();
 49   
 50    /**
 51    * Constructs a default <code>STAXEventReader</code> instance with a
 52    * default {@link DocumentFactory}.
 53    */
 54  1 public STAXEventReader() {
 55  1 this.factory = DocumentFactory.getInstance();
 56    }
 57   
 58    /**
 59    * Constructs a <code>STAXEventReader</code> instance that uses the
 60    * specified {@link DocumentFactory}to construct DOM4J {@link Node}s.
 61    *
 62    * @param factory
 63    * The DocumentFactory to use when constructing DOM4J nodes, or
 64    * <code>null</code> if a default should be used.
 65    */
 66  0 public STAXEventReader(DocumentFactory factory) {
 67  0 if (factory != null) {
 68  0 this.factory = factory;
 69    } else {
 70  0 this.factory = DocumentFactory.getInstance();
 71    }
 72    }
 73   
 74    /**
 75    * Sets the DocumentFactory to be used when constructing DOM4J nodes.
 76    *
 77    * @param documentFactory
 78    * The DocumentFactory to use when constructing DOM4J nodes, or
 79    * <code>null</code> if a default should be used.
 80    */
 81  0 public void setDocumentFactory(DocumentFactory documentFactory) {
 82  0 if (documentFactory != null) {
 83  0 this.factory = documentFactory;
 84    } else {
 85  0 this.factory = DocumentFactory.getInstance();
 86    }
 87    }
 88   
 89    /**
 90    * Constructs a StAX event stream from the provided I/O stream and reads a
 91    * DOM4J document from it.
 92    *
 93    * @param is
 94    * The I/O stream from which the Document will be read.
 95    *
 96    * @return The Document that was read from the stream.
 97    *
 98    * @throws XMLStreamException
 99    * If an error occurs reading content from the stream.
 100    */
 101  0 public Document readDocument(InputStream is) throws XMLStreamException {
 102  0 return readDocument(is, null);
 103    }
 104   
 105    /**
 106    * Constructs a StAX event stream from the provided I/O character stream and
 107    * reads a DOM4J document from it.
 108    *
 109    * @param reader
 110    * The character stream from which the Document will be read.
 111    *
 112    * @return The Document that was read from the stream.
 113    *
 114    * @throws XMLStreamException
 115    * If an error occurs reading content from the stream.
 116    */
 117  1 public Document readDocument(Reader reader) throws XMLStreamException {
 118  1 return readDocument(reader, null);
 119    }
 120   
 121    /**
 122    * Constructs a StAX event stream from the provided I/O stream and reads a
 123    * DOM4J document from it.
 124    *
 125    * @param is
 126    * The I/O stream from which the Document will be read.
 127    * @param systemId
 128    * A system id used to resolve entities.
 129    *
 130    * @return The Document that was read from the stream.
 131    *
 132    * @throws XMLStreamException
 133    * If an error occurs reading content from the stream.
 134    */
 135  0 public Document readDocument(InputStream is, String systemId)
 136    throws XMLStreamException {
 137  0 XMLEventReader eventReader = inputFactory.createXMLEventReader(
 138    systemId, is);
 139   
 140  0 try {
 141  0 return readDocument(eventReader);
 142    } finally {
 143  0 eventReader.close();
 144    }
 145    }
 146   
 147    /**
 148    * Constructs a StAX event stream from the provided I/O character stream and
 149    * reads a DOM4J document from it.
 150    *
 151    * @param reader
 152    * The character stream from which the Document will be read.
 153    * @param systemId
 154    * A system id used to resolve entities.
 155    *
 156    * @return The Document that was read from the stream.
 157    *
 158    * @throws XMLStreamException
 159    * If an error occurs reading content from the stream.
 160    */
 161  1 public Document readDocument(Reader reader, String systemId)
 162    throws XMLStreamException {
 163  1 XMLEventReader eventReader = inputFactory.createXMLEventReader(
 164    systemId, reader);
 165   
 166  1 try {
 167  1 return readDocument(eventReader);
 168    } finally {
 169  1 eventReader.close();
 170    }
 171    }
 172   
 173    /**
 174    * Reads a {@link Node}from the event stream. If the next event is a
 175    * {@link StartElement}, all events until the closing {@link EndElement}
 176    * will be read, and the resulting nodes will be added to the returned
 177    * {@link Element}.
 178    *
 179    * <p>
 180    * <strong>Pre-Conditions </strong>: The stream must be positioned before an
 181    * event other than an <code>EndElement</code>,<code>EndDocument</code>,
 182    * or any DTD-related events, which are not currently supported.
 183    * </p>
 184    *
 185    * @param reader
 186    * The reader from which events will be read.
 187    *
 188    * @return A DOM4J {@link Node}constructed from the read events.
 189    *
 190    * @throws XMLStreamException
 191    * If an error occurs reading from the stream, or the stream was
 192    * positioned before an unsupported event.
 193    */
 194  24 public Node readNode(XMLEventReader reader) throws XMLStreamException {
 195  24 XMLEvent event = reader.peek();
 196   
 197  24 if (event.isStartElement()) {
 198  8 return readElement(reader);
 199  16 } else if (event.isCharacters()) {
 200  16 return readCharacters(reader);
 201  0 } else if (event.isStartDocument()) {
 202  0 return readDocument(reader);
 203  0 } else if (event.isProcessingInstruction()) {
 204  0 return readProcessingInstruction(reader);
 205  0 } else if (event.isEntityReference()) {
 206  0 return readEntityReference(reader);
 207  0 } else if (event.isAttribute()) {
 208  0 return readAttribute(reader);
 209  0 } else if (event.isNamespace()) {
 210  0 return readNamespace(reader);
 211    } else {
 212  0 throw new XMLStreamException("Unsupported event: " + event);
 213    }
 214    }
 215   
 216    /**
 217    * Reads a DOM4J {@link Document}from the provided stream. The stream
 218    * should be positioned at the start of a document, or before a {@link
 219    * StartElement} event.
 220    *
 221    * @param reader
 222    * The event stream from which to read the {@link Document}.
 223    *
 224    * @return The {@link Document}that was read from the stream.
 225    *
 226    * @throws XMLStreamException
 227    * If an error occurs reading events from the stream.
 228    */
 229  1 public Document readDocument(XMLEventReader reader)
 230    throws XMLStreamException {
 231  1 Document doc = null;
 232   
 233  1 while (reader.hasNext()) {
 234  5 XMLEvent nextEvent = reader.peek();
 235  5 int type = nextEvent.getEventType();
 236   
 237  5 switch (type) {
 238  1 case XMLStreamConstants.START_DOCUMENT:
 239   
 240  1 StartDocument event = (StartDocument) reader.nextEvent();
 241   
 242  1 if (doc == null) {
 243    // create document
 244  1 if (event.encodingSet()) {
 245  1 String encodingScheme = event
 246    .getCharacterEncodingScheme();
 247  1 doc = factory.createDocument(encodingScheme);
 248    } else {
 249  0 doc = factory.createDocument();
 250    }
 251    } else {
 252    // duplicate or misplaced xml declaration
 253  0 String msg = "Unexpected StartDocument event";
 254  0 throw new XMLStreamException(msg, event.getLocation());
 255    }
 256   
 257  1 break;
 258   
 259  1 case XMLStreamConstants.END_DOCUMENT:
 260  0 case XMLStreamConstants.SPACE:
 261  2 case XMLStreamConstants.CHARACTERS:
 262   
 263    // skip end document and space outside the root element
 264  3 reader.nextEvent();
 265   
 266  3 break;
 267   
 268  1 default:
 269   
 270  1 if (doc == null) {
 271    // create document
 272  0 doc = factory.createDocument();
 273    }
 274   
 275  1 Node n = readNode(reader);
 276  1 doc.add(n);
 277    }
 278    }
 279   
 280  1 return doc;
 281    }
 282   
 283    /**
 284    * Reads a DOM4J Element from the provided event stream. The stream must be
 285    * positioned before an {@link StartElement}event. In addition to the
 286    * initial start event, all events up to and including the closing {@link
 287    * EndElement} will be read, and included with the returned element.
 288    *
 289    * @param eventReader
 290    * The event stream from which to read the Element.
 291    *
 292    * @return The Element that was read from the stream.
 293    *
 294    * @throws XMLStreamException
 295    * If an error occured reading events from the stream, or the
 296    * stream was not positioned before a {@linkStartElement}event.
 297    */
 298  8 public Element readElement(XMLEventReader eventReader)
 299    throws XMLStreamException {
 300  8 XMLEvent event = eventReader.peek();
 301   
 302  8 if (event.isStartElement()) {
 303    // advance the reader and get the StartElement event
 304  8 StartElement startTag = eventReader.nextEvent().asStartElement();
 305  8 Element elem = createElement(startTag);
 306   
 307    // read element content
 308  8 while (true) {
 309  31 if (!eventReader.hasNext()) {
 310  0 String msg = "Unexpected end of stream while reading"
 311    + " element content";
 312  0 throw new XMLStreamException(msg);
 313    }
 314   
 315  31 XMLEvent nextEvent = eventReader.peek();
 316   
 317  31 if (nextEvent.isEndElement()) {
 318  8 EndElement endElem = eventReader.nextEvent().asEndElement();
 319   
 320  8 if (!endElem.getName().equals(startTag.getName())) {
 321  0 throw new XMLStreamException("Expected "
 322    + startTag.getName() + " end-tag, but found"
 323    + endElem.getName());
 324    }
 325   
 326  8 break;
 327    }
 328   
 329  23 Node child = readNode(eventReader);
 330  23 elem.add(child);
 331    }
 332   
 333  8 return elem;
 334    } else {
 335  0 throw new XMLStreamException("Expected Element event, found: "
 336    + event);
 337    }
 338    }
 339   
 340    /**
 341    * Constructs a DOM4J Attribute from the provided event stream. The stream
 342    * must be positioned before an {@link Attribute}event.
 343    *
 344    * @param reader
 345    * The event stream from which to read the Attribute.
 346    *
 347    * @return The Attribute that was read from the stream.
 348    *
 349    * @throws XMLStreamException
 350    * If an error occured reading events from the stream, or the
 351    * stream was not positioned before an {@linkAttribute}event.
 352    */
 353  0 public org.dom4j.Attribute readAttribute(XMLEventReader reader)
 354    throws XMLStreamException {
 355  0 XMLEvent event = reader.peek();
 356   
 357  0 if (event.isAttribute()) {
 358  0 Attribute attr = (Attribute) reader.nextEvent();
 359   
 360  0 return createAttribute(null, attr);
 361    } else {
 362  0 throw new XMLStreamException("Expected Attribute event, found: "
 363    + event);
 364    }
 365    }
 366   
 367    /**
 368    * Constructs a DOM4J Namespace from the provided event stream. The stream
 369    * must be positioned before a {@link Namespace}event.
 370    *
 371    * @param reader
 372    * The event stream from which to read the Namespace.
 373    *
 374    * @return The Namespace that was read from the stream.
 375    *
 376    * @throws XMLStreamException
 377    * If an error occured reading events from the stream, or the
 378    * stream was not positioned before a {@linkNamespace}event.
 379    */
 380  0 public org.dom4j.Namespace readNamespace(XMLEventReader reader)
 381    throws XMLStreamException {
 382  0 XMLEvent event = reader.peek();
 383   
 384  0 if (event.isNamespace()) {
 385  0 Namespace ns = (Namespace) reader.nextEvent();
 386   
 387  0 return createNamespace(ns);
 388    } else {
 389  0 throw new XMLStreamException("Expected Namespace event, found: "
 390    + event);
 391    }
 392    }
 393   
 394    /**
 395    * Constructs a DOM4J Text or CDATA section from the provided event stream.
 396    * The stream must be positioned before a {@link Characters}event.
 397    *
 398    * @param reader
 399    * The event stream from which to read the Text or CDATA.
 400    *
 401    * @return The Text or CDATA that was read from the stream.
 402    *
 403    * @throws XMLStreamException
 404    * If an error occured reading events from the stream, or the
 405    * stream was not positioned before a {@linkCharacters}event.
 406    */
 407  16 public CharacterData readCharacters(XMLEventReader reader)
 408    throws XMLStreamException {
 409  16 XMLEvent event = reader.peek();
 410   
 411  16 if (event.isCharacters()) {
 412  16 Characters characters = reader.nextEvent().asCharacters();
 413   
 414  16 return createCharacterData(characters);
 415    } else {
 416  0 throw new XMLStreamException("Expected Characters event, found: "
 417    + event);
 418    }
 419    }
 420   
 421    /**
 422    * Constructs a DOM4J Comment from the provided event stream. The stream
 423    * must be positioned before a {@link Comment}event.
 424    *
 425    * @param reader
 426    * The event stream from which to read the Comment.
 427    *
 428    * @return The Comment that was read from the stream.
 429    *
 430    * @throws XMLStreamException
 431    * If an error occured reading events from the stream, or the
 432    * stream was not positioned before a {@linkComment}event.
 433    */
 434  0 public org.dom4j.Comment readComment(XMLEventReader reader)
 435    throws XMLStreamException {
 436  0 XMLEvent event = reader.peek();
 437   
 438  0 if (event instanceof Comment) {
 439  0 return createComment((Comment) reader.nextEvent());
 440    } else {
 441  0 throw new XMLStreamException("Expected Comment event, found: "
 442    + event);
 443    }
 444    }
 445   
 446    /**
 447    * Constructs a DOM4J Entity from the provided event stream. The stream must
 448    * be positioned before an {@link EntityReference}event.
 449    *
 450    * @param reader
 451    * The event stream from which to read the {@link
 452    * EntityReference}.
 453    *
 454    * @return The {@link org.dom4j.Entity}that was read from the stream.
 455    *
 456    * @throws XMLStreamException
 457    * If an error occured reading events from the stream, or the
 458    * stream was not positioned before an {@linkEntityReference}
 459    * event.
 460    */
 461  0 public Entity readEntityReference(XMLEventReader reader)
 462    throws XMLStreamException {
 463  0 XMLEvent event = reader.peek();
 464   
 465  0 if (event.isEntityReference()) {
 466  0 EntityReference entityRef = (EntityReference) reader.nextEvent();
 467   
 468  0 return createEntity(entityRef);
 469    } else {
 470  0 throw new XMLStreamException("Expected EntityRef event, found: "
 471    + event);
 472    }
 473    }
 474   
 475    /**
 476    * Constructs a DOM4J ProcessingInstruction from the provided event stream.
 477    * The stream must be positioned before a {@link ProcessingInstruction}
 478    * event.
 479    *
 480