package org.ow2.jonas.ws.cxf;

import javax.xml.namespace.QName;
import javax.xml.ws.WebServiceException;

import org.apache.cxf.jaxws.support.JaxWsImplementorInfo;
import org.ow2.easybeans.api.bean.info.IWebServiceInfo;
import org.ow2.util.ee.metadata.ws.api.struct.IWebServiceMarker;

/**
 * The JOnASJaxWsImplementorInfo is needed because the webservices.xml infos
 * can overrides some info provided by annotations.
 *
 * @author Guillaume Sauthier
 */
public class JOnASJaxWsImplementorInfo extends JaxWsImplementorInfo {

    private String endpointInterface;
    private String protocolBinding;
    private String wsdlLocation;
    private QName serviceName;
    private QName portName;
    private boolean mtomEnabled = false;

    /**
     * Construct a new implementor info object.
     * @param implementorClass Implementor Class
     */
    public JOnASJaxWsImplementorInfo(final Class<?> implementorClass) {
        this(implementorClass, null, null, null, null, null, false);
    }

    /**
     * Construct a new implementor info object.
     * @param implementorClass Implementor Class
     * @param info Metadata about the port being deployed
     */
    public JOnASJaxWsImplementorInfo(final Class<?> implementorClass, final IWebServiceInfo info) {
        this(implementorClass,
                info.getEndpointInterface(),
                info.getProtocolBinding(),
                info.getWsdlLocation(),
                info.getServiceName(),
                info.getPortName(),
                info.isMTOMEnabled());
    }

    public JOnASJaxWsImplementorInfo(final Class<?> implementorClass, final IWebServiceMarker marker) {
        this(implementorClass,
                marker.getEndpointInterface(),
                marker.getProtocolBinding(),
                marker.getWsdlLocation(),
                marker.getServiceName(),
                marker.getPortName(),
                marker.isEnableMtom());
    }

    public JOnASJaxWsImplementorInfo(final Class<?> implementorClass,
                                     final String sei,
                                     final String protocolBinding,
                                     final String wsdlLocation,
                                     final QName serviceName,
                                     final QName portName,
                                     final boolean mtomEnabled) {
        super(implementorClass);
        this.endpointInterface = sei;
        this.protocolBinding = protocolBinding;
        this.wsdlLocation = wsdlLocation;
        this.serviceName = serviceName;
        this.portName = portName;
        this.mtomEnabled = mtomEnabled;
    }

    @Override
    public Class<?> getSEIClass() {
        if (this.endpointInterface != null) {

            // Load the overrided SEI class using the implementor ClassLoader
            ClassLoader loader = super.getImplementorClass().getClassLoader();
            try {
                return loader.loadClass(this.endpointInterface);
            } catch (ClassNotFoundException e) {
                throw new WebServiceException("SEI " + this.endpointInterface
                        + " is not accessible from ClassLoader " + loader, e);
            }
        }
        return super.getSEIClass();
    }

    @Override
    public String getBindingType() {
        if (this.protocolBinding != null) {
            return this.protocolBinding;
        }
        return super.getBindingType();
    }

    @Override
    public String getWsdlLocation() {
        if (this.wsdlLocation != null) {
            return this.wsdlLocation;
        }
        return super.getWsdlLocation();
    }

    /**
     * See use of targetNamespace in {@link javax.jws.WebService}.
     *
     * @return the qualified name of the service.
     */
    @Override
    public QName getServiceName() {
        if (this.serviceName != null) {
            return this.serviceName;
        }
        return super.getServiceName();
    }

    /**
     * See use of targetNamespace in {@link javax.jws.WebService}.
     *
     * @return the qualified name of the endpoint.
     */
    @Override
    public QName getEndpointName() {
        if (this.portName != null) {
            return this.portName;
        }
        return super.getEndpointName();
    }

    /**
     * @return true if MTOM is enabled, else false.
     */
    public boolean isMTOMEnabled() {
        return mtomEnabled;
    }

}
