/////////////////////////////////////////////////////////////////////////
//
// © University of Southampton IT Innovation Centre, 2004
//
// Copyright in this library belongs to the IT Innovation Centre of
// 2 Venture Road, Chilworth Science Park, Southampton, SO16 7NP, UK.
//
// This software may not be used, sold, licensed, transferred, copied
// or reproduced in whole or in part in any manner or form or in or
// on any media by any person other than in accordance with the terms
// of the Licence Agreement supplied with the software, or otherwise
// without the prior written consent of the copyright owners.
//
// This software is distributed WITHOUT ANY WARRANTY, without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE, except where stated in the Licence Agreement supplied with
// the software.
//
//      Created by:             Darren Marvin
//      Created date:           2004/04/30
//      Created for project:    GEMSS
//
/////////////////////////////////////////////////////////////////////////
//
//      Dependencies: None
//
/////////////////////////////////////////////////////////////////////////
//
//      Last commit info:       $Author: $
//                              $Date: $
//                              $Revision: $
//
/////////////////////////////////////////////////////////////////////////

package uk.ac.soton.itinnovation.gemss.transportmessaging.servicedescription.endpointtypes;

import eu.gemss.components.transport.servicedescription.*;
import eu.gemss.components.transport.servicedescription.endpointtypes.*;
import java.io.*;
import java.net.*;
import java.util.logging.*;
import org.apache.axis.utils.*;
import org.w3c.dom.*;
import org.xml.sax.*;

/**
 * WSDLEndpointImp implements the WSDLEndpoint interface and
 * provides information about the endpoint / access point for a WSDL service
 */
public class WSDLEndpointImp implements WSDLEndpoint {

    private static Logger mLogger = Logger.getLogger("uk.ac.soton.itinnovation.gemss.transportmessaging.servicedescription.endpointtypes.WSDLEndpointImp");

    private String mWSDLURI = null;
    private URL mEndpointURL = null;
    private Document mWSDLDocument = null;
    private String mServiceName = null;
    private String mPortName = null;

    public WSDLEndpointImp(URL endPointURL) throws ServiceDescriptionException {
       //this is the most risky since no validation that the endpoint is suitable takes place
        if(endPointURL==null) {
           mLogger.log(Level.SEVERE,"Endpoint URI is invalid");
           throw new ServiceDescriptionException("Endpoint URI is invalid");
        }
        mEndpointURL = endPointURL;
    }

    public WSDLEndpointImp(String wsdlURI,String serviceName, String portName) throws ServiceDescriptionException {
        if(wsdlURI==null || wsdlURI.equals("")) {
            mLogger.log(Level.SEVERE,"WSDL URI is invalid");
            throw new ServiceDescriptionException("WSDL URI is invalid");
        }
        if(serviceName==null || serviceName.equals("")) {
            mLogger.log(Level.SEVERE,"Service name is invalid");
            throw new ServiceDescriptionException("Service name is invalid");
        }
        mWSDLURI = wsdlURI;
        mServiceName = serviceName;
        mPortName = portName;
        //would like to retrieve the wsdl and cache it here but no security context exists yet
    }

    public WSDLEndpointImp(Document wsdlDoc,String serviceName, String portName) throws ServiceDescriptionException {
       if(wsdlDoc==null) {
           mLogger.log(Level.SEVERE,"WSDL Document is invalid");
           throw new ServiceDescriptionException("WSDL Document is invalid");
       }
       if(serviceName==null || serviceName.equals("")) {
            mLogger.log(Level.SEVERE,"Service name is invalid");
            throw new ServiceDescriptionException("Service name is invalid");
        }
        mWSDLDocument = wsdlDoc;
        mServiceName = serviceName;
        mPortName = portName;
    }

    /*
    public WSDLEndpointImp(String wsdlURI) throws ServiceDescriptionException {
        if(wsdlURI==null || wsdlURI.equals("")) {
            mLogger.log(Level.SEVERE,"WSDL URI is invalid");
            throw new ServiceDescriptionException("WSDL URI is invalid");
        }
        mWSDLURI = wsdlURI;
        //would like to retrieve the wsdl and cache it here but no security context exists yet
    }
    */
    /*
    public WSDLEndpointImp(Document wsdlDoc) throws ServiceDescriptionException {
       if(wsdlDoc==null) {
           mLogger.log(Level.SEVERE,"WSDL Document is invalid");
           throw new ServiceDescriptionException("WSDL Document is invalid");
       }
        mWSDLDocument = wsdlDoc;

    }
    */

    /**
     * Retrieve the URI for the actual WSDL definition document
     * @return URI string, returns null if wsdl uri not set
     */
    public final String getWSDLURI() {
        return mWSDLURI;
    }

    /**
     * Retrieve the WSDL document
     * @return WSDL document, returns null if document not set
     */
    public final Document getWSDLDocument() {
        return mWSDLDocument;
    }

    /**
     * Set the WSDL document
     * @param document WSDL document
     */
    public void setWSDLDocument(Document document) {
        mWSDLDocument = document;
    }

    /**
     * Retrieve the URI for endpoint / access point for the service
     * @return URI string, returns null if URL not set
     */
    public final URL getEndpointURL() {
        return mEndpointURL;
    }

    /**
     * Set the endpoint URL
     * @param endpointURL endpoint URL
     */
    public void setEndpointURI(URL endpointURL) {
        mEndpointURL = endpointURL;
    }

    /**
     * Retrieve the service name
     * @return service name, returns null if service name not set
     */
    public final String getServiceName() {
        return mServiceName;
    }

    /**
     * Set the service name
     * @param serviceName service name
     */
    public void setServiceName(String serviceName) {
        mServiceName = serviceName;
    }

    /**
     * Retrieve the port name
     * @return port name, returns null if not set
     */
    public String getPortName() {
        return mPortName;
    }

    /**
     * Set the port name
     * @param portName port name
     */
    public void setPortName(String portName) {
        mPortName = portName;
    }

    /**
     * Test to see if WSDL document is cached
     * @return true if cached, false otherwise
     */
    public boolean WSDLDocCached() {
        if(mWSDLDocument==null)
            return false;
        else
            return true;
    }

    /**
     * Test to see if endpoint set
     * @return true if set, false otherwise
     */
    public boolean endpointSet() {
        if(mEndpointURL==null)
            return false;
        else
            return true;

    }

    /**
     * Test to see if WSDL uri set
     * @return true if set, false otherwise
     *
     */
    public boolean wsdlURISet() {
        if(mWSDLURI==null)
            return false;
        else
            return true;
    }

    /**
     * Test to see if Service name has been set
     * @return true if set, false otherwise
     */
    public boolean serviceNameSet() {
        if(mServiceName==null)
            return false;
        else
            return true;
    }

    /**
     * Test to see if port name has been set
     * @return true if set, false otherwise
     */
    public boolean portNameSet() {
        if(mPortName==null)
            return false;
        else
            return true;
    }

    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
	    String strXML;
	    StringBuffer strBuffer;

	    try {
		    // write service name
		    if(mServiceName != null) {
			    out.writeBoolean(true);
			    out.writeObject(mServiceName);
		    }
		    else out.writeBoolean(false);

		    // write port name
		    if(mPortName != null) {
			    out.writeBoolean(true);
			    out.writeObject(mPortName);
		    }
		    else out.writeBoolean(false);

		    // write WSDL URI
		    if(mWSDLURI != null) {
			    out.writeBoolean(true);
			    out.writeObject(this.mWSDLURI);
		    }
		    else out.writeBoolean(false);

		    // write endpoint URL
		    if(mEndpointURL != null) {
			    out.writeBoolean(true);
			    out.writeObject(this.mEndpointURL.toExternalForm());
		    }
		    else out.writeBoolean(false);

		    // Using XMLUtils.DocumentToStream due to JDOM errors in removing xsd namespace

		    if( mWSDLDocument != null ) {
			    out.writeBoolean( true );

			    strXML = XMLUtils.DocumentToString( mWSDLDocument );
			    strBuffer = new StringBuffer( strXML );
			    out.writeObject( strBuffer );
		    }
		    else out.writeBoolean(false);
/*
		    // write WSDL doc (using JDOM)
		    // output trim, tabs etc added to make it nicer to debug and read. It also seems to solve
		    // some of the problems reading and writing using JDOM. [Stuart Oct03]
		    if(mWSDLDocument != null) {
			    out.writeBoolean(true);
			    document = (new DOMBuilder()).build(mWSDLDocument);
			    outputXML = new XMLOutputter();
			    outputXML.setTextTrim( true );
			    outputXML.setNewlines( true );
			    outputXML.setIndent("\t");
			    out.writeObject( outputXML.outputString(document) );
		    }
		    else out.writeBoolean(false);
*/
	    }
	    catch( Exception ex ) {
		    mLogger.log(Level.SEVERE,"Unable to serialize endpoint",ex);
		    throw new IOException("Unable to serialize WSDLEndpoint");
	    }
   }

   private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
	   boolean serviceNameExists, portNameExists, uriExists, endpointExists, wsdlDocExists;
	   InputSource inSource;
	   StringBuffer strBuffer;

	   try {
		   // read service name
		   serviceNameExists = in.readBoolean();
		   if(serviceNameExists) this.mServiceName = (String) in.readObject();

		   // read port name
		   portNameExists = in.readBoolean();
		   if(portNameExists) this.mPortName = (String) in.readObject();

		   // read WSDL URI
		   uriExists = in.readBoolean();
		   if(uriExists) this.mWSDLURI = (String) in.readObject();

		   // read endpoint
		   endpointExists = in.readBoolean();
		   if(endpointExists) this.mEndpointURL = new URL((String) in.readObject());

		   // read in the WSDL doc
		   // ignore whitespace (e.g. tabs) and do not do the validation thing since this seems to
		   // produce grammer errors etc in JDOM [Stuart Oct03]
		   wsdlDocExists = in.readBoolean();
		   if(wsdlDocExists) {
			   strBuffer = (StringBuffer) in.readObject();
			   inSource = new InputSource( new StringReader( strBuffer.toString() ) );
			   mWSDLDocument = XMLUtils.newDocument( inSource );

			   /* not using JDOM due to xsd namespace error
			   builder = new SAXBuilder();
			   builder.setValidation( false );
			   builder.setIgnoringElementContentWhitespace( false );
			   document = builder.build( new StringReader((String) in.readObject()) );
			   mWSDLDocument = (new DOMOutputter()).output(document);
			   */
		   }
	   }
	   catch( Exception ex ) {
		    mLogger.log(Level.SEVERE,"Unable to deserialize",ex);
		    throw new IOException("Unable to deserialize WSDLEndpoint");
	    }
    }
}
