/*
 * $Id: CORBAWorkflowService.java,v 1.3 2004/11/10 15:02:53 koppy Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 * 
 * Created on 06.07.2004
 *
 * $Log: CORBAWorkflowService.java,v $
 * Revision 1.3  2004/11/10 15:02:53  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.2  2004/09/20 10:26:15  koppy
 * +javadoc Dokumentation
 *
 * Revision 1.1  2004/08/30 14:49:58  koppy
 * Initiale Version der Workflow-Komponente
 *
 */
package vkc.workflow.service;

import java.io.OutputStream;

import org.enhydra.shark.api.client.wfbase.BaseException;
import org.enhydra.shark.api.client.wfservice.ConnectFailed;
import org.omg.CORBA.ORB;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming.NamingContextHelper;

import vkc.misc.VKCLogManager;
import vkc.view.WebShare;
import vkc.workflow.service.corba.CORBAPackageManager;
import vkc.workflow.service.corba.CORBAProcessManager;
import vkc.workflow.service.corba.CORBARepositoryManager;
import vkc.workflow.service.corba.CORBAUserMappingManager;
import vkc.workflow.service.corba.CORBAWorklistManager;
import vkc.workflow.service.manager.PackageManager;
import vkc.workflow.service.manager.ProcessManager;
import vkc.workflow.service.manager.RepositoryManager;
import vkc.workflow.service.manager.UserMappingManager;
import vkc.workflow.service.manager.WorklistManager;
import vkc.workflow.util.JaWEUtils;
import vkc.workflow.util.SharkUtils;
import WorkflowModel.WfProcess;
import WorkflowService.AdminMisc;
import WorkflowService.ExecutionAdministration;
import WorkflowService.PackageAdministration;
import WorkflowService.SharkConnection;
import WorkflowService.SharkInterface;
import WorkflowService.SharkInterfaceHelper;

/**
 * This class represents the CORBA client implementation
 * of the VKC workflow service.
 * 
 * @author Andreas Koop
 */
public class CORBAWorkflowService implements VKCWorkflowService {

    /**
     * name of the workflow engine
     */
    private String engine = null;

    /**
     * reference on the shark interface
     */
    private SharkInterface shark = null;

    /**
     * package manager
     */
    private PackageManager packageManager = null;

    /**
     * repository manager
     */
    private RepositoryManager repositoryManager = null;

    /**
     * usermapping manager
     */
    private UserMappingManager userMappingManager = null;

    /**
     * worklist manager
     */
    private WorklistManager worklistManager = null;

    /**
     * process manager
     */
    private ProcessManager processManager = null;

    /**
     * constructor for the 
     * CORBA workflow service
     */
    public CORBAWorkflowService() {

        engine = WebShare.getProperties().getProperty("vkc.workflow.engine",
                "Shark").trim();
        String host = WebShare.getProperties().getProperty("vkc.workflow.host",
                "localhost").trim();
        String port = WebShare.getProperties().getProperty("vkc.workflow.port",
                "10123").trim();

        try {
            shark = findWorkflowServer(host, port);

        } catch (Exception e) {
            VKCLogManager.errorLog(this, "", e.getMessage(),e);
            VKCLogManager.errorLog(this, "",
                    "Could not connect to CORBA SharkServer!", e);
        }

        packageManager = new CORBAPackageManager(this);
        repositoryManager = new CORBARepositoryManager(this);
        userMappingManager = new CORBAUserMappingManager(this);
        worklistManager = new CORBAWorklistManager(this);
        processManager = new CORBAProcessManager(this);
    }

    /**
     * @return Returns the shark.
     */
    public SharkInterface getShark() {
        return shark;
    }

    /** 
     * (non-Javadoc)
     * @see vkc.workflow.service.VKCWorkflowService#connect(java.lang.String, java.lang.String)
     */
    public WfMConnection connect(String username, String pwd)
            throws BaseException, ConnectFailed {

        SharkConnection sConn = null;
        
        try {
            sConn = shark.getSharkConnection();
        } catch (RuntimeException e1) {
            // Falls der SHARK-Server neu gestartet wurde
            // dann wird er noch einmal zu erreichen versucht.
            try {
                shark = findWorkflowServer(
                        WebShare.getProperties().getProperty("vkc.workflow.host",
                        "localhost").trim(),
                        WebShare.getProperties().getProperty("vkc.workflow.port",
                        "10123").trim()
                );
                sConn = shark.getSharkConnection();
            } catch (Exception e2) {
                VKCLogManager.errorLog(this, "", "Connect failed!", e2);
                throw new ConnectFailed(e2);
            }
            
        }

        try {
            sConn.connect(username, pwd, engine, "");

        } catch (WfBase.BaseException e) {
            throw new BaseException(e);
        } catch (WorkflowService.ConnectFailed e) {
            throw new ConnectFailed(e);
        }
        
        WfMConnection conn = new WfMConnection(sConn);
        conn.setUsername(username);
        conn.setPassword(pwd);
        conn.setEngine( engine );
        
        return conn;
    }
   
    /**
     * Returns the name of the corresponding workflow engine
     * @return name of the engine
     */
    public String getEngine(){
        return engine;
    }
    
    /** 
     * (non-Javadoc)
     * @see vkc.workflow.service.VKCWorkflowService#writeProcessGraph(java.lang.String, java.lang.String, java.lang.String, java.io.OutputStream)
     */
    public void writeProcessGraph(String userName, String pwd, String procId,
            OutputStream out) {

        ExecutionAdministration ea = null;
        AdminMisc adminMisc = shark.getAdminInterface().getAdminMisc();
        PackageAdministration pkgAdmin = this.getPackageAdministration();
        try {
            ea = shark.getAdminInterface().getExecutionAdministration();
            ea.connect(userName, pwd, engine, "");
            adminMisc.connect(userName, pwd, engine, "");
            pkgAdmin.connect(userName, pwd, engine, "");

            WfProcess wfProcess = ea.getProcess(procId);
            if (wfProcess == null)
                return;

            JaWEUtils.writeProcessGraphAsJPG(adminMisc, pkgAdmin, wfProcess,
                    out);

        } catch (Exception e) {
            VKCLogManager.errorLog(this, "", e.getMessage(),e);
        } catch (ThreadDeath e) {
            VKCLogManager.errorLog(this, "", e.getMessage(),e);
        } finally {
            SharkUtils.disconnect(ea);
            SharkUtils.disconnect(adminMisc);
            SharkUtils.disconnect(pkgAdmin);
        }

    }

    /** 
     * (non-Javadoc)
     * @see vkc.workflow.service.VKCWorkflowService#writeProcessDefGraph(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.io.OutputStream)
     */
    public void writeProcessDefGraph(String userName, String pwd, String pkgId, String procDefId,
            OutputStream out) {

        PackageAdministration pkgAdmin = this.getPackageAdministration();
        try {
            
            pkgAdmin.connect(userName, pwd, engine, "");

    
            JaWEUtils.writeProcessDefGraphAsJPG(pkgAdmin, pkgId, procDefId,
                    out);

        } catch (Exception e) {
            VKCLogManager.errorLog(this, "", e.getMessage(),e);
        } catch (ThreadDeath e) {
            VKCLogManager.errorLog(this, "", e.getMessage(),e);
        } finally {
            SharkUtils.disconnect(pkgAdmin);
        }

    }

    /**
     * Helper method for getting the package administration interface
     * @return the package administration interface
     */
    private PackageAdministration getPackageAdministration() {
        return shark.getAdminInterface().getPackageAdministration();
    }

    /**
     * Helper method for obtaining a reference to the shark
     * interface through CORBA.
     * 
     * @param host the hostname
     * @param port the port
     * @return reference to the shark interface
     * @throws Exception
     */
    private SharkInterface findWorkflowServer(String host, String port)
            throws Exception {

        String[] args = { "-ORBInitialHost", host, "-ORBInitialPort", port };
        // Create and initialize the ORB
        ORB orb = ORB.init(args, null);
        // Get the root naming context
        org.omg.CORBA.Object objRef = orb
                .resolve_initial_references("NameService");
        NamingContext ncRef = NamingContextHelper.narrow(objRef);

        // Resolve the object reference in naming
        NameComponent nc = new NameComponent(engine, "");
        NameComponent path[] = { nc };
        return SharkInterfaceHelper.narrow(ncRef.resolve(path));
    }

    /**
     * (non-Javadoc)
     * 
     * @see vkc.workflow.service.VKCWorkflowService#getPackageManager()
     */
    public PackageManager getPackageManager() {
        return packageManager;
    }

    /**
     * (non-Javadoc)
     * 
     * @see vkc.workflow.service.VKCWorkflowService#getRepositoryManager()
     */
    public RepositoryManager getRepositoryManager() {
        return repositoryManager;
    }

    /**
     * (non-Javadoc)
     * 
     * @see vkc.workflow.service.VKCWorkflowService#getUserMappingManager()
     */
    public UserMappingManager getUserMappingManager() {
        return userMappingManager;
    }

    /**
     * (non-Javadoc)
     * 
     * @see vkc.workflow.service.VKCWorkflowService#getWorklistManager()
     */
    public WorklistManager getWorklistManager() {
        return worklistManager;
    }

    /**
     * (non-Javadoc)
     * 
     * @see vkc.workflow.service.VKCWorkflowService#getProcessManager()
     */
    public ProcessManager getProcessManager() {
        return processManager;
    }

}
