1 /*
2  * Copyright (c) 2005, 2019, 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 XMLStreamWriter fStreamWriter;
55     private static final boolean DEBUG = false;
56 
57     /**
58      * Constructs an XMLEventWriterImpl that implements the standard XMLStreamWriter
59      * interface.
60      * @param streamWriter
61      */
XMLEventWriterImpl(XMLStreamWriter streamWriter)62     public XMLEventWriterImpl(XMLStreamWriter streamWriter) {
63         fStreamWriter = streamWriter;
64     }
65 
66     /**
67      *
68      * @param xMLEventReader
69      * @throws XMLStreamException
70      */
add(XMLEventReader xMLEventReader)71     public void add(XMLEventReader xMLEventReader) throws XMLStreamException {
72         if (xMLEventReader == null) {
73             throw new XMLStreamException("Event reader shouldn't be null");
74         }
75         while (xMLEventReader.hasNext()) {
76             add(xMLEventReader.nextEvent());
77         }
78     }
79 
80     /**
81      *
82      * @param xMLEvent
83      * @throws XMLStreamException
84      */
add(XMLEvent xMLEvent)85     public void add(XMLEvent xMLEvent) throws XMLStreamException {
86         int type = xMLEvent.getEventType();
87         switch (type) {
88             case XMLEvent.DTD: {
89                 DTD dtd = (DTD) xMLEvent;
90                 if (DEBUG) {
91                     System.out.println("Adding DTD = " + dtd.toString());
92                 }
93                 fStreamWriter.writeDTD(dtd.getDocumentTypeDeclaration());
94                 break;
95             }
96             case XMLEvent.START_DOCUMENT: {
97                 StartDocument startDocument = (StartDocument) xMLEvent;
98                 if (DEBUG) {
99                     System.out.println("Adding StartDocument = " + startDocument.toString());
100                 }
101                 try {
102                     if (XMLStreamWriterBase.class.isAssignableFrom(fStreamWriter.getClass())) {
103                         // internal impl uses the extended interface
104                         ((XMLStreamWriterBase)fStreamWriter).writeStartDocument(
105                                 startDocument.getCharacterEncodingScheme(),
106                                 startDocument.getVersion(),
107                                 startDocument.isStandalone(),
108                                 startDocument.standaloneSet());
109                     } else {
110                         fStreamWriter.writeStartDocument(
111                                 startDocument.getCharacterEncodingScheme(),
112                                 startDocument.getVersion());
113                     }
114                 } catch (XMLStreamException e) {
115                     fStreamWriter.writeStartDocument(startDocument.getVersion());
116                 }
117                 break;
118             }
119             case XMLEvent.START_ELEMENT: {
120                 StartElement startElement = xMLEvent.asStartElement();
121                 if (DEBUG) {
122                     System.out.println("Adding startelement = " + startElement.toString());
123                 }
124                 QName qname = startElement.getName();
125                 fStreamWriter.writeStartElement(qname.getPrefix(), qname.getLocalPart(),
126                         qname.getNamespaceURI());
127 
128                 /*
129                   getNamespaces() Returns an Iterator of namespaces declared on this element.
130                 This Iterator does not contain previously declared namespaces unless they
131                 appear on the current START_ELEMENT. Therefore this list may contain redeclared
132                 namespaces and duplicate namespace declarations. Use the getNamespaceContext()
133                 method to get the current context of namespace declarations. We should be
134                 using getNamespaces() to write namespace declarations for this START_ELEMENT
135                 */
136                 Iterator<? extends Namespace> iterator = startElement.getNamespaces();
137                 while (iterator.hasNext()) {
138                     Namespace namespace = iterator.next();
139                     fStreamWriter.writeNamespace(namespace.getPrefix(), namespace.getNamespaceURI());
140                 }
141                 //REVISIT: What about writing attributes ?
142                 Iterator<? extends Attribute> attributes = startElement.getAttributes();
143                 while (attributes.hasNext()) {
144                     Attribute attribute = attributes.next();
145                     QName aqname = attribute.getName();
146                     fStreamWriter.writeAttribute(aqname.getPrefix(), aqname.getNamespaceURI(),
147                             aqname.getLocalPart(), attribute.getValue());
148                 }
149                 break;
150             }
151             case XMLEvent.NAMESPACE: {
152                 Namespace namespace = (Namespace) xMLEvent;
153                 if (DEBUG) {
154                     System.out.println("Adding namespace = " + namespace.toString());
155                 }
156                 fStreamWriter.writeNamespace(namespace.getPrefix(), namespace.getNamespaceURI());
157                 break;
158             }
159             case XMLEvent.COMMENT: {
160                 Comment comment = (Comment) xMLEvent;
161                 if (DEBUG) {
162                     System.out.println("Adding comment = " + comment.toString());
163                 }
164                 fStreamWriter.writeComment(comment.getText());
165                 break;
166             }
167             case XMLEvent.PROCESSING_INSTRUCTION: {
168                 ProcessingInstruction processingInstruction = (ProcessingInstruction) xMLEvent;
169                 if (DEBUG) {
170                     System.out.println("Adding processing instruction = " + processingInstruction.toString());
171                 }
172                 fStreamWriter.writeProcessingInstruction(processingInstruction.getTarget(),
173                         processingInstruction.getData());
174                 break;
175             }
176             case XMLEvent.CHARACTERS: {
177                 Characters characters = xMLEvent.asCharacters();
178                 if (DEBUG) {
179                     System.out.println("Adding characters = " + characters.toString());
180                 }
181                 //check if the CHARACTERS are CDATA
182                 if (characters.isCData()) {
183                     fStreamWriter.writeCData(characters.getData());
184                 } else {
185                     fStreamWriter.writeCharacters(characters.getData());
186                 }
187                 break;
188             }
189             case XMLEvent.ENTITY_REFERENCE: {
190                 EntityReference entityReference = (EntityReference) xMLEvent;
191                 if (DEBUG) {
192                     System.out.println("Adding Entity Reference = " + entityReference.toString());
193                 }
194                 fStreamWriter.writeEntityRef(entityReference.getName());
195                 break;
196             }
197             case XMLEvent.ATTRIBUTE: {
198                 Attribute attribute = (Attribute) xMLEvent;
199                 if (DEBUG) {
200                     System.out.println("Adding Attribute = " + attribute.toString());
201                 }
202                 QName qname = attribute.getName();
203                 fStreamWriter.writeAttribute(qname.getPrefix(), qname.getNamespaceURI(),
204                         qname.getLocalPart(), attribute.getValue());
205                 break;
206             }
207             case XMLEvent.CDATA: {
208                 //there is no separate CDATA datatype but CDATA event can be reported
209                 //by using vendor specific CDATA property.
210                 Characters characters = (Characters) xMLEvent;
211                 if (DEBUG) {
212                     System.out.println("Adding characters = " + characters.toString());
213                 }
214                 if (characters.isCData()) {
215                     fStreamWriter.writeCData(characters.getData());
216                 }
217                 break;
218             }
219             //xxx: Why there isn't any event called Notation.
220             //case XMLEvent.NOTATION_DECLARATION:{
221             //}
222 
223             case XMLEvent.END_ELEMENT: {
224                 fStreamWriter.writeEndElement();
225                 break;
226             }
227             case XMLEvent.END_DOCUMENT: {
228                 fStreamWriter.writeEndDocument();
229                 break;
230             }
231             //throw new XMLStreamException("Unknown Event type = " + type);
232         };
233 
234     }
235 
236     /**
237      *
238      * @throws XMLStreamException
239      */
close()240     public void close() throws XMLStreamException {
241         fStreamWriter.close();
242     }
243 
244     /**
245      *
246      * @throws XMLStreamException will inturn call flush on the stream to which
247      * data is being written.
248      */
flush()249     public void flush() throws XMLStreamException {
250         fStreamWriter.flush();
251     }
252 
253     /**
254      *
255      * @return
256      */
getNamespaceContext()257     public NamespaceContext getNamespaceContext() {
258         return fStreamWriter.getNamespaceContext();
259     }
260 
261     /**
262      *
263      * @param namespaceURI Namespace URI
264      * @throws XMLStreamException
265      * @return prefix associated with the URI.
266      */
getPrefix(String namespaceURI)267     public String getPrefix(String namespaceURI) throws XMLStreamException {
268         return fStreamWriter.getPrefix(namespaceURI);
269     }
270 
271     /**
272      *
273      * @param uri Namespace URI
274      * @throws XMLStreamException
275      */
setDefaultNamespace(String uri)276     public void setDefaultNamespace(String uri) throws XMLStreamException {
277         fStreamWriter.setDefaultNamespace(uri);
278     }
279 
280     /**
281      *
282      * @param namespaceContext Namespace Context
283      * @throws XMLStreamException
284      */
setNamespaceContext(NamespaceContext namespaceContext)285     public void setNamespaceContext(NamespaceContext namespaceContext)
286             throws XMLStreamException {
287         fStreamWriter.setNamespaceContext(namespaceContext);
288     }
289 
290     /**
291      *
292      * @param prefix namespace prefix associated with the uri.
293      * @param uri Namespace URI
294      * @throws XMLStreamException
295      */
setPrefix(String prefix, String uri)296     public void setPrefix(String prefix, String uri) throws XMLStreamException {
297         fStreamWriter.setPrefix(prefix, uri);
298     }
299 
300 }//XMLEventWriterImpl
301