/*
 * 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.tuscany.sca.binding.ws.jaxws;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import javax.wsdl.Binding;
import javax.wsdl.BindingOperation;
import javax.wsdl.Definition;
import javax.wsdl.Input;
import javax.wsdl.OperationType;
import javax.wsdl.PortType;
import javax.wsdl.extensions.AttributeExtensible;
import javax.wsdl.extensions.soap.SOAPAddress;
import javax.wsdl.extensions.soap.SOAPOperation;
import javax.wsdl.extensions.soap12.SOAP12Address;
import javax.wsdl.extensions.soap12.SOAP12Operation;
import javax.xml.namespace.QName;
import javax.xml.soap.Detail;
import javax.xml.soap.DetailEntry;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.soap.SOAPBinding;
import javax.xml.ws.soap.SOAPFaultException;

import org.apache.tuscany.sca.assembly.ComponentReference;
import org.apache.tuscany.sca.assembly.Endpoint;
import org.apache.tuscany.sca.binding.ws.WebServiceBinding;
import org.apache.tuscany.sca.core.invocation.Constants;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.interfacedef.util.FaultException;
import org.apache.tuscany.sca.interfacedef.wsdl.WSDLInterface;
import org.apache.tuscany.sca.invocation.DataExchangeSemantics;
import org.apache.tuscany.sca.invocation.Invoker;
import org.apache.tuscany.sca.invocation.Message;
import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
import org.oasisopen.sca.ServiceRuntimeException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * Uses JAXWS Dispatch to invoke a remote web service
 * 
 * @version $Rev$ $Date$
 */
public class JAXWSBindingInvoker implements Invoker, DataExchangeSemantics {
    private final static String SCA11_TUSCANY_NS = "http://tuscany.apache.org/xmlns/sca/1.1";

    public static final String WSA_FINAL_NAMESPACE = "http://www.w3.org/2005/08/addressing";
    public static final QName QNAME_WSA_ADDRESS = new QName(WSA_FINAL_NAMESPACE, "Address", "wsa");
    public static final QName QNAME_WSA_FROM = new QName(WSA_FINAL_NAMESPACE, "From", "wsa");
    public static final QName QNAME_WSA_MESSAGEID = new QName(WSA_FINAL_NAMESPACE, "MessageID", "wsa");
    public static final QName QNAME_WSA_TO = new QName(WSA_FINAL_NAMESPACE, "To", "wsa");
    public static final QName QNAME_WSA_ACTION = new QName(WSA_FINAL_NAMESPACE, "Action", "wsa");
    public static final QName QNAME_WSA_RELATESTO = new QName(WSA_FINAL_NAMESPACE, "RelatesTo", "wsa");
    private static final QName submissionWSAWNS = new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing",
                                                            QNAME_WSA_ACTION.getLocalPart());
    private static final QName finalWSANS = new QName("http://www.w3.org/2005/08/addressing",
                                                      QNAME_WSA_ACTION.getLocalPart());
    private static final QName finalWSAWNS = new QName("http://www.w3.org/2006/05/addressing/wsdl",
                                                       QNAME_WSA_ACTION.getLocalPart());
    private static final QName finalWSAMNS = new QName("http://www.w3.org/2007/05/addressing/metadata",
                                                       QNAME_WSA_ACTION.getLocalPart());

    public static final String TUSCANY_PREFIX = "tuscany";
    public static final QName CALLBACK_ID_REFPARM_QN = new QName(SCA11_TUSCANY_NS, "CallbackID", TUSCANY_PREFIX);
    public static final QName CONVERSATION_ID_REFPARM_QN =
        new QName(SCA11_TUSCANY_NS, "ConversationID", TUSCANY_PREFIX);

    private boolean dynamicDispatchForCallback = false;
    protected Dispatch<SOAPMessage> staticDispatch;
    private MessageFactory messageFactory;
    private Operation operation;
    protected WebServiceBinding wsBinding;
    private RuntimeEndpointReference endpointReference;

    public JAXWSBindingInvoker(Operation operation,
                               WebServiceFeature[] features,
                               MessageFactory messageFactory,
                               WebServiceBinding wsBinding,
                               RuntimeEndpointReference endpointReference) {
        this.messageFactory = messageFactory;
        this.operation = operation;
        this.wsBinding = wsBinding;
        this.endpointReference = endpointReference;
        
        if (endpointReference.getReference().isForCallback()) {
            this.dynamicDispatchForCallback = true;
        } else {
            this.staticDispatch = createStaticDispatch();
        }
    }
    
    protected Dispatch<SOAPMessage> createDynamicDispatch() {
        QName serviceName = wsBinding.getService().getQName();
        QName portName = new QName(serviceName.getNamespaceURI(), wsBinding.getPort().getName());
        Service service = Service.create(serviceName);
        service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointReference.getDeployedURI());   
        
        return service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);
    }

    protected Dispatch<SOAPMessage> createStaticDispatch() {
        URL wsdlLocation = null;
        try {
            if (wsBinding.getGeneratedWSDLDocument() != null && wsBinding.getGeneratedWSDLDocument().getDocumentBaseURI() != null) {
                wsdlLocation = new URL(wsBinding.getGeneratedWSDLDocument().getDocumentBaseURI());
            }
        } catch (Exception e) {
            // ignore and try getting the location from the other places 
        }
        try {
            if (wsBinding.getUserSpecifiedWSDLDefinition().getLocation() != null) {
                wsdlLocation = wsBinding.getUserSpecifiedWSDLDefinition().getLocation().toURL();
            }
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        if (wsdlLocation != null) {
            return createDispatchFromWSDL(wsdlLocation);
        } else {
            return createDispatchFromURI(endpointReference.getDeployedURI());                       
        }        
    }
    
    protected Dispatch<SOAPMessage> createDynamicDispatch(String uri) {
        return createDispatchFromURI(uri);
    }
    
    private Dispatch<SOAPMessage> createDispatchFromWSDL(URL wsdlLocation) {
        QName serviceName = wsBinding.getServiceName();
        QName portName = new QName(serviceName.getNamespaceURI(), wsBinding.getPortName());
        Service service = Service.create(wsdlLocation, serviceName);
        
        return service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);
    }
    
    protected Dispatch<SOAPMessage> createDispatchFromURI(String uri) {
        QName serviceName = wsBinding.getService().getQName();
        QName portName = new QName(serviceName.getNamespaceURI(), wsBinding.getPort().getName());
        Service service = Service.create(serviceName);
        service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, uri);
        
        return service.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);
    }

    public Message invoke(Message msg) {
        try {
            SOAPMessage resp = invokeTarget(msg);
            if (resp != null) {
                SOAPBody body = resp.getSOAPBody();
                if (body != null) {
                    SOAPFault fault = body.getFault();
                    if (fault != null) {
                        // setFault(msg, fault);
                    } else {
                        // WS-I uses single-element payload
                        Element payload =(Element)body.getChildElements().next();
                        if (wsBinding.isRpcLiteral()) {
                            Element unwrappedPayload = null; 
                            NodeList children = payload.getChildNodes();                                                                
                            for (int i = 0; i < children.getLength(); i++) {
                                Node nextChild = children.item(i);
                                if (nextChild instanceof Element) {
                                    unwrappedPayload = (Element)nextChild;
                                    break;
                                }
                            }
                            msg.setBody(unwrappedPayload);
                        } else {                            
                            msg.setBody(payload);
                        }
                    }
                }
            }
        } catch (SOAPFaultException e) {
            setFault(msg, e);
        } catch (WebServiceException e) {
            msg.setFaultBody(e);
        } catch (SOAPException e) {
            msg.setFaultBody(e);
        } catch (Throwable e) {
            msg.setFaultBody(e);
        }

        return msg;
    }

    private void setFault(Message msg, SOAPFaultException e) {
        SOAPFault fault = e.getFault();
        Detail detail = fault.getDetail();
        if (detail != null) {
            for (Iterator i = detail.getDetailEntries(); i.hasNext();) {
                DetailEntry entry = (DetailEntry)i.next();
                FaultException fe = new FaultException(e.getMessage(), entry, e);
                fe.setFaultName(entry.getElementQName());
                msg.setFaultBody(fe);
            }
        } else {
            msg.setFaultBody(e);
        }
    }

    protected String getSOAPAction(String operationName) {
        Binding binding = wsBinding.getBinding();
        if (binding != null) {
            for (Object o : binding.getBindingOperations()) {
                BindingOperation bop = (BindingOperation)o;
                if (bop.getName().equalsIgnoreCase(operationName)) {
                    for (Object o2 : bop.getExtensibilityElements()) {
                        if (o2 instanceof SOAPOperation) {
                            return ((SOAPOperation)o2).getSoapActionURI();
                        } else if (o2 instanceof SOAP12Operation) {
                            return ((SOAP12Operation)o2).getSoapActionURI();
                        }
                    }
                }
            }
        }
        return null;
    }

    protected SOAPMessage invokeTarget(Message msg) throws SOAPException {
        SOAPMessage soapMessage = messageFactory.createMessage();
        SOAPPart soapPart = soapMessage.getSOAPPart();
        javax.xml.soap.SOAPEnvelope envelope = soapPart.getEnvelope();

        String action = getSOAPAction(operation.getName());

        setHeaders(envelope.getHeader(), msg, action);

        javax.xml.soap.SOAPBody body = envelope.getBody();
        Object[] args = (Object[])msg.getBody();
        
        if (wsBinding.isRpcLiteral()) {
            
            String wrapperNamespace = null;
            
            // the rpc style creates a wrapper with a namespace where the namespace is
            // defined on the wsdl binding operation. If no binding is provided by the 
            // user then default to the namespace of the WSDL itself. 
            if (wsBinding.getBinding() != null){
                Iterator iter = wsBinding.getBinding().getBindingOperations().iterator();
                loopend:
                while(iter.hasNext()){
                    BindingOperation bOp = (BindingOperation)iter.next();
                    if (bOp.getName().equals(msg.getOperation().getName())){
                        for (Object ext : bOp.getBindingInput().getExtensibilityElements()){
                            if (ext instanceof javax.wsdl.extensions.soap.SOAPBody){
                                wrapperNamespace = ((javax.wsdl.extensions.soap.SOAPBody)ext).getNamespaceURI();
                                break loopend;
                            }
                        }
                    }
                }
            }
            
            if (wrapperNamespace == null){
                wrapperNamespace =  wsBinding.getUserSpecifiedWSDLDefinition().getNamespace();
            }
            
            Element rpcOperationWrapper = body.getOwnerDocument().createElementNS(wrapperNamespace, msg.getOperation().getName());            
            for (Object arg : args) {
                Node next = (Node)arg;
                Node nextImported = body.getOwnerDocument().importNode(next, true);
                rpcOperationWrapper.appendChild(nextImported);    
            }            
            body.appendChild(rpcOperationWrapper);
        }  else if (wsBinding.isRpcEncoded()) {
            throw new ServiceRuntimeException("rpc/encoded WSDL style not supported for endpoint reference " + endpointReference);
        } else if (wsBinding.isDocEncoded()){
            throw new ServiceRuntimeException("doc/encoded WSDL style not supported for endpoint reference " + endpointReference);
        }  else {
            // In the unit test the owner doc is null
            // so explicitly adopt the node instead
            // body.addDocument(((Node)args[0]).getOwnerDocument());
            Node msgNode = body.getOwnerDocument().importNode((Node)args[0], true);
            body.appendChild(msgNode);
        }        

        soapMessage.saveChanges();
        
        Dispatch<SOAPMessage> invocationDispatch = null;
        
        //TODO - captured static case as well???
        if (dynamicDispatchForCallback) {            
            Endpoint ep = msg.getTo();
            if (ep != null && ep.getBinding() != null) {
                String address = ep.getDeployedURI();
                invocationDispatch = createDynamicDispatch(address);
            } else {
                throw new ServiceRuntimeException("[BWS20025] Unable to determine destination endpoint for endpoint reference " + endpointReference);
            }
        } else {
            invocationDispatch = staticDispatch;
        }
        
        if (operation.isNonBlocking()) {
            invocationDispatch.invokeOneWay(soapMessage);
            return null;
        }

        if (action != null) {
            invocationDispatch.getRequestContext().put(Dispatch.SOAPACTION_USE_PROPERTY, true);
            invocationDispatch.getRequestContext().put(Dispatch.SOAPACTION_URI_PROPERTY, action);
        }
        SOAPMessage response = invocationDispatch.invoke(soapMessage);
        return response;
    }

    protected void setHeaders(SOAPHeader sh, Message msg, String action) throws SOAPException {

        Endpoint callbackEndpoint = msg.getFrom().getCallbackEndpoint();

        // add WS-Addressing header for the invocation of a bidirectional
        // service
        // FIXME: is there any way to use the Axis2 addressing support for this?
        //
        // IIUC, this 'if (callbackEndpoint != null)' will be true if:
        //   1)  This is a bidirectional interface   
        //      AND
        //   2)  We are invoking in the forward direction of the bidirectional interface.
        //
        if (callbackEndpoint != null) {
            // // Load the actual callback endpoint URI into an Axis EPR ready
            // to form the content of the wsa:From header
            // EndpointReference fromEPR = new
            // EndpointReference(callbackEndpoint.getBinding().getURI());
            //
            // addWSAFromHeader(sh, fromEPR);
            SOAPHeaderElement fromH = sh.addHeaderElement(QNAME_WSA_FROM);
            SOAPElement fromAddress = fromH.addChildElement(QNAME_WSA_ADDRESS);            
            fromAddress.setTextContent(callbackEndpoint.getDeployedURI());

            addWSAActionHeader(sh, action);

            // We need a wsa:MessageId for request-response operation per WS-Addressing core specification, 
            // (and Axis2 will choke if addressing module is enabled.)
            if (!operation.isNonBlocking()) {
                String messageId = UUID.randomUUID().toString();
                SOAPHeaderElement msgIdHeader = sh.addHeaderElement(QNAME_WSA_MESSAGEID);
                msgIdHeader.setTextContent(messageId);
            }
            
        } // end if

        String toAddress = getToAddress(msg);
        // requestMC.setTo( new EndpointReference(toAddress) );

        // IIUC, this 'if (callbackEndpoint != null)' will be true if:
        //   1)  This is a bidirectional interface   
        //      AND
        //   2)  We are invoking in the callback direction of the bidirectional interface.
        //
        if (isInvocationForCallback(msg)) {
            addWSAToHeader(sh, toAddress, msg);
            addWSARefParms(sh, msg);
            addWSAActionHeader(sh, action);
            addWSARelatesTo(sh, msg);
        } // end if

    }

    private String getToAddress(Message msg) throws ServiceRuntimeException {
        String address = null;

        // if target endpoint was not specified when this invoker was created,
        // use dynamically specified target endpoint passed in with the message

        String to = getPortLocation();
        if (to == null) {
            Endpoint ep = msg.getTo();
            if (ep != null && ep.getBinding() != null) {
                address = ep.getDeployedURI();
            } else {
                throw new ServiceRuntimeException(
                                                  "[BWS20025] Unable to determine destination endpoint for endpoint reference " + endpointReference);
            }
        } else {
            address = to;
        }

        return address;
    } // end method getToAddress

    protected String getPortLocation() {
        String ep = null;
        if (wsBinding.getPort() != null) {
            List<?> wsdlPortExtensions = wsBinding.getPort().getExtensibilityElements();
            for (final Object extension : wsdlPortExtensions) {
                if (extension instanceof SOAPAddress) {
                    ep = ((SOAPAddress)extension).getLocationURI();
                    break;
                }
                if (extension instanceof SOAP12Address) {
                    SOAP12Address address = (SOAP12Address)extension;
                    ep = address.getLocationURI();
                    break;
                }
            }
        }
        if (ep == null || ep.equals("")) {
            ep = endpointReference.getDeployedURI();
        }
        return ep;
    }

    // private void addWSAFromHeader( SOAPHeader sh, EndpointReference fromEPR )
    // throws AxisFault {
    // OMElement epr = EndpointReferenceHelper.toOM(sh.getOMFactory(),
    // fromEPR,
    // QNAME_WSA_FROM,
    // AddressingConstants.Final.WSA_NAMESPACE);
    // sh.addChild(epr);
    //
    // } // end method addWSAFromHeader

    private static String WS_REF_PARMS = "WS_REFERENCE_PARAMETERS";

    private void addWSAToHeader(SOAPHeader sh, String address, Message msg) throws SOAPException {
        // Create wsa:To header which is required by ws-addressing spec
        // OMElement wsaToOM = sh.getOMFactory().createOMElement(QNAME_WSA_TO);
        // wsaToOM.setText( address );
        // sh.addChild(wsaToOM);
        SOAPHeaderElement toH = sh.addHeaderElement(QNAME_WSA_TO);
        toH.setTextContent(address);
    } // end method addWSAToHeader

    protected void addWSARefParms(SOAPHeader sh, Message msg) throws SOAPException {  

        // Not implemented and so will not pass compliance test BWS_5006.


    } // end method addWSARefParms
    
    
    private void addWSAActionHeader(SOAPHeader sh, String action) throws SOAPException {
        // Create wsa:Action header which is required by ws-addressing spec

        if (action == null) {
            PortType portType = ((WSDLInterface)wsBinding.getBindingInterfaceContract().getInterface()).getPortType();
            javax.wsdl.Operation op = portType.getOperation(operation.getName(), null, null);
            action = getActionFromInputElement(wsBinding.getGeneratedWSDLDocument(), portType, op, op.getInput());
        }

        // OMElement actionOM =
        // sh.getOMFactory().createOMElement(QNAME_WSA_ACTION);
        // actionOM.setText(action == null ? "" : action);
        // sh.addChild(actionOM);

        SOAPHeaderElement actionH = sh.addHeaderElement(QNAME_WSA_ACTION);
        actionH.setTextContent(action == null ? "" : action);

    } // end method addWSAActionHeader

    protected static String SCA_CALLBACK_REL = "http://docs.oasis-open.org/opencsa/sca-bindings/ws/callback";

    /**
     * Adds a wsa:RelatesTo SOAP header if the incoming invocation had a
     * wsa:MessageID SOAP header present - note that OASIS SCA requires that the
     * RelationshipType attribute is set to a particular SCA value
     * 
     * @param sh - the SOAP headers
     * @param msg - the message
     * @throws SOAPException
     */
    private void addWSARelatesTo(SOAPHeader sh, Message msg) throws SOAPException {
        
        //
        // Note that the 'core' (loosely speaking) part of the invocation chain 
        // will have already copied the forward message msgId to the RELATES_TO header.
        //
        String idValue = (String)msg.getHeaders().get(Constants.RELATES_TO);
        if (idValue != null) {
            SOAPHeaderElement relatesToH = sh.addHeaderElement(QNAME_WSA_RELATESTO);
            relatesToH.addAttribute(new QName(null, "RelationshipType"), SCA_CALLBACK_REL);
            relatesToH.setTextContent(idValue);
            // OMElement relatesToOM = sh.getOMFactory().createOMElement(
            // QNAME_WSA_RELATESTO );
            // OMAttribute relType =
            // sh.getOMFactory().createOMAttribute("RelationshipType", null,
            // SCA_CALLBACK_REL);
            // relatesToOM.addAttribute( relType );
            // relatesToOM.setText( idValue );
            // sh.addChild( relatesToOM );
        }
    } // end method addWSARelatesTo

    /**
     * Indicates if the invocation is for the callback of a bidirectional
     * service
     * 
     * @param msg the Message
     * @return true if the invocation is for the callback of a bidirectional
     *         service, false otherwise
     */
    private boolean isInvocationForCallback(Message msg) {
        org.apache.tuscany.sca.assembly.EndpointReference fromEPR = msg.getFrom();
        if (fromEPR != null) {
            ComponentReference ref = fromEPR.getReference();
            if (ref != null)
                return ref.isForCallback();
        } // end if
        return false;
    } // end method isInvocationForCallback

    /**
     * getActionFromInputElement
     * 
     * @param def the wsdl:definitions which contains the wsdl:portType
     * @param wsdl4jPortType the wsdl:portType which contains the wsdl:operation
     * @param op the wsdl:operation which contains the input element
     * @param input the input element to be examined to generate the wsa:Action
     * @return either the wsaw:Action from the input element or an action
     *         generated using the DefaultActionPattern
     */
    public static String getActionFromInputElement(Definition def,
                                                   PortType wsdl4jPortType,
                                                   javax.wsdl.Operation op,
                                                   Input input) {
        String result = getWSAWActionExtensionAttribute(input);
        if (result == null) {
            result = generateActionFromInputElement(def, wsdl4jPortType, op, input);
        }
        return result;
    }

    private static String getWSAWActionExtensionAttribute(AttributeExtensible ae) {
        // Search first for a wsaw:Action using the submission namespace
        Object attribute = ae.getExtensionAttribute(submissionWSAWNS);
        // Then if that did not exist one using the w3c WSAM namespace
        if (attribute == null) {
            attribute = ae.getExtensionAttribute(finalWSAMNS);
        }
        // Then if that did not exist one using the w3c WSAW namespace
        // (for backwards compat reasons)
        if (attribute == null) {
            attribute = ae.getExtensionAttribute(finalWSAWNS);
        }
        // Then finally if that did not exist, try the 2005/08 NS
        // (Included here because it's needed for Apache Muse)
        if (attribute == null) {
            attribute = ae.getExtensionAttribute(finalWSANS);
        }

        // wsdl4j may return a String, QName or a List of either
        // If it is a list, extract the first element
        if (attribute instanceof List) {
            List l = (List)attribute;
            if (l.size() > 0) {
                attribute = l.get(0);
            } else {
                attribute = null;
            }
        }

        // attribute must now be a QName or String or null
        // If it is a QName, take the LocalPart as a String
        if (attribute instanceof QName) {
            QName qn = (QName)attribute;
            attribute = qn.getLocalPart();
        }

        if ((attribute instanceof String)) {
            String result = (String)attribute;
            return result;
        } else {
            return null;
        }
    }

    /**
     * Generate the Action for an Input using the Default Action Pattern
     * <p/>
     * Pattern is defined as [target namespace][delimiter][port type
     * name][delimiter][input name]
     * 
     * @param def is required to obtain the targetNamespace
     * @param wsdl4jPortType is required to obtain the portType name
     * @param op is required to generate the input name if not explicitly
     *            specified
     * @param input is required for its name if specified
     * @return a wsa:Action value based on the Default Action Pattern and the
     *         provided objects
     */
    public static String generateActionFromInputElement(Definition def,
                                                        PortType wsdl4jPortType,
                                                        javax.wsdl.Operation op,
                                                        Input input) {
        // Get the targetNamespace of the wsdl:definitions
        String targetNamespace = def.getTargetNamespace();

        // Determine the delimiter. Per the spec: 'is ":" when the [target
        // namespace] is a URN, otherwise "/".
        // Note that for IRI schemes other than URNs which aren't path-based
        // (i.e. those that outlaw the "/"
        // character), the default action value may not conform to the rules of
        // the IRI scheme. Authors
        // are advised to specify explicit values in the WSDL in this case.'
        String delimiter = SLASH;
        if (targetNamespace.toLowerCase().startsWith(URN)) {
            delimiter = COLON;
        }

        // Get the portType name (as a string to be included in the action)
        String portTypeName = wsdl4jPortType.getQName().getLocalPart();
        // Get the name of the input element (and generate one if none
        // explicitly specified)
        String inputName = getNameFromInputElement(op, input);

        // Append the bits together
        StringBuffer sb = new StringBuffer();
        sb.append(targetNamespace);
        // Deal with the problem that the targetNamespace may or may not have a
        // trailing delimiter
        if (!targetNamespace.endsWith(delimiter)) {
            sb.append(delimiter);
        }
        sb.append(portTypeName);
        sb.append(delimiter);
        sb.append(inputName);

        // Resolve the action from the StringBuffer
        String result = sb.toString();

        return result;
    }

    /**
     * Get the name of the specified Input element using the rules defined in
     * WSDL 1.1 Section 2.4.5 http://www.w3.org/TR/wsdl#_names
     */
    private static String getNameFromInputElement(javax.wsdl.Operation op, Input input) {
        // Get the name from the input element if specified.
        String result = input.getName();

        // If not we'll have to generate it.
        if (result == null) {
            // If Request-Response or Solicit-Response do something special per
            // WSDL 1.1 Section 2.4.5
            OperationType operationType = op.getStyle();
            if (null != operationType) {
                if (operationType.equals(OperationType.REQUEST_RESPONSE)) {
                    result = op.getName() + REQUEST;
                } else if (operationType.equals(OperationType.SOLICIT_RESPONSE)) {
                    result = op.getName() + RESPONSE;
                }
            }
            // If the OperationType was not available for some reason, assume
            // on-way or notification
            if (result == null) {
                result = op.getName();
            }
        }
        return result;
    }

    private static final String URN = "urn";
    private static final String SLASH = "/";
    private static final String COLON = ":";
    private static final String REQUEST = "Request";
    private static final String RESPONSE = "Response";

    public boolean allowsPassByReference() {
        return true;
    }
}
