/*
 * 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.addressing;

import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.util.AttributeHelper;
import org.apache.axiom.om.util.ElementHelper;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.metadata.InterfaceName;
import org.apache.axis2.addressing.metadata.ServiceName;
import org.apache.axis2.addressing.metadata.WSDLLocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * The methods in this class are used to process {@link EndpointReference} objects
 * according to the rules of the 2005/08 (Final) and 2004/08 (submission) WS-Addressing
 * specifications.
 */
public class EndpointReferenceHelper {

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

    private final static Map finalQNames = new IdentityHashMap();
    private final static Map submissionQNames = new IdentityHashMap();

    /**
     * Populates an endpoint reference based on the <code>OMElement</code> and
     * WS-Addressing namespace that is passed in.
     *
     * @param epr                 an endpoint reference instance to hold the info.
     * @param eprOMElement        an element of endpoint reference type
     * @param addressingNamespace the namespace of the WS-Addressing spec to comply with.
     * @throws AxisFault if unable to locate an address element, or if the specified namespace
     * is different to the actual namespace.
     * @see #fromOM(OMElement)
     */
    public static void fromOM(EndpointReference epr, OMElement eprOMElement,
                              String addressingNamespace) throws AxisFault {
        String namespace = fromOM(epr, eprOMElement);
        
        if (!namespace.equals(addressingNamespace))
            throw new AxisFault("The endpoint reference does not match the specified namespace.");
    }

    /**
     * Populates an endpoint reference based on the <code>OMElement</code>. Returns the
     * WS-Addressing namespace of the endpoint reference.
     * 
     * @param epr          an endpoint reference instance to hold the info. If the endpoint
     * reference is null then just the WS-Addressing namespace is returned.
     * @param eprOMElement an element of endpoint reference type
     * @return a string representing the WS-Addressing namespace of the endpoint reference.
     * @throws AxisFault if unable to locate an address element.
     */
    public static String fromOM(EndpointReference epr, OMElement eprOMElement)
    throws AxisFault {
        boolean isFinalAddressingNamespace = false;
        Map map = null;

        //First pass, identify the addressing namespace.
        OMElement address = eprOMElement
                .getFirstChildWithName((QName) finalQNames.get(AddressingConstants.EPR_ADDRESS));

        if (address != null) {
            map = finalQNames;
            isFinalAddressingNamespace = true;

            if (log.isDebugEnabled()) {
                log.debug("fromOM: Found address element for namespace, " +
                        AddressingConstants.Final.WSA_NAMESPACE);
            }
        } else {
            address = eprOMElement.getFirstChildWithName(
                    (QName) submissionQNames.get(AddressingConstants.EPR_ADDRESS));

            if (address != null) {
                map = submissionQNames;
                isFinalAddressingNamespace = false;

                if (log.isDebugEnabled()) {
                    log.debug("fromOM: Found address element for namespace, " +
                            AddressingConstants.Submission.WSA_NAMESPACE);
                }
            } else {
                throw new AxisFault(
                        "Unable to locate an address element for the endpoint reference type.");
            }
        }

        //Second pass, identify the properties.
        if (epr != null)
            fromOM(epr, eprOMElement, map, isFinalAddressingNamespace);

        return ((QName) map.get(AddressingConstants.EPR_ADDRESS)).getNamespaceURI();
    }

    /**
     * Populates an endpoint reference based on the <code>String</code> that is
     * passed in. If the http://schemas.xmlsoap.org/ws/2004/08/addressing namespace
     * is in effect then any reference properties will be saved as reference parameters.
     * Regardless of the addressing namespace in effect, any elements present in the
     * <code>String</code> that are not recognised are saved as extensibility elements.
     *
     * @param eprString string from the element of endpoint reference type
     * @throws AxisFault if unable to locate an address element
     * @deprecated use {@link #fromString(String)} instead.
     */
    public static EndpointReference fromOM(String eprString) throws AxisFault {
        return fromString(eprString);
    }

    /**
     * Populates an endpoint reference based on the <code>String</code> that is
     * passed in. If the http://schemas.xmlsoap.org/ws/2004/08/addressing namespace
     * is in effect then any reference properties will be saved as reference parameters.
     * Regardless of the addressing namespace in effect, any elements present in the
     * <code>String</code> that are not recognised are saved as extensibility elements.
     *
     * @param eprString string from the element of endpoint reference type
     * @throws AxisFault if unable to locate an address element
     */
    public static EndpointReference fromString(String eprString) throws AxisFault {
        try {
            return fromOM(new StAXOMBuilder(
                    new ByteArrayInputStream(eprString.getBytes())).getDocumentElement());
        } catch (XMLStreamException e) {
            throw AxisFault.makeFault(e);
        }
    }

    /**
     * Populates an endpoint reference based on the <code>OMElement</code> that is
     * passed in. If the http://schemas.xmlsoap.org/ws/2004/08/addressing namespace
     * is in effect then any reference properties will be saved as reference parameters.
     * Regardless of the addressing namespace in effect, any elements present in the
     * <code>OMElement</code> that are not recognised are saved as extensibility elements.
     *
     * @param eprOMElement an element of endpoint reference type
     * @throws AxisFault if unable to locate an address element
     */
    public static EndpointReference fromOM(OMElement eprOMElement) throws AxisFault {
        EndpointReference epr = new EndpointReference("");
        fromOM(epr, eprOMElement);

        return epr;
    }

    /**
     * Creates an <code>OMElement</code> based on the properties of the endpoint
     * reference. The output may differ based on the addressing namespace that is
     * in effect when this method is called. If the http://www.w3.org/2005/08/addressing
     * namespace is in effect, and a metadata property has been defined for the
     * endpoint reference, then there will be a metadata element to contain the
     * property in the output. If the http://schemas.xmlsoap.org/ws/2004/08/addressing
     * namespace is in effect, however, then no metadata element will be included
     * in the output, even if a metadata property element has been defined.
     *
     * @param factory
     * @param epr
     * @param qname
     * @param addressingNamespace
     * @return
     * @throws AxisFault
     */
    public static OMElement toOM(OMFactory factory, EndpointReference epr, QName qname,
                                 String addressingNamespace) throws AxisFault {
        OMElement eprElement = null;

        if (log.isDebugEnabled()) {
            log.debug("toOM: Factory, " + factory);
            log.debug("toOM: Endpoint reference, " + epr);
            log.debug("toOM: Element qname, " + qname);
            log.debug("toOM: Addressing namespace, " + addressingNamespace);
        }

        if (addressingNamespace == null) {
            throw new AxisFault("Addressing namespace cannot be null.");
        }

        if (qname.getPrefix() != null) {
            OMNamespace wrapNs =
                    factory.createOMNamespace(qname.getNamespaceURI(), qname.getPrefix());
            if (factory instanceof SOAPFactory) {
                eprElement =
                        ((SOAPFactory) factory).createSOAPHeaderBlock(qname.getLocalPart(), wrapNs);
            } else {
                eprElement = factory.createOMElement(qname.getLocalPart(), wrapNs);
            }

            OMNamespace wsaNS = factory.createOMNamespace(addressingNamespace,
                                                          AddressingConstants.WSA_DEFAULT_PREFIX);
            OMElement addressE =
                    factory.createOMElement(AddressingConstants.EPR_ADDRESS, wsaNS, eprElement);
            String address = epr.getAddress();
            addressE.setText(address);

            ArrayList addressAttributes = epr.getAddressAttributes();
            if (addressAttributes != null) {
                Iterator attrIter = addressAttributes.iterator();
                while (attrIter.hasNext()) {
                    OMAttribute omAttribute = (OMAttribute) attrIter.next();
                    AttributeHelper.importOMAttribute(omAttribute, addressE);
                }
            }

            List metaData = epr.getMetaData();
            if (metaData != null &&
                    AddressingConstants.Final.WSA_NAMESPACE.equals(addressingNamespace)) {
                OMElement metadataE = factory.createOMElement(
                        AddressingConstants.Final.WSA_METADATA, wsaNS, eprElement);
                for (int i = 0, size = metaData.size(); i < size; i++) {
                    OMElement omElement = (OMElement) metaData.get(i);
                    metadataE.addChild(ElementHelper.importOMElement(omElement, factory));
                }

                ArrayList metadataAttributes = epr.getMetadataAttributes();
                if (metadataAttributes != null) {
                    Iterator attrIter = metadataAttributes.iterator();
                    while (attrIter.hasNext()) {
                        OMAttribute omAttribute = (OMAttribute) attrIter.next();
                        AttributeHelper.importOMAttribute(omAttribute, metadataE);
                    }
                }
            }


            Map referenceParameters = epr.getAllReferenceParameters();
            if (referenceParameters != null) {
                OMElement refParameterElement = factory.createOMElement(
                        AddressingConstants.EPR_REFERENCE_PARAMETERS, wsaNS, eprElement);
                Iterator iterator = referenceParameters.values().iterator();
                while (iterator.hasNext()) {
                    OMElement omElement = (OMElement) iterator.next();
                    refParameterElement.addChild(ElementHelper.importOMElement(omElement, factory));
                }
            }

            List attributes = epr.getAttributes();
            if (attributes != null) {
                for (int i = 0, size = attributes.size(); i < size; i++) {
                    OMAttribute omAttribute = (OMAttribute) attributes.get(i);
                    AttributeHelper.importOMAttribute(omAttribute, eprElement);
                }
            }

            // add xs:any
            List extensibleElements = epr.getExtensibleElements();
            if (extensibleElements != null) {
                for (int i = 0, size = extensibleElements.size(); i < size; i++) {
                    OMElement omElement = (OMElement) extensibleElements.get(i);
                    eprElement.addChild(ElementHelper.importOMElement(omElement, factory));
                }
            }
        } else {
            throw new AxisFault("prefix must be specified");
        }

        return eprElement;
    }

    private static void fromOM(EndpointReference epr, OMElement eprOMElement, Map map,
                               boolean isFinalAddressingNamespace) {
        Iterator childElements = eprOMElement.getChildElements();

        while (childElements.hasNext()) {
            OMElement eprChildElement = (OMElement) childElements.next();
            QName qname = eprChildElement.getQName();

            if (map.get(AddressingConstants.EPR_ADDRESS).equals(qname)) {
                //We need to identify the address element again in order to ensure
                //that it is not included with the extensibility elements.
                epr.setAddress(eprChildElement.getText());
                Iterator allAddrAttributes = eprChildElement.getAllAttributes();
                ArrayList addressAttributes = new ArrayList();
                while (allAddrAttributes.hasNext()) {
                    OMAttribute attribute = (OMAttribute) allAddrAttributes.next();
                    addressAttributes.add(attribute);
                }
                epr.setAddressAttributes(addressAttributes);
            } else if (map.get(AddressingConstants.EPR_REFERENCE_PARAMETERS).equals(qname)) {
                Iterator iterator = eprChildElement.getChildElements();
                while (iterator.hasNext()) {
                    OMElement element = (OMElement) iterator.next();
                    epr.addReferenceParameter(element);
                }
            } else if (isFinalAddressingNamespace &&
                    map.get(AddressingConstants.Final.WSA_METADATA).equals(qname)) {
                Iterator iterator = eprChildElement.getChildElements();
                while (iterator.hasNext()) {
                    OMNode node = (OMNode) iterator.next();
                    epr.addMetaData(node);
                }
                Iterator allMDAttributes = eprChildElement.getAllAttributes();
                ArrayList metadataAttributes = new ArrayList();
                while (allMDAttributes.hasNext()) {
                    OMAttribute attribute = (OMAttribute) allMDAttributes.next();
                    metadataAttributes.add(attribute);
                }
                epr.setMetadataAttributes(metadataAttributes);
            } else if (!isFinalAddressingNamespace &&
                    map.get(AddressingConstants.Submission.EPR_REFERENCE_PROPERTIES).equals(qname))
            {
                // since we have the model for WS-Final, we don't have a place to keep this reference properties.
                // The only compatible place is reference properties
                Iterator iterator = eprChildElement.getChildElements();
                while (iterator.hasNext()) {
                    OMElement element = (OMElement) iterator.next();
                    epr.addReferenceParameter(element);
                }
            } else {
                epr.addExtensibleElement(eprChildElement);
            }
        }

        Iterator attributes = eprOMElement.getAllAttributes();
        while (attributes.hasNext()) {
            OMAttribute attribute = (OMAttribute) attributes.next();
            epr.addAttribute(attribute);
        }

        if (log.isDebugEnabled()) {
            log.debug("fromOM: Endpoint reference, " + epr);
        }
    }
    
    /**
     * Retrieves the WS-Addressing EPR ServiceName element from an EPR.
     * 
     * @param epr the EPR to retrieve the element from
     * @param addressingNamespace the WS-Addressing namespace associated with
     * the EPR.
     * @return an instance of <code>ServiceName</code>. The return value is
     * never <code>null</code>.
     * @throws AxisFault
     */
    public static ServiceName getServiceNameMetadata(EndpointReference epr, String addressingNamespace) throws AxisFault {
        ServiceName serviceName = new ServiceName();
        List elements = null;
        
        if (AddressingConstants.Submission.WSA_NAMESPACE.equals(addressingNamespace))
            elements = epr.getExtensibleElements();
        else
            elements = epr.getMetaData();
        
        if (elements != null) {
            //Retrieve the service name and endpoint name.
            for (int i = 0, size = elements.size(); i < size; i++) {
                OMElement omElement = (OMElement) elements.get(i);
                if (ServiceName.isServiceNameElement(omElement)) {
                    serviceName.fromOM(omElement);
                    break;
                }
            }
        }
        
        return serviceName;
    }
    
    /**
     * Retrieves the WS-Addressing EPR PortType, or InterfaceName, element from an EPR,
     * as appropriate.
     * 
     * @param epr the EPR to retrieve the element from
     * @param addressingNamespace the WS-Addressing namespace associated with
     * the EPR.
     * @return an instance of <code>InterfaceName</code>. The return value is
     * never <code>null</code>.
     * @throws AxisFault
     */
    public static InterfaceName getInterfaceNameMetadata(EndpointReference epr, String addressingNamespace) throws AxisFault {
        InterfaceName interfaceName = new InterfaceName();
        List elements = null;
        
        if (AddressingConstants.Submission.WSA_NAMESPACE.equals(addressingNamespace))
            elements = epr.getExtensibleElements();
        else
            elements = epr.getMetaData();
        
        if (elements != null) {
            //Retrieve the service name and endpoint name.
            for (int i = 0, size = elements.size(); i < size; i++) {
                OMElement omElement = (OMElement) elements.get(i);
                if (InterfaceName.isInterfaceNameElement(omElement)) {
                    interfaceName.fromOM(omElement);
                    break;
                }
            }
        }
        
        return interfaceName;
    }
    
    /**
     * Retrieves the wsdli:wsdlLocation attribute from an EPR.
     * 
     * @param epr the EPR to retrieve the attribute from
     * @param addressingNamespace the WS-Addressing namespace associated with
     * the EPR.
     * @return an instance of <code>WSDLLocation</code>. The return value is
     * never <code>null</code>.
     * @throws AxisFault
     */
    public static WSDLLocation getWSDLLocationMetadata(EndpointReference epr, String addressingNamespace) throws AxisFault {
        WSDLLocation wsdlLocation = new WSDLLocation();
        List attributes = null;

        if (AddressingConstants.Submission.WSA_NAMESPACE.equals(addressingNamespace))
            attributes = epr.getAttributes();
        else
            attributes = epr.getMetadataAttributes();
        
        if (attributes != null) {
            //Retrieve the wsdl location.
            for (int i = 0, size = attributes.size(); i < size; i++) {
                OMAttribute omAttribute = (OMAttribute) attributes.get(i);
                if (WSDLLocation.isWSDLLocationAttribute(omAttribute)) {
                    wsdlLocation.fromOM(omAttribute);
                    break;
                }
            }
        }
        
        return wsdlLocation;
    }

    /**
     * Adds an instance of <code>ServiceName</code> as metadata to the specified EPR.
     * The metadata is mapped to a WS-Addressing EPR ServiceName element.
     * 
     * @param factory an <code>OMFactory</code>
     * @param epr the EPR to retrieve the attribute from
     * @param addressingNamespace the WS-Addressing namespace associated with
     * the EPR.
     * @param serviceName an instance of <code>ServiceName</code> that contains the
     * metadata
     * @throws AxisFault
     */
    public static void setServiceNameMetadata(OMFactory factory, EndpointReference epr, String addressingNamespace, ServiceName serviceName) throws AxisFault {
        if (AddressingConstants.Submission.WSA_NAMESPACE.equals(addressingNamespace)) {
            OMElement omElement = serviceName.toOM(factory, ServiceName.subQName);
            epr.addExtensibleElement(omElement);
        }
        else {
            OMElement omElement = serviceName.toOM(factory, ServiceName.wsamQName);
            epr.addMetaData(omElement);
        }
    }

    /**
     * Adds an instance of <code>InterfaceName</code> as metadata to the specified EPR.
     * The metadata is mapped to a WS-Addressing EPR PortType or InterfaceName element.
     * 
     * @param factory an <code>OMFactory</code>
     * @param epr the EPR to retrieve the attribute from
     * @param addressingNamespace the WS-Addressing namespace associated with
     * the EPR.
     * @param interfaceName an instance of <code>InterfaceName</code> that contains the
     * metadata
     * @throws AxisFault
     */
     public static void setInterfaceNameMetadata(OMFactory factory, EndpointReference epr, String addressingNamespace, InterfaceName interfaceName) throws AxisFault {
        if (AddressingConstants.Submission.WSA_NAMESPACE.equals(addressingNamespace)) {
            OMElement omElement = interfaceName.toOM(factory, InterfaceName.subQName);
            epr.addExtensibleElement(omElement);
        }
        else {
            OMElement omElement = interfaceName.toOM(factory, InterfaceName.wsamQName);
            epr.addMetaData(omElement);
        }
    }
    
     /**
      * Adds an instance of <code>WSDLLocation</code> as metadata to the specified EPR.
      * The metadata is mapped to a wsdli:wsdlLocation attribute.
      * 
      * @param factory an <code>OMFactory</code>
      * @param epr the EPR to retrieve the attribute from
      * @param addressingNamespace the WS-Addressing namespace associated with
      * the EPR.
      * @param wsdlLocation an instance of <code>WSDLLocation</code> that contains the
      * metadata
      * @throws AxisFault
      */
    public static void setWSDLLocationMetadata(OMFactory factory, EndpointReference epr, String addressingNamespace, WSDLLocation wsdlLocation) throws AxisFault {
        OMAttribute attribute = wsdlLocation.toOM(factory);

        if (AddressingConstants.Submission.WSA_NAMESPACE.equals(addressingNamespace)) {
            epr.addAttribute(attribute);
        }
        else {
            ArrayList list = new ArrayList();
            list.add(attribute);
            epr.setMetadataAttributes(list);
        }
    }
    
    static {
        finalQNames.put(AddressingConstants.EPR_ADDRESS, new QName(
                AddressingConstants.Final.WSA_NAMESPACE, AddressingConstants.EPR_ADDRESS));
        finalQNames.put(AddressingConstants.EPR_REFERENCE_PARAMETERS, new QName(
                AddressingConstants.Final.WSA_NAMESPACE,
                AddressingConstants.EPR_REFERENCE_PARAMETERS));
        finalQNames.put(AddressingConstants.Final.WSA_METADATA, new QName(
                AddressingConstants.Final.WSA_NAMESPACE, AddressingConstants.Final.WSA_METADATA));

        submissionQNames.put(AddressingConstants.EPR_ADDRESS, new QName(
                AddressingConstants.Submission.WSA_NAMESPACE, AddressingConstants.EPR_ADDRESS));
        submissionQNames.put(AddressingConstants.EPR_REFERENCE_PARAMETERS, new QName(
                AddressingConstants.Submission.WSA_NAMESPACE,
                AddressingConstants.EPR_REFERENCE_PARAMETERS));
        submissionQNames.put(AddressingConstants.Submission.EPR_REFERENCE_PROPERTIES, new QName(
                AddressingConstants.Submission.WSA_NAMESPACE,
                AddressingConstants.Submission.EPR_REFERENCE_PROPERTIES));
    }
}
