/*
 * 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.jaxws.marshaller.impl.alt;

import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.description.AttachmentDescription;
import org.apache.axis2.jaxws.description.AttachmentType;
import org.apache.axis2.jaxws.description.EndpointDescription;
import org.apache.axis2.jaxws.description.EndpointInterfaceDescription;
import org.apache.axis2.jaxws.description.OperationDescription;
import org.apache.axis2.jaxws.description.ParameterDescription;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.jaxws.marshaller.MethodMarshaller;
import org.apache.axis2.jaxws.message.Message;
import org.apache.axis2.jaxws.message.Protocol;
import org.apache.axis2.jaxws.message.factory.MessageFactory;
import org.apache.axis2.jaxws.registry.FactoryRegistry;
import org.apache.axis2.jaxws.runtime.description.marshal.MarshalServiceRuntimeDescription;
import org.apache.axis2.jaxws.utility.ConvertUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;
import javax.xml.ws.WebServiceException;
import java.util.List;
import java.util.TreeSet;


/**
 * The Doc/Lit Wrapped Minimal Marshaller is used when 1) The web service is Doc/Lit mininal, and 2)
 * JAXB artifacts are missing (i.e. we don't have ObjectFactories)
 */
public class DocLitBareMinimalMethodMarshaller implements MethodMarshaller {

    private static Log log = LogFactory.getLog(DocLitBareMinimalMethodMarshaller.class);

    public DocLitBareMinimalMethodMarshaller() {
        super();
    }

    public Object demarshalResponse(Message message, Object[] signatureArgs,
                                    OperationDescription operationDesc)
            throws WebServiceException {

        EndpointInterfaceDescription ed = operationDesc.getEndpointInterfaceDescription();
        EndpointDescription endpointDesc = ed.getEndpointDescription();

        // Note all exceptions are caught and rethrown with a WebServiceException
        try {
            // Sample Document message
            // ..
            // <soapenv:body>
            //    <m:return ... >...</m:param>
            // </soapenv:body>
            //
            // Important points.
            //   1) There is no operation element in the message
            //   2) The data blocks are located underneath the operation element. 
            //   3) The name of the data blocks (m:param) are defined by the schema.
            //      (SOAP indicates that the name of the element is not important, but
            //      for document processing, we will assume that the name corresponds to 
            //      a schema root element)
            //   4) The type of the data block is defined by schema; thus in most cases
            //      an xsi:type will not be present
            ParameterDescription[] pds = operationDesc.getParameterDescriptions();
            MarshalServiceRuntimeDescription marshalDesc =
                    MethodMarshallerUtils.getMarshalDesc(endpointDesc);
            TreeSet<String> packages = marshalDesc.getPackages();

            // Get the return value.
            Class returnType = operationDesc.getResultActualType();
            Object returnValue = null;
            boolean hasReturnInBody = false;
            if (returnType != void.class) {
                AttachmentDescription attachmentDesc = 
                    operationDesc.getResultAttachmentDescription();
                if (attachmentDesc != null) {
                    if (attachmentDesc.getAttachmentType() == AttachmentType.SWA) {
                       String cid = message.getAttachmentID(0);
                       returnValue = message.getDataHandler(cid);
                    } else {
                        throw ExceptionFactory.
                          makeWebServiceException(Messages.getMessage("pdElementErr"));
                    }
                } else {
                    // Use "byJavaType" unmarshalling if necessary
                    Class byJavaType = null;
                    if (MethodMarshallerUtils.isNotJAXBRootElement(returnType, marshalDesc)) {
                        byJavaType = returnType;
                    }
                    // If the webresult is in the header, we need the name of the header so that we can find it.
                    Element returnElement = null;
                    if (operationDesc.isResultHeader()) {
                        returnElement = MethodMarshallerUtils
                        .getReturnElement(packages, message, byJavaType, operationDesc.isListType(), true,
                                          operationDesc.getResultTargetNamespace(),
                                          operationDesc.getResultName(),
                                          MethodMarshallerUtils.numOutputBodyParams(pds) > 0);

                    } else {
                        returnElement = MethodMarshallerUtils
                        .getReturnElement(packages, message, byJavaType, operationDesc.isListType(), false, null, null,
                                          MethodMarshallerUtils.numOutputBodyParams(pds) > 0);
                        hasReturnInBody = true;
                    }
                    //TODO should we allow null if the return is a header?
                    //Validate input parameters for operation and make sure no input parameters are null.
                    //As per JAXWS Specification section 3.6.2.3 if a null value is passes as an argument 
                    //to a method then an implementation MUST throw WebServiceException.
                    returnValue = returnElement.getTypeValue();
                }
                if (ConvertUtils.isConvertable(returnValue, returnType)) {
                    returnValue = ConvertUtils.convert(returnValue, returnType);
                }               
            }

            // We want to use "by Java Type" unmarshalling for 
            // allall non-JAXB objects
            Class[] javaTypes = new Class[pds.length];
            for (int i = 0; i < pds.length; i++) {
                ParameterDescription pd = pds[i];
                Class type = pd.getParameterActualType();
                if (MethodMarshallerUtils.isNotJAXBRootElement(type, marshalDesc)) {
                    javaTypes[i] = type;
                }
            }

            // Unmarshall the ParamValues from the Message
            List<PDElement> pvList = MethodMarshallerUtils.getPDElements(pds,
                                                                         message,
                                                                         packages,
                                                                         false, // output
                                                                         hasReturnInBody,
                                                                         javaTypes); // byJavaType unmarshalling

            // Populate the response Holders
            MethodMarshallerUtils.updateResponseSignatureArgs(pds, pvList, signatureArgs);

            return returnValue;
        } catch (Exception e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
    }

    public Object[] demarshalRequest(Message message, OperationDescription operationDesc)
            throws WebServiceException {

        EndpointInterfaceDescription ed = operationDesc.getEndpointInterfaceDescription();
        EndpointDescription endpointDesc = ed.getEndpointDescription();

        // Note all exceptions are caught and rethrown with a WebServiceException
        try {
            // Sample Document message
            // ..
            // <soapenv:body>
            //    <m:param .. >...</m:param>
            // </soapenv:body>
            //
            // Important points.
            //   1) There is no operation element under the body.
            //   2) The data blocks are located underneath the body.  
            //   3) The name of the data blocks (m:param) are defined by the schema
            //   4) The type of the data block (data:foo) is defined by schema (and probably
            //      is not present in the message
            ParameterDescription[] pds = operationDesc.getParameterDescriptions();
            MarshalServiceRuntimeDescription marshalDesc =
                    MethodMarshallerUtils.getMarshalDesc(endpointDesc);
            TreeSet<String> packages = marshalDesc.getPackages();

            // We want to use "by Java Type" unmarshalling for 
            // allall non-JAXB objects
            Class[] javaTypes = new Class[pds.length];
            for (int i = 0; i < pds.length; i++) {
                ParameterDescription pd = pds[i];
                Class type = pd.getParameterActualType();
                // If it is not a JAXB Root Element
                if (MethodMarshallerUtils.isNotJAXBRootElement(type, marshalDesc)) {
                    javaTypes[i] = type;
                } 
            }

            // Unmarshal the ParamValues from the message
            List<PDElement> pvList = MethodMarshallerUtils.getPDElements(pds,
                                                                         message,
                                                                         packages,
                                                                         true, // input
                                                                         false,
                                                                         javaTypes); // never unmarshal by type for doc/lit bare

            // Build the signature arguments
            Object[] sigArguments = MethodMarshallerUtils.createRequestSignatureArgs(pds, pvList);
            return sigArguments;
        } catch (Exception e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
    }

    public Message marshalResponse(Object returnObject,
                                   Object[] signatureArgs,
                                   OperationDescription operationDesc, Protocol protocol)
            throws WebServiceException {

        EndpointInterfaceDescription ed = operationDesc.getEndpointInterfaceDescription();
        EndpointDescription endpointDesc = ed.getEndpointDescription();

        // We want to respond with the same protocol as the request,
        // It the protocol is null, then use the Protocol defined by the binding
        if (protocol == null) {
            protocol = Protocol.getProtocolForBinding(endpointDesc.getBindingType());
        }

        // Note all exceptions are caught and rethrown with a WebServiceException
        try {
            // Sample Document message
            // ..
            // <soapenv:body>
            //    <m:return ... >...</m:param>
            // </soapenv:body>
            //
            // Important points.
            //   1) There is no operation element in the message
            //   2) The data blocks are located underneath the operation element. 
            //   3) The name of the data blocks (m:param) are defined by the schema.
            //      (SOAP indicates that the name of the element is not important, but
            //      for document processing, we will assume that the name corresponds to 
            //      a schema root element)
            //   4) The type of the data block is defined by schema; thus in most cases
            //      an xsi:type will not be present

            // Get the operation information
            ParameterDescription[] pds = operationDesc.getParameterDescriptions();
            MarshalServiceRuntimeDescription marshalDesc =
                    MethodMarshallerUtils.getMarshalDesc(endpointDesc);
            TreeSet<String> packages = marshalDesc.getPackages();

            // Create the message 
            MessageFactory mf = (MessageFactory)FactoryRegistry.getFactory(MessageFactory.class);
            Message m = mf.create(protocol);

            // Put the return object onto the message
            Class returnType = operationDesc.getResultActualType();
            if (returnType != void.class) {
                
                AttachmentDescription attachmentDesc = 
                    operationDesc.getResultAttachmentDescription();
                if (attachmentDesc != null) {
                    if (attachmentDesc.getAttachmentType() == AttachmentType.SWA) {
                        // Create an Attachment object with the signature value
                        Attachment attachment = new Attachment(returnObject, 
                                                               returnType, 
                                                               attachmentDesc,
                                                               operationDesc.getResultPartName());
                        m.addDataHandler(attachment.getDataHandler(), 
                                         attachment.getContentID());
                        m.setDoingSWA(true);
                    } else {
                        throw ExceptionFactory.
                          makeWebServiceException(Messages.getMessage("pdElementErr"));
                    }
                } else {

                    // Use byJavaType marshalling if necessary
                    Class byJavaType = null;
                    if (MethodMarshallerUtils.isNotJAXBRootElement(returnType, marshalDesc)) {
                        byJavaType = returnType;
                    }

                    Element returnElement = null;
                    QName returnQName = new QName(operationDesc.getResultTargetNamespace(),
                                                  operationDesc.getResultName());
                    if (marshalDesc.getAnnotationDesc(returnType).hasXmlRootElement()) {
                        returnElement = new Element(returnObject, returnQName);
                    } else {
                        returnElement = new Element(returnObject, returnQName, returnType);
                    }
                    MethodMarshallerUtils.toMessage(returnElement, returnType, operationDesc.isListType(),
                                                    marshalDesc, m,
                                                    byJavaType,
                                                    operationDesc.isResultHeader());
                }
            }

            // Convert the holder objects into a list of JAXB objects for marshalling
            List<PDElement> pdeList = MethodMarshallerUtils.getPDElements(marshalDesc,
                                                                          pds,
                                                                          signatureArgs,
                                                                          false, // output
                                                                          false, false);

            // We want to use "by Java Type" marshalling for 
            // all body elements and all non-JAXB objects
            for (PDElement pde : pdeList) {
                ParameterDescription pd = pde.getParam();
                Class type = pd.getParameterActualType();
                if (MethodMarshallerUtils.isNotJAXBRootElement(type, marshalDesc)) {
                    pde.setByJavaTypeClass(type);
                }
            }

            // Put values onto the message
            MethodMarshallerUtils.toMessage(pdeList, m, packages);
            
            // Enable SWA for nested SwaRef attachments
            if (operationDesc.hasResponseSwaRefAttachments()) {
                m.setDoingSWA(true);
            }

            return m;
        } catch (Exception e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
    }

    public Message marshalRequest(Object[] signatureArguments, OperationDescription operationDesc)
            throws WebServiceException {

        EndpointInterfaceDescription ed = operationDesc.getEndpointInterfaceDescription();
        EndpointDescription endpointDesc = ed.getEndpointDescription();
        Protocol protocol = Protocol.getProtocolForBinding(endpointDesc.getClientBindingID());

        // Note all exceptions are caught and rethrown with a WebServiceException
        try {
            // Sample Document message
            // ..
            // <soapenv:body>
            //    <m:param .. >...</m:param>
            // </soapenv:body>
            //
            // Important points.
            //   1) There is no operation element under the body.
            //   2) The data blocks are located underneath the body.  
            //   3) The name of the data blocks (m:param) are defined by the schema
            //   4) The type of the data block (data:foo) is defined by schema (and probably
            //      is not present in the message

            // Get the operation information
            ParameterDescription[] pds = operationDesc.getParameterDescriptions();
            MarshalServiceRuntimeDescription marshalDesc =
                    MethodMarshallerUtils.getMarshalDesc(endpointDesc);
            TreeSet<String> packages = marshalDesc.getPackages();

            // Create the message 
            MessageFactory mf = (MessageFactory)FactoryRegistry.getFactory(MessageFactory.class);
            Message m = mf.create(protocol);

            // The input object represent the signature arguments.
            // Signature arguments are both holders and non-holders
            // Convert the signature into a list of JAXB objects for marshalling
            List<PDElement> pdeList = MethodMarshallerUtils.getPDElements(marshalDesc,
                                                                          pds,
                                                                          signatureArguments,
                                                                          true,  // input
                                                                          false, false);

            // We want to use "by Java Type" marshalling for 
            // all body elements and all non-JAXB objects
            for (PDElement pde : pdeList) {
                ParameterDescription pd = pde.getParam();
                Class type = pd.getParameterActualType();
                if (MethodMarshallerUtils.isNotJAXBRootElement(type, marshalDesc)) {
                    pde.setByJavaTypeClass(type);
                }
            }

            // Put values onto the message...marshalling by type
            MethodMarshallerUtils.toMessage(pdeList, m, packages);
            
            // Enable SWA for nested SwaRef attachments
            if (operationDesc.hasRequestSwaRefAttachments()) {
                m.setDoingSWA(true);
            }

            return m;
        } catch (Exception e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
    }

    public Message marshalFaultResponse(Throwable throwable, OperationDescription operationDesc,
                                        Protocol protocol) throws WebServiceException {

        EndpointInterfaceDescription ed = operationDesc.getEndpointInterfaceDescription();
        EndpointDescription endpointDesc = ed.getEndpointDescription();
        MarshalServiceRuntimeDescription marshalDesc =
                MethodMarshallerUtils.getMarshalDesc(endpointDesc);

        // We want to respond with the same protocol as the request,
        // It the protocol is null, then use the Protocol defined by the binding
        if (protocol == null) {
            protocol = Protocol.getProtocolForBinding(endpointDesc.getBindingType());
        }

        // Note all exceptions are caught and rethrown with a WebServiceException
        try {
            // Create the message 
            MessageFactory mf = (MessageFactory)FactoryRegistry.getFactory(MessageFactory.class);
            Message m = mf.create(protocol);

            // Put the fault onto the message
            MethodMarshallerUtils.marshalFaultResponse(throwable,
                                                       marshalDesc,
                                                       operationDesc,
                                                       m);
            return m;
        } catch (Exception e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
    }

    public Throwable demarshalFaultResponse(Message message, OperationDescription operationDesc)
            throws WebServiceException {

        EndpointInterfaceDescription ed = operationDesc.getEndpointInterfaceDescription();
        EndpointDescription endpointDesc = ed.getEndpointDescription();
        MarshalServiceRuntimeDescription marshalDesc =
                MethodMarshallerUtils.getMarshalDesc(endpointDesc);

        // Note all exceptions are caught and rethrown with a WebServiceException
        try {
            Throwable t = MethodMarshallerUtils
                    .demarshalFaultResponse(operationDesc, marshalDesc, message);
            return t;
        } catch (Exception e) {
            throw ExceptionFactory.makeWebServiceException(e);
        }
    }

}
