/*
 * 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 org.apache.axis2.jibx;

import org.apache.axiom.om.OMDataSource;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.util.StAXUtils;
import org.jibx.runtime.IBindingFactory;
import org.jibx.runtime.IMarshallable;
import org.jibx.runtime.IMarshaller;
import org.jibx.runtime.IMarshallingContext;
import org.jibx.runtime.IXMLWriter;
import org.jibx.runtime.JiBXException;
import org.jibx.runtime.impl.StAXWriter;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;

/** Data source for OM element backed by JiBX data bound object. */
public class JiBXDataSource implements OMDataSource {
    /**
     * Marshaller index (only needed if object does not have a top-level mapping definition in the
     * binding, <code>-1</code> if not used).
     */
    private final int marshallerIndex;

    /** Element name (only used with {@link #marshallerIndex}). */
    private final String elementName;
    
    /** Element namespace URI (only used with {@link #marshallerIndex}). */
    private final String elementNamespace;

    /** Element namespace prefix (only used with {@link #marshallerIndex}). */
    private final String elementNamespacePrefix;
    
    /** Element namespace index (only used with {@link #marshallerIndex}). */
    private final int elementNamespaceIndex;

    /** Indexes of namespaces to be opened (only used with {@link #marshallerIndex}). */
    private final int[] openNamespaceIndexes;

    /** Prefixes of namespaces to be opened (only used with {@link #marshallerIndex}). */
    private final String[] openNamespacePrefixes;

    /** Data object for output. */
    private final Object dataObject;

    /** Binding factory for creating marshaller. */
    private final IBindingFactory bindingFactory;

    /**
     * Constructor from marshallable object and binding factory.
     *
     * @param obj
     * @param factory
     */
    public JiBXDataSource(IMarshallable obj, IBindingFactory factory) {
        marshallerIndex = -1;
        dataObject = obj;
        bindingFactory = factory;
        elementName = elementNamespace = elementNamespacePrefix = null;
        elementNamespaceIndex = -1;
        openNamespaceIndexes = null;
        openNamespacePrefixes = null;
    }

    /**
     * Constructor from object with mapping index and binding factory.
     *
     * @param obj
     * @param index
     * @param name
     * @param uri
     * @param prefix
     * @param nsindexes
     * @param nsprefixes
     * @param factory
     */
    public JiBXDataSource(Object obj, int index, String name, String uri, String prefix,
                          int[] nsindexes, String[] nsprefixes, IBindingFactory factory) {
        if (index < 0) {
            throw new
                    IllegalArgumentException("index value must be non-negative");
        }
        marshallerIndex = index;
        dataObject = obj;
        bindingFactory = factory;
        boolean found = false;
        String[] nss = factory.getNamespaces();
        int nsidx = -1;
        for (int i = 0; i < nsindexes.length; i++) {
            if (uri.equals(nss[nsindexes[i]])) {
                nsidx = nsindexes[i];
                prefix = nsprefixes[i];
                found = true;
                break;
            }
        }
        elementName = name;
        elementNamespace = uri;
        elementNamespacePrefix = prefix;
        if (!found) {
            for (int i = 0; i < nss.length; i++) {
                if (uri.equals(nss[i])) {
                    nsidx = i;
                    break;
                }
            }
            if (nsidx >= 0) {
                int[] icpy = new int[nsindexes.length+1];
                icpy[0] = nsidx;
                System.arraycopy(nsindexes, 0, icpy, 1, nsindexes.length);
                nsindexes = icpy;
                String[] scpy = new String[nsprefixes.length+1];
                scpy[0] = prefix;
                System.arraycopy(nsprefixes, 0, scpy, 1, nsprefixes.length);
                nsprefixes = scpy;
            } else {
                throw new IllegalStateException("Namespace not found");
            }
        }
        elementNamespaceIndex = nsidx;
        openNamespaceIndexes = nsindexes;
        openNamespacePrefixes = nsprefixes;
    }

    /**
     * Internal method to handle the actual marshalling. If the source object is marshallable it's
     * it's just marshalled directly, without worrying about redundant namespace declarations and
     * such. If it needs to be handled with an abstract mapping, the handling is determined by the
     * 'full' flag. When this is <code>true</code> all namespaces are declared directly, while if
     * <code>false</code> the namespaces must have previously been declared on some enclosing
     * element of the output. This allows the normal case of marshalling within the context of a
     * SOAP message to be handled efficiently, while still generating correct XML if the element is
     * marshalled directly (as when building the AXIOM representation for use by WS-Security).
     * 
     * @param full
     * @param ctx
     * @throws JiBXException
     */
    private void marshal(boolean full, IMarshallingContext ctx) throws JiBXException {
        try {
            
            if (marshallerIndex < 0) {
                if (dataObject instanceof IMarshallable) {
                    ((IMarshallable)dataObject).marshal(ctx);
                } else {
                    throw new IllegalStateException("Object of class " + dataObject.getClass().getName() +
                        " needs a JiBX <mapping> to be marshalled");
                }
            } else {
                IXMLWriter wrtr = ctx.getXmlWriter();
                String name = elementName;
                int nsidx = 0;
                if (full) {
                    
                    // declare all namespaces on start tag
                    nsidx = elementNamespaceIndex;
                    wrtr.startTagNamespaces(nsidx, name, openNamespaceIndexes, openNamespacePrefixes);
                    
                } else {
        
                    // configure writer with namespace declared in enclosing scope
                    wrtr.openNamespaces(openNamespaceIndexes, openNamespacePrefixes);
                    if (!"".equals(elementNamespacePrefix)) {
                        name = elementNamespacePrefix + ':' + name;
                    }
                    wrtr.startTagOpen(0, name);
                }
                
                // marshal object representation (may include attributes) into element
                IMarshaller mrsh = ctx.getMarshaller(marshallerIndex,
                                                     bindingFactory
                                                             .getMappedClasses()[marshallerIndex]);
                mrsh.marshal(dataObject, ctx);
                wrtr.endTag(nsidx, name);
            }
            ctx.getXmlWriter().flush();

        } catch (IOException e) {
            throw new JiBXException("Error marshalling XML representation: " + e.getMessage(), e);
        }
    }

    /* (non-Javadoc)
     * @see org.apache.axiom.om.OMDataSource#serialize(java.io.OutputStream, org.apache.axiom.om.OMOutputFormat)
     */
    public void serialize(OutputStream output, OMOutputFormat format) throws XMLStreamException {
        try {
            
            // marshal with all namespace declarations, since external state unknown
            IMarshallingContext ctx = bindingFactory.createMarshallingContext();
            ctx.setOutput(output, format == null ? null : format.getCharSetEncoding());
            marshal(true, ctx);
            
        } catch (JiBXException e) {
            throw new XMLStreamException("Error in JiBX marshalling: " + e.getMessage(), e);
        }
    }

    /* (non-Javadoc)
     * @see org.apache.axiom.om.OMDataSource#serialize(java.io.Writer, org.apache.axiom.om.OMOutputFormat)
     */
    public void serialize(Writer writer, OMOutputFormat format) throws XMLStreamException {
        try {
            
            // marshal with all namespace declarations, since external state unknown
            IMarshallingContext ctx = bindingFactory.createMarshallingContext();
            ctx.setOutput(writer);
            marshal(true, ctx);
            
        } catch (JiBXException e) {
            throw new XMLStreamException("Error in JiBX marshalling: " + e.getMessage(), e);
        }
    }

    /* (non-Javadoc)
     * @see org.apache.axiom.om.OMDataSource#serialize(javax.xml.stream.XMLStreamWriter)
     */
    public void serialize(XMLStreamWriter xmlWriter) throws XMLStreamException {
        try {
            
            // check if namespaces already declared for abstract mapping
            boolean full = true;
            String[] nss = bindingFactory.getNamespaces();
            if (marshallerIndex >= 0) {
                String prefix = xmlWriter.getPrefix(elementNamespace);
                if (elementNamespacePrefix.equals(prefix)) {
                    full = false;
                    for (int i = 0; i < openNamespaceIndexes.length; i++) {
                        String uri = nss[i];
                        prefix = xmlWriter.getPrefix(uri);
                        if (!openNamespacePrefixes[i].equals(prefix)) {
                            full = true;
                            break;
                        }
                    }
                }
            }
            
            // marshal with all namespace declarations, since external state unknown
            IXMLWriter writer = new StAXWriter(nss, xmlWriter);
            IMarshallingContext ctx = bindingFactory.createMarshallingContext();
            ctx.setXmlWriter(writer);
            marshal(full, ctx);
            
        } catch (JiBXException e) {
            throw new XMLStreamException("Error in JiBX marshalling: " + e.getMessage(), e);
        }
    }

    /* (non-Javadoc)
     * @see org.apache.axiom.om.OMDataSource#getReader()
     */
    public XMLStreamReader getReader() throws XMLStreamException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        serialize(bos, null);
        return StAXUtils.createXMLStreamReader(new ByteArrayInputStream(bos.toByteArray()));
    }
}