/*
 * $RCSfile: DefaultSessionWsInvocationSender.java,v $
 * $Date: 2006/01/26 14:48:59 $
 * $Revision: 1.1.2.2 $
 * $Author: andreys $
 */

/*
 * Copyright (c) 2002-2003 IST-2004-2006-511731 ModelWare - ModelBus.
 * All rights reserved.
 *
 * This software is published under the terms of the ModelBus Software License
 * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * A copy of ModelBus Software License is provided with this distribution in
 * doc/LICENSE.txt file.
 */

/*
 * DefaultSessionWsInvocationSender.java Add description 
 * 
 * @author Andrey Sadovykh (LIP6)
 * @version $Revision: 1.1.2.2 $ $Date: 2006/01/26 14:48:59 $
 */
package org.eclipse.mddi.modelbus.adapter.infrastructure.transport.client.ws;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Properties;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;

import org.apache.log4j.Logger;
import org.eclipse.mddi.modelbus.adapter.infrastructure.model_manipulation.DescriptionUtil;
import org.eclipse.mddi.modelbus.adapter.infrastructure.transport.SessionManager;
import org.eclipse.mddi.modelbus.adapter.infrastructure.transport.SessionProviderProxy;
import org.eclipse.mddi.modelbus.adapter.infrastructure.transport.marshal.ws.AbstractMarshaler;
import org.eclipse.mddi.modelbus.adapter.infrastructure.transport.marshal.ws.DefaultSessionMarshaler;
import org.eclipse.mddi.modelbus.adapter.infrastructure.transport.marshal.ws.SoapUtil;
import org.eclipse.mddi.modelbus.adapter.user.ModelingServiceError;
import org.eclipse.mddi.modelbus.adapter.user.consumer.ModelBusCommunicationException;
import org.eclipse.mddi.modelbus.adapter.user.consumer.ModelTypeMismatchException;
import org.eclipse.mddi.modelbus.adapter.user.consumer.NoToolAvailableException;
import org.eclipse.mddi.modelbus.adapter.user.consumer.ServiceUnknownException;
import org.eclipse.mddi.modelbus.description.abstract_.ModelingService;
import org.eclipse.mddi.modelbus.description.abstract_.Parameter;

/*
 * DefaultSessionWsInvocationSender
 * 
 */

public class DefaultSessionWsInvocationSender extends DefaultWsInvocationSender
        implements SessionProviderProxy {

    public static final String NEW_SESSION_TAG = "newSession";

    public static final String END_SESSION_TAG = "endSession";

    private static Logger logger = Logger
            .getLogger(DefaultSessionWsInvocationSender.class);

    private SessionManager sessionManager;

    public DefaultSessionWsInvocationSender(Properties prop) {
        super(prop);
        setMarshaler(new DefaultSessionMarshaler(prop));
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.mddi.modelbus.adapter.infrastructure.transport.SessionProviderProxy#setSessionManager(org.eclipse.mddi.modelbus.adapter.infrastructure.transport.SessionManager)
     */
    public void setSessionManager(SessionManager sessionManager) {
        this.sessionManager = sessionManager;

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.mddi.modelbus.adapter.infrastructure.transport.SessionProviderProxy#newSession()
     */
    public String newSession() throws ModelBusCommunicationException {
        this.targetUrl = DescriptionUtil.getProperty(getToolDescription(), "URL");
        try {
            createNewSessionRequest();
            makeConnection();
            readNewSessionResponse();
        } catch (Exception e) {
            logger.error("Can't make newSession", e);
            throw new ModelBusCommunicationException("Can't make newSession", e);
        }

        // read sessionId
        String sessionId = ((DefaultSessionMarshaler) getMarshaler()).getSessionId();
        
        // update SessionManager
        sessionManager.putProviderProxy(sessionId, this);
        return sessionId;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.mddi.modelbus.adapter.infrastructure.transport.SessionProviderProxy#endSession(java.lang.String)
     */
    public void endSession(String sessionId)
            throws ModelBusCommunicationException {
        this.targetUrl = DescriptionUtil.getProperty(getToolDescription(), "URL");
        try {
            createEndSessionRequest();
            makeConnection();
            readEndSessionResponse();
        } catch (Exception e) {
            logger.error("Can't make endSession", e);
            throw new ModelBusCommunicationException("Can't make endSession", e);
        }
        // update SessionManager
        sessionManager.removeSession(sessionId);

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.mddi.modelbus.adapter.infrastructure.transport.SessionProviderProxy#getOpenSessions()
     */
    public String[] getOpenSessions() {
        return sessionManager.getOpenSessions(getToolDescription().getName()
                + "." + getToolDescription().getInterface().getName() + ".*");
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.mddi.modelbus.adapter.infrastructure.transport.SessionProviderProxy#invoke(org.eclipse.mddi.modelbus.description.abstract_.ModelingService,
     *      java.lang.Object[], java.lang.String)
     */
    public Object[] invoke(ModelingService ms, Object[] inputs, String sessionID)
            throws ServiceUnknownException, NoToolAvailableException,
            ModelTypeMismatchException, ModelBusCommunicationException,
            ModelingServiceError {
        // set session ID
        ((DefaultSessionMarshaler) getMarshaler()).setSessionId(sessionID);
        
        try {
            return invoke(ms, inputs);
        } catch (Exception e) {
            throw new ModelBusCommunicationException ("Can't invoke serivce at:"+this.targetUrl,e);
        }
        
    }

    public void createNewSessionRequest() throws SOAPException {
        requestMsg = SoapUtil.messageFactory.createMessage();
        SOAPBody requestbody = requestMsg.getSOAPBody();
        AbstractMarshaler.setNamespaces(requestbody);
        requestbody.addChildElement(NEW_SESSION_TAG, "modelbus");

    }

    public void readNewSessionResponse() throws Exception {
        SOAPBody responsebody = responseMsg.getSOAPBody();
        if (responsebody.hasFault()) {
            SOAPFault f = responsebody.getFault();
            if (AbstractMarshaler.isModelingServiceError(f)) {
                ModelingServiceError err = AbstractMarshaler
                        .unmarshallModelingServiceError(f);
                throw err;
            } else {
                throw new ModelBusCommunicationException(f.toString()
                        + "[ uri = " + targetUrl + "]");
            }

        } else {
            SOAPElement resTopElem = SoapUtil.getFirstChild(responsebody);
            if (resTopElem == null) {
                logger.error("Empty SOAP response");
                logger.debug(responsebody.toString());
                throw new ModelBusCommunicationException("Empty SOAP response");
            }
            getMarshaler().unmarshal((Parameter[]) null, resTopElem);
        }
    }

    public void createEndSessionRequest() throws Exception {
        requestMsg = SoapUtil.messageFactory.createMessage();
        SOAPBody requestbody = requestMsg.getSOAPBody();
        AbstractMarshaler.setNamespaces(requestbody);
        SOAPElement reqTopElem =requestbody.addChildElement(END_SESSION_TAG, "modelbus");
        getMarshaler().marshal((Parameter[]) null, null, reqTopElem);

    }

    public void readEndSessionResponse() throws SOAPException, IOException, ModelingServiceError, ModelBusCommunicationException {
        SOAPBody responsebody = responseMsg.getSOAPBody();
        if (responsebody.hasFault()) {
            SOAPFault f = responsebody.getFault();
            if (AbstractMarshaler.isModelingServiceError(f)) {
                ModelingServiceError err = AbstractMarshaler
                        .unmarshallModelingServiceError(f);
                throw err;
            } else {
                throw new ModelBusCommunicationException(f.toString()
                        + "[ uri = " + targetUrl + "]");
            }

        } 
    }

    
    //TEST PURPOSE ONLY
    public static void main (String [] args){
        Properties p=null;
        DefaultSessionWsInvocationSender sender = new DefaultSessionWsInvocationSender(p);
        try {

            //marchaling newSession
            
            sender.createNewSessionRequest();
            System.out.println("New Req:"+sender.requestMsg.getSOAPBody().toString());

            //marchaling endSession
            ((DefaultSessionMarshaler) sender.getMarshaler()).setSessionId("AAAA");
            sender.createEndSessionRequest();
            System.out.println("End Req:"+sender.requestMsg.getSOAPBody().toString());
            
            //unmarchaling newSession
            String xmlString =
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
                "                   xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
                "                   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
                " <soapenv:Body>\n" +
                " <modelbus:newSessionResponse xmlns:modelbus=\"http://www.modelware-ist.org/modelbus\">"+
                "<modelbus:sessionId>BBBBB</modelbus:sessionId>"+
                "</modelbus:newSessionResponse>\n" +
                " </soapenv:Body>\n" +
                "</soapenv:Envelope>";


            MessageFactory mf = MessageFactory.newInstance();
            sender.responseMsg = 
                mf.createMessage(new MimeHeaders(), new ByteArrayInputStream(xmlString.getBytes()));
            sender.readNewSessionResponse();
            
            System.out.println("newSession Read sessionId:"+((DefaultSessionMarshaler)sender.getMarshaler()).getSessionId());
            
            //unmarchal endSession
            xmlString ="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
            "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
            "                   xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
            "                   xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
            " <soapenv:Body>\n" +
            " <modelbus:endSessionResponse xmlns:modelbus=\"http://www.modelware-ist.org/modelbus\">"+
            "<modelbus:sessionId>CCCCCC</modelbus:sessionId>"+
            "</modelbus:endSessionResponse>\n" +
            " </soapenv:Body>\n" +
            "</soapenv:Envelope>";
            mf = MessageFactory.newInstance();
            sender.responseMsg = 
                mf.createMessage(new MimeHeaders(), new ByteArrayInputStream(xmlString.getBytes()));
            sender.readNewSessionResponse();
            
            System.out.println("endSession Read sessionId:"+((DefaultSessionMarshaler)sender.getMarshaler()).getSessionId());
            
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
}
