blob: e8cd45bc54a248b9aa10a450be1da1d5824c5d4d [file] [log] [blame]
/*
* Copyright (c) 1998, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// mmacivor - June 24/2009 - 1.0 - Initial implementation
package org.eclipse.persistence.oxm.record;
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.NamespaceResolver;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.record.DomToXMLStreamWriter;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
/**
* <p>Use this type of MarshalRecord when the marshal target is an XMLStreamWriter
* <p><code>
* XMLContext xmlContext = new XMLContext("session-name");<br>
* XMLMarshaller xmlMarshaller = xmlContext.createMarshaller();<br>
* XMLStreamWriterRecord writerRecord = new XMLStreamWriterRecord(xmlStreamWriter);<br>
* xmlMarshaller.marshal(myObject, writerRecord);<br>
* </code>
* @see org.eclipse.persistence.oxm.XMLMarshaller
*/
public class XMLStreamWriterRecord extends MarshalRecord {
private DomToXMLStreamWriter domToStreamWriter;
private Map<String, String> prefixMapping;
private NamespaceResolver namespaceResolver;
private XMLStreamWriter xmlStreamWriter;
public XMLStreamWriterRecord(XMLStreamWriter xmlStreamWriter) {
this.xmlStreamWriter = xmlStreamWriter;
}
public XMLStreamWriter getXMLStreamWriter() {
return xmlStreamWriter;
}
public void setXMLStreamWriter(XMLStreamWriter anXMLStreamWriter) {
this.xmlStreamWriter = anXMLStreamWriter;
}
private DomToXMLStreamWriter getDomToXMLStreamWriter() {
if(null == domToStreamWriter) {
domToStreamWriter = new DomToXMLStreamWriter();
}
return domToStreamWriter;
}
@Override
public void attribute(XPathFragment xPathFragment, NamespaceResolver namespaceResolver, String value) {
try {
String namespaceURI = xPathFragment.getNamespaceURI();
if(namespaceURI == null) {
xmlStreamWriter.writeAttribute(xPathFragment.getLocalName(), value);
} else {
String prefix = getPrefixForFragment(xPathFragment);
if(prefix == null) {
xmlStreamWriter.writeAttribute(namespaceURI, xPathFragment.getLocalName(), value);
} else {
xmlStreamWriter.writeAttribute(prefix, namespaceURI, xPathFragment.getLocalName(), value);
}
}
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void defaultNamespaceDeclaration(String defaultNamespace){
try{
xmlStreamWriter.writeDefaultNamespace(defaultNamespace);
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void namespaceDeclaration(String prefix, String namespaceURI){
try{
xmlStreamWriter.writeNamespace(prefix, namespaceURI);
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void attributeWithoutQName(String namespaceURI, String localName, String prefix, String value){
try {
if(namespaceURI == null || namespaceURI.length() == 0) {
xmlStreamWriter.writeAttribute(localName, value);
} else {
xmlStreamWriter.writeAttribute(xmlStreamWriter.getNamespaceContext().getPrefix(namespaceURI), namespaceURI, localName, value);
}
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void attribute(String namespaceURI, String localName, String name, String value) {
try {
if(namespaceURI == null || namespaceURI.length() == 0) {
xmlStreamWriter.writeAttribute(localName, value);
} else {
xmlStreamWriter.writeAttribute(xmlStreamWriter.getNamespaceContext().getPrefix(namespaceURI), namespaceURI, localName, value);
}
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void cdata(String value) {
try {
for (String part : MarshalRecord.splitCData(value)) {
xmlStreamWriter.writeCData(part);
}
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void characters(String value) {
try {
xmlStreamWriter.writeCharacters(value);
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public boolean isNamespaceAware() {
return true;
}
@Override
public void closeStartElement() {
}
@Override
public void openStartElement(XPathFragment xPathFragment, NamespaceResolver namespaceResolver) {
super.openStartElement(xPathFragment, namespaceResolver);
try {
String namespaceURI = xPathFragment.getNamespaceURI();
if(namespaceURI == null) {
NamespaceContext namespaceContext = xmlStreamWriter.getNamespaceContext();
if(null == namespaceContext) {
xmlStreamWriter.writeStartElement(xPathFragment.getLocalName());
} else {
String defaultNamespace = namespaceContext.getNamespaceURI(Constants.EMPTY_STRING);
xmlStreamWriter.writeStartElement(Constants.EMPTY_STRING, xPathFragment.getLocalName(), Constants.EMPTY_STRING);
if(defaultNamespace != null && defaultNamespace.length() > 0 ) {
xmlStreamWriter.writeDefaultNamespace(Constants.EMPTY_STRING);
}
}
} else {
String prefix = getPrefixForFragment(xPathFragment);
if(prefix == null) {
prefix = Constants.EMPTY_STRING;
}
xmlStreamWriter.writeStartElement(prefix, xPathFragment.getLocalName(), namespaceURI);
if(xPathFragment.isGeneratedPrefix()){
namespaceDeclaration(xPathFragment.getPrefix(), xPathFragment.getNamespaceURI());
}
}
writePrefixMappings();
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void element(XPathFragment frag) {
try {
xmlStreamWriter.writeStartElement(getNameForFragment(frag));
xmlStreamWriter.writeEndElement();
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void endDocument() {
try {
xmlStreamWriter.writeEndDocument();
xmlStreamWriter.flush();
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void endElement(XPathFragment pathFragment, NamespaceResolver namespaceResolver) {
try {
xmlStreamWriter.writeEndElement();
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void node(Node node, NamespaceResolver resolver,String uri, String name) {
try {
if(node.getNodeType() == Node.DOCUMENT_NODE) {
node = ((Document)node).getDocumentElement();
}
getDomToXMLStreamWriter().writeToStream(node, uri, name , this.xmlStreamWriter);
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void startDocument(String encoding, String version) {
try {
if(Constants.DEFAULT_XML_ENCODING.equals(encoding)) {
xmlStreamWriter.writeStartDocument(version);
} else {
xmlStreamWriter.writeStartDocument(encoding, version);
}
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void startPrefixMapping(String prefix, String namespaceUri) {
if(null == this.prefixMapping) {
this.prefixMapping = new HashMap<>();
}
this.prefixMapping.put(prefix, namespaceUri);
}
private void writePrefixMappings() {
try {
if(null != namespaceResolver) {
String defaultNamespace = namespaceResolver.getDefaultNamespaceURI();
if(defaultNamespace != null) {
xmlStreamWriter.writeNamespace(Constants.EMPTY_STRING, defaultNamespace);
}
if(namespaceResolver.hasPrefixesToNamespaces()) {
for(Map.Entry<String, String> entry:this.namespaceResolver.getPrefixesToNamespaces().entrySet()) {
xmlStreamWriter.writeNamespace(entry.getKey(), entry.getValue());
}
}
namespaceResolver = null;
}
if(null != prefixMapping) {
for(Map.Entry<String, String> entry:this.prefixMapping.entrySet()) {
xmlStreamWriter.writeNamespace(entry.getKey(), entry.getValue());
}
prefixMapping = null;
}
} catch(XMLStreamException e) {
throw XMLMarshalException.marshalException(e);
}
}
@Override
public void namespaceDeclarations(NamespaceResolver namespaceResolver) {
}
@Override
public void startPrefixMappings(NamespaceResolver namespaceResolver) {
this.namespaceResolver = namespaceResolver;
}
}