1 /*
   2  * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.xml.internal.stream.writers;
  27 
  28 import java.util.Iterator;
  29 import javax.xml.namespace.NamespaceContext;
  30 import javax.xml.namespace.QName;
  31 import javax.xml.stream.XMLEventReader;
  32 import javax.xml.stream.XMLEventWriter;
  33 import javax.xml.stream.XMLStreamException;
  34 import javax.xml.stream.XMLStreamWriter;
  35 import javax.xml.stream.events.Attribute;
  36 import javax.xml.stream.events.Characters;
  37 import javax.xml.stream.events.Comment;
  38 import javax.xml.stream.events.DTD;
  39 import javax.xml.stream.events.EntityReference;
  40 import javax.xml.stream.events.Namespace;
  41 import javax.xml.stream.events.ProcessingInstruction;
  42 import javax.xml.stream.events.StartDocument;
  43 import javax.xml.stream.events.StartElement;
  44 import javax.xml.stream.events.XMLEvent;
  45 
  46 /**
  47  *
  48  * @author Neeraj Bajaj, Sun Microsystems.
  49  *
  50  */
  51 public class XMLEventWriterImpl implements XMLEventWriter {
  52 
  53     //delegate everything to XMLStreamWriter..
  54     private final XMLStreamWriterBase fStreamWriter;
  55     private static final boolean DEBUG = false;
  56 
  57     /**
  58      *
  59      * @param streamWriter
  60      */
  61     public XMLEventWriterImpl(XMLStreamWriter streamWriter) {
  62         fStreamWriter = (XMLStreamWriterBase) streamWriter;
  63     }
  64 
  65     /**
  66      *
  67      * @param xMLEventReader
  68      * @throws XMLStreamException
  69      */
  70     public void add(XMLEventReader xMLEventReader) throws XMLStreamException {
  71         if (xMLEventReader == null) {
  72             throw new XMLStreamException("Event reader shouldn't be null");
  73         }
  74         while (xMLEventReader.hasNext()) {
  75             add(xMLEventReader.nextEvent());
  76         }
  77     }
  78 
  79     /**
  80      *
  81      * @param xMLEvent
  82      * @throws XMLStreamException
  83      */
  84     public void add(XMLEvent xMLEvent) throws XMLStreamException {
  85         int type = xMLEvent.getEventType();
  86         switch (type) {
  87             case XMLEvent.DTD: {
  88                 DTD dtd = (DTD) xMLEvent;
  89                 if (DEBUG) {
  90                     System.out.println("Adding DTD = " + dtd.toString());
  91                 }
  92                 fStreamWriter.writeDTD(dtd.getDocumentTypeDeclaration());
  93                 break;
  94             }
  95             case XMLEvent.START_DOCUMENT: {
  96                 StartDocument startDocument = (StartDocument) xMLEvent;
  97                 if (DEBUG) {
  98                     System.out.println("Adding StartDocument = " + startDocument.toString());
  99                 }
 100                 try {
 101                     fStreamWriter.writeStartDocument(startDocument.getCharacterEncodingScheme(),
 102                             startDocument.getVersion(),
 103                             startDocument.isStandalone(), startDocument.standaloneSet());
 104                 } catch (XMLStreamException e) {
 105                     fStreamWriter.writeStartDocument(startDocument.getVersion());
 106                 }
 107                 break;
 108             }
 109             case XMLEvent.START_ELEMENT: {
 110                 StartElement startElement = xMLEvent.asStartElement();
 111                 if (DEBUG) {
 112                     System.out.println("Adding startelement = " + startElement.toString());
 113                 }
 114                 QName qname = startElement.getName();
 115                 fStreamWriter.writeStartElement(qname.getPrefix(), qname.getLocalPart(),
 116                         qname.getNamespaceURI());
 117 
 118                 /*
 119                   getNamespaces() Returns an Iterator of namespaces declared on this element.
 120                 This Iterator does not contain previously declared namespaces unless they
 121                 appear on the current START_ELEMENT. Therefore this list may contain redeclared
 122                 namespaces and duplicate namespace declarations. Use the getNamespaceContext()
 123                 method to get the current context of namespace declarations. We should be
 124                 using getNamespaces() to write namespace declarations for this START_ELEMENT
 125                 */
 126                 Iterator<? extends Namespace> iterator = startElement.getNamespaces();
 127                 while (iterator.hasNext()) {
 128                     Namespace namespace = iterator.next();
 129                     fStreamWriter.writeNamespace(namespace.getPrefix(), namespace.getNamespaceURI());
 130                 }
 131                 //REVISIT: What about writing attributes ?
 132                 Iterator<? extends Attribute> attributes = startElement.getAttributes();
 133                 while (attributes.hasNext()) {
 134                     Attribute attribute = attributes.next();
 135                     QName aqname = attribute.getName();
 136                     fStreamWriter.writeAttribute(aqname.getPrefix(), aqname.getNamespaceURI(),
 137                             aqname.getLocalPart(), attribute.getValue());
 138                 }
 139                 break;
 140             }
 141             case XMLEvent.NAMESPACE: {
 142                 Namespace namespace = (Namespace) xMLEvent;
 143                 if (DEBUG) {
 144                     System.out.println("Adding namespace = " + namespace.toString());
 145                 }
 146                 fStreamWriter.writeNamespace(namespace.getPrefix(), namespace.getNamespaceURI());
 147                 break;
 148             }
 149             case XMLEvent.COMMENT: {
 150                 Comment comment = (Comment) xMLEvent;
 151                 if (DEBUG) {
 152                     System.out.println("Adding comment = " + comment.toString());
 153                 }
 154                 fStreamWriter.writeComment(comment.getText());
 155                 break;
 156             }
 157             case XMLEvent.PROCESSING_INSTRUCTION: {
 158                 ProcessingInstruction processingInstruction = (ProcessingInstruction) xMLEvent;
 159                 if (DEBUG) {
 160                     System.out.println("Adding processing instruction = " + processingInstruction.toString());
 161                 }
 162                 fStreamWriter.writeProcessingInstruction(processingInstruction.getTarget(),
 163                         processingInstruction.getData());
 164                 break;
 165             }
 166             case XMLEvent.CHARACTERS: {
 167                 Characters characters = xMLEvent.asCharacters();
 168                 if (DEBUG) {
 169                     System.out.println("Adding characters = " + characters.toString());
 170                 }
 171                 //check if the CHARACTERS are CDATA
 172                 if (characters.isCData()) {
 173                     fStreamWriter.writeCData(characters.getData());
 174                 } else {
 175                     fStreamWriter.writeCharacters(characters.getData());
 176                 }
 177                 break;
 178             }
 179             case XMLEvent.ENTITY_REFERENCE: {
 180                 EntityReference entityReference = (EntityReference) xMLEvent;
 181                 if (DEBUG) {
 182                     System.out.println("Adding Entity Reference = " + entityReference.toString());
 183                 }
 184                 fStreamWriter.writeEntityRef(entityReference.getName());
 185                 break;
 186             }
 187             case XMLEvent.ATTRIBUTE: {
 188                 Attribute attribute = (Attribute) xMLEvent;
 189                 if (DEBUG) {
 190                     System.out.println("Adding Attribute = " + attribute.toString());
 191                 }
 192                 QName qname = attribute.getName();
 193                 fStreamWriter.writeAttribute(qname.getPrefix(), qname.getNamespaceURI(),
 194                         qname.getLocalPart(), attribute.getValue());
 195                 break;
 196             }
 197             case XMLEvent.CDATA: {
 198                 //there is no separate CDATA datatype but CDATA event can be reported
 199                 //by using vendor specific CDATA property.
 200                 Characters characters = (Characters) xMLEvent;
 201                 if (DEBUG) {
 202                     System.out.println("Adding characters = " + characters.toString());
 203                 }
 204                 if (characters.isCData()) {
 205                     fStreamWriter.writeCData(characters.getData());
 206                 }
 207                 break;
 208             }
 209             //xxx: Why there isn't any event called Notation.
 210             //case XMLEvent.NOTATION_DECLARATION:{
 211             //}
 212 
 213             case XMLEvent.END_ELEMENT: {
 214                 fStreamWriter.writeEndElement();
 215                 break;
 216             }
 217             case XMLEvent.END_DOCUMENT: {
 218                 fStreamWriter.writeEndDocument();
 219                 break;
 220             }
 221             //throw new XMLStreamException("Unknown Event type = " + type);
 222         };
 223 
 224     }
 225 
 226     /**
 227      *
 228      * @throws XMLStreamException
 229      */
 230     public void close() throws XMLStreamException {
 231         fStreamWriter.close();
 232     }
 233 
 234     /**
 235      *
 236      * @throws XMLStreamException will inturn call flush on the stream to which
 237      * data is being written.
 238      */
 239     public void flush() throws XMLStreamException {
 240         fStreamWriter.flush();
 241     }
 242 
 243     /**
 244      *
 245      * @return
 246      */
 247     public NamespaceContext getNamespaceContext() {
 248         return fStreamWriter.getNamespaceContext();
 249     }
 250 
 251     /**
 252      *
 253      * @param namespaceURI Namespace URI
 254      * @throws XMLStreamException
 255      * @return prefix associated with the URI.
 256      */
 257     public String getPrefix(String namespaceURI) throws XMLStreamException {
 258         return fStreamWriter.getPrefix(namespaceURI);
 259     }
 260 
 261     /**
 262      *
 263      * @param uri Namespace URI
 264      * @throws XMLStreamException
 265      */
 266     public void setDefaultNamespace(String uri) throws XMLStreamException {
 267         fStreamWriter.setDefaultNamespace(uri);
 268     }
 269 
 270     /**
 271      *
 272      * @param namespaceContext Namespace Context
 273      * @throws XMLStreamException
 274      */
 275     public void setNamespaceContext(NamespaceContext namespaceContext)
 276             throws XMLStreamException {
 277         fStreamWriter.setNamespaceContext(namespaceContext);
 278     }
 279 
 280     /**
 281      *
 282      * @param prefix namespace prefix associated with the uri.
 283      * @param uri Namespace URI
 284      * @throws XMLStreamException
 285      */
 286     public void setPrefix(String prefix, String uri) throws XMLStreamException {
 287         fStreamWriter.setPrefix(prefix, uri);
 288     }
 289 
 290 }//XMLEventWriterImpl