Package com.envoisolutions.sxc.jaxb

Source Code of com.envoisolutions.sxc.jaxb.MarshallerImpl

/**
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package com.envoisolutions.sxc.jaxb;

import java.util.HashMap;
import java.util.Map;
import java.util.Calendar;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.MarshalException;
import javax.xml.bind.ValidationEvent;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.attachment.AttachmentMarshaller;
import javax.xml.bind.helpers.AbstractMarshallerImpl;
import javax.xml.bind.helpers.ValidationEventImpl;
import javax.xml.datatype.Duration;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Result;
import javax.xml.transform.dom.DOMResult;
import javax.xml.validation.Schema;

import com.envoisolutions.sxc.util.PrettyPrintXMLStreamWriter;
import com.envoisolutions.sxc.util.RuntimeXMLStreamException;
import com.envoisolutions.sxc.util.W3CDOMStreamWriter;
import com.envoisolutions.sxc.util.XoXMLStreamWriter;
import com.envoisolutions.sxc.util.XoXMLStreamWriterImpl;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

public class MarshallerImpl extends AbstractMarshallerImpl {
  public static final String MARSHALLER = "sxc.marshaller";

    private final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
    private final JAXBIntrospectorImpl introspector;

    private final Map<Class<?>, ? super XmlAdapter> adapters = new HashMap<Class<?>, XmlAdapter>();
    private AttachmentMarshaller attachmentMarshaller;
    private Listener listener;
    private Schema schema;

    public MarshallerImpl(JAXBIntrospectorImpl introspector) {
        this.introspector = introspector;
    }

    public void marshal(Object jaxbElement, Result result) throws JAXBException {
        if (jaxbElement == null) throw new IllegalArgumentException("jaxbElement is null");
        if (result == null) throw new IllegalArgumentException("result is null");
        XMLStreamWriter writer = null;
        try {
            if (result instanceof DOMResult) {
                Node node = ((DOMResult) result).getNode();

                if (node instanceof Document) {
                    writer = new W3CDOMStreamWriter((Document) node);
                } else if (node instanceof Element) {
                    writer = new W3CDOMStreamWriter((Element) node);
                } else {
                    throw new UnsupportedOperationException("Node type not supported.");
                }
            } else {
                writer = xmlOutputFactory.createXMLStreamWriter(result);
            }
            marshal(jaxbElement, writer);
        } catch (XMLStreamException e) {
            throw new JAXBException("Could not close XMLStreamWriter.", e);
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (XMLStreamException ignored) {
                }
            }
        }
    }

    public void marshal(Object jaxbElement, XMLEventWriter writer) throws JAXBException {
        // todo how do we convert XMLEventWriter into a XMLStreamWriter
        throw new UnsupportedOperationException();
    }

    public void marshal(Object jaxbElement, XMLStreamWriter writer) throws JAXBException {
        if (jaxbElement == null) throw new IllegalArgumentException("jaxbElement is null");
        if (writer == null) throw new IllegalArgumentException("xsw is null");

        if (!introspector.isElement(jaxbElement)) {
            throw new MarshalException("Object must be annotated with @XmlRootElement or be a JAXBElement!");
        }

        // if formatted output is set, use the pretty print wrapper
        if (isFormattedOutput()) {
            writer = new PrettyPrintXMLStreamWriter(writer);
        }

        // writer with out custom extension
        XoXMLStreamWriter w = new XoXMLStreamWriterImpl(writer);

        try {
            // if the is not a fragment, write the document header
            if (!isFragment()) {
                w.writeStartDocument(getEncoding(), null);
            }

            // write xsi:type if there is no default root element for this type
            boolean writeXsiType = true;
            if (jaxbElement instanceof JAXBElement) {
                writeXsiType = ((JAXBElement)jaxbElement).isTypeSubstituted();
            } else {
                JAXBObject jaxbObject = introspector.getJaxbMarshaller(jaxbElement.getClass());
                if (jaxbObject != null) {
                    writeXsiType = jaxbObject.getXmlRootElement() == null && jaxbObject.getXmlType() != null;
                }
            }

            write(jaxbElement, w, new RuntimeContext(this), true, writeXsiType);

            if (!isFragment()) {
                w.writeEndDocument();
            }
        } catch (XMLStreamException e) {
            throw new MarshalException(e);
        }
    }

    public void write(Object jaxbElement, XoXMLStreamWriter writer, RuntimeContext context, boolean writeTag, boolean writeXsiType) throws JAXBException {
        if (jaxbElement == null) throw new IllegalArgumentException("jaxbElement is null");
        if (writer == null) throw new IllegalArgumentException("writer is null");

        try {
            if (writeTag) {
                QName name;
                if (jaxbElement instanceof JAXBElement) {
                    JAXBElement element = (JAXBElement) jaxbElement;
                    writeXsiType = writeXsiType || element.isTypeSubstituted();
                    name = element.getName();

                    jaxbElement = element.getValue();
                } else if (jaxbElement instanceof Element) {
                    Element element = (Element) jaxbElement;

                    String namespaceURI = element.getNamespaceURI();
                    if (namespaceURI == null) namespaceURI = "";
                    name = new QName(namespaceURI, element.getLocalName());
                } else {
                    JAXBObject jaxbObject = introspector.getJaxbMarshaller(jaxbElement.getClass());
                    if (jaxbObject == null || jaxbObject.getXmlRootElement() == null) {
                        throw new MarshalException("Object must be annotated with @XmlRootElement or be a JAXBElement!");
                    }
                    name = jaxbObject.getXmlRootElement();
                }

                // open element
                writer.writeStartElementWithAutoPrefix(name.getNamespaceURI(), name.getLocalPart());
            }

            if (jaxbElement instanceof JAXBElement && ((JAXBElement) jaxbElement).isNil()) {
                // nil JAXBElement
                writer.writeXsiNil();
            } else if (jaxbElement != null) {
                Class<?> c = jaxbElement.getClass();
                if (c == String.class) {
                    writer.writeCharacters((String) jaxbElement);
                } else if (c == Boolean.class) {
                    writer.writeBoolean((Boolean) jaxbElement);
                } else if (c == Byte.class) {
                    writer.writeByte((Byte) jaxbElement);
                } else if (c == Double.class) {
                    writer.writeDouble((Double) jaxbElement);
                } else if (c == Float.class) {
                    writer.writeFloat((Float) jaxbElement);
                } else if (c == Long.class) {
                    writer.writeLong((Long) jaxbElement);
                } else if (c == Integer.class) {
                    writer.writeInt((Integer) jaxbElement);
                } else if (c == Short.class) {
                    writer.writeShort((Short) jaxbElement);
                } else if (Duration.class.isAssignableFrom(c)) {
                    writer.writeCharacters(jaxbElement.toString());
                } else if (XMLGregorianCalendar.class.isAssignableFrom(c)) {
                    writer.writeCharacters(((XMLGregorianCalendar) jaxbElement).toXMLFormat());
                } else if (Calendar.class.isAssignableFrom(c)) {
                    StandardJAXBObjects.CalendarJAXB.INSTANCE.write(writer, (Calendar) jaxbElement, context);
                } else if (c == byte[].class) {
                    BinaryUtils.encodeBytes(writer, (byte[]) jaxbElement);
                } else if (Element.class.isAssignableFrom(c)) {
                    writer.writeDomElement((Element) jaxbElement, false);
                } else {
                    JAXBObject jaxbObject = introspector.getJaxbMarshaller(c);
                    if (jaxbObject != null) {
                        if (writeXsiType) {
                            writer.writeXsiType(jaxbObject.getXmlType().getNamespaceURI(), jaxbObject.getXmlType().getLocalPart());
                        }

                        //noinspection unchecked
                        jaxbObject.write(writer, jaxbElement, context);
                    } else {
                        String message = "No marshaller for " + c.getName();
                        if (getEventHandler() == null || !getEventHandler().handleEvent(new ValidationEventImpl(ValidationEvent.ERROR, message, new ValidationEventLocatorImpl(jaxbElement, null)))) {
                            throw new MarshalException(message);
                        }
                    }
                }
            }

            if (writeTag) {
                // close element
                writer.writeEndElement();
            }
        } catch (Exception e) {
            if (e instanceof JAXBException) {
                // assume event handler has already been notified
                throw (JAXBException) e;
            }
            if (e instanceof RuntimeXMLStreamException) {
                // simply unwrap and handle below
                e = ((RuntimeXMLStreamException) e).getCause();
            }

            // report fatal error
            if (getEventHandler() != null) {
                getEventHandler().handleEvent(new ValidationEventImpl(ValidationEvent.FATAL_ERROR, "Fatal error", new ValidationEventLocatorImpl(), e));
            }

            if (e instanceof XMLStreamException) {
                Throwable cause = e.getCause();
                if (cause instanceof JAXBException) {
                    throw (JAXBException) e;
                }
                throw new MarshalException(cause == null ? e : cause);
            }
            throw new MarshalException(e);

        }
    }

    @SuppressWarnings({"unchecked"})
    public <A extends XmlAdapter> A getAdapter(Class<A> type) {
        return (A) adapters.get(type);
    }

    public <A extends XmlAdapter> void setAdapter(Class<A> type, A adapter) {
        adapters.put(type, adapter);
    }

    public AttachmentMarshaller getAttachmentMarshaller() {
        return attachmentMarshaller;
    }

    public void setAttachmentMarshaller(AttachmentMarshaller attachmentMarshaller) {
        this.attachmentMarshaller = attachmentMarshaller;
    }

    public Listener getListener() {
        return listener;
    }

    public void setListener(Listener listener) {
        this.listener = listener;
    }

    public Schema getSchema() {
        return schema;
    }

    public void setSchema(Schema schema) {
        this.schema = schema;
    }
}
TOP

Related Classes of com.envoisolutions.sxc.jaxb.MarshallerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.