/* $Id: SingletonServices.java,v 1.5 2005/08/26 04:45:00 ysahara Exp $
*
* Copyright (c)ARGO 21, Corporation. 2005.  All rights reserved.
 * 
 * This file is part of Nautica Workflow.
 * 
 *  Nautica Workflow is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 * 
 *  Nautica Workflow is distributed 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.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with Nautica Workflow; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *  
*/
package jp.co.argo21.nautica.workflow.sample.util;

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

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
import javax.xml.rpc.ServiceException;

import jp.co.argo21.nautica.workflow.security.simple.OrganizationManagerRemote;
import jp.co.argo21.nautica.workflow.security.simple.RoleManagerRemote;
import jp.co.argo21.nautica.workflow.security.simple.UserManagerRemote;
import jp.co.argo21.nautica.workflow.soap.WorkItemHandler;
import jp.co.argo21.nautica.workflow.soap.WorkItemHandlerServiceLocator;
import jp.co.argo21.nautica.workflow.soap.WorkflowEngineHandler;
import jp.co.argo21.nautica.workflow.soap.WorkflowEngineHandlerServiceLocator;
import jp.co.argo21.nautica.workflow.soap.WorkflowServiceConnector;
import jp.co.argo21.nautica.workflow.soap.WorkflowServiceConnectorServiceLocator;

/**
 * ワークフローエンジンとの接続を取得するクラス。
 * 
 * @author  ruchida(Argo 21, Corp.)
 * @version $Revision: 1.5 $
 * @since   Nautica Workflow 0.9
 */
public class SingletonServices {

    private WorkflowServiceConnector conn;
    private UserManagerRemote usm;
    private OrganizationManagerRemote osm;
    private RoleManagerRemote rsm;    
    private WorkItemHandler wih;    
    private WorkflowEngineHandler weh;
    
    private static final String FACTORY_INITIAL = "java.naming.factory.initial";
    private static final String CNCTXFACTORY = "com.sun.jndi.cosnaming.CNCtxFactory";
    private static final String PROVIDER_URL = "java.naming.provider.url";
    private String defaultUrl = "iiop://localhost:1050";
    
    private static final String USER_MANAGER = "WorkflowUserManager";
    private static final String ORGANIZATION_MANAGER = "WorkflowOrganizationManager";
    private static final String ROLE_MANAGER = "WorkflowRoleManager";
    
    private static String NAUTICA_WORKFLOW_URL = "nautica.workflow.url";
    
    private static final SingletonServices singleton = new SingletonServices();

    /**
     * コンストラクタ
     * 
     * @throws IOException
     */
    private SingletonServices() {
    }
    
    /**
     * このクラスのインスタンスを返す。
     * 
     * @return インスタンス
     */
    public static SingletonServices getInstance() {
        return singleton;
    }
    
    /**
     * ユーザ管理を返す。
     * 
     * @return ユーザ管理
     * @throws NamingException ネーミング例外が発生した場合
     */
    public UserManagerRemote getUserManager() throws NamingException, IOException {
        if (usm == null) {
            System.setProperty(FACTORY_INITIAL, CNCTXFACTORY);
            String url = getNauticaWorkflowConfig(NAUTICA_WORKFLOW_URL);
            if (url == null || url.equals("")) {
                System.setProperty(PROVIDER_URL, defaultUrl);
            } else {
                System.setProperty(PROVIDER_URL, url);
            }
            Context context = new InitialContext();
            Object ref = context.lookup(USER_MANAGER);
            usm = (UserManagerRemote) PortableRemoteObject.narrow(ref, UserManagerRemote.class);
        }
        return usm;
    }

    /**
     * 組織管理を返す。
     * 
     * @return 組織管理
     * @throws NamingException ネーミング例外が発生した場合
     */
    public OrganizationManagerRemote getOrganizationManager() throws NamingException, IOException {
        if (osm == null) {
            System.setProperty(FACTORY_INITIAL, CNCTXFACTORY);
            String url = getNauticaWorkflowConfig(NAUTICA_WORKFLOW_URL);
            if (url == null || url.equals("")) {
                System.setProperty(PROVIDER_URL, defaultUrl);
            } else {
                System.setProperty(PROVIDER_URL, url);
            }
            Context context = new InitialContext();
            Object ref = context.lookup(ORGANIZATION_MANAGER);
            osm = (OrganizationManagerRemote) PortableRemoteObject.narrow(ref,
                    OrganizationManagerRemote.class);
        }
        return osm;
    }

    /**
     * ロール管理を返す。
     * 
     * @return ロール管理
     * @throws NamingException ネーミング例外が発生した場合
     */
    public RoleManagerRemote getRoleManager() throws NamingException, IOException {
        if (rsm == null) {
            System.setProperty(FACTORY_INITIAL, CNCTXFACTORY);
            String url = getNauticaWorkflowConfig(NAUTICA_WORKFLOW_URL);
            if (url == null || url.equals("")) {
                System.setProperty(PROVIDER_URL, defaultUrl);
            } else {
                System.setProperty(PROVIDER_URL, url);
            }
            Context context = new InitialContext();
            Object ref = context.lookup(ROLE_MANAGER);
            rsm = (RoleManagerRemote) PortableRemoteObject.narrow(ref, RoleManagerRemote.class);
        }
        return rsm;
    }

    /**
     * ワークフローのコネクタを返す。
     * 
     * @return コネクタ
     * @throws ServiceException コネクタの取得に失敗した場合
     */
    public WorkflowServiceConnector getWfConnection() throws ServiceException {
        if (conn == null) {
            conn = new WorkflowServiceConnectorServiceLocator()
            .getWorkflowServiceConnector();
        }
        return conn;
    }
    
    /**
     * 作業項目のハンドラを返す。
     * 
     * @return 作業項目ハンドラ
     * @throws ServiceException 作業項目ハンドラの取得に失敗した場合
     */
    public WorkItemHandler getWfWorkitemHandler() throws ServiceException {
        if (wih == null) {
            wih = new WorkItemHandlerServiceLocator().getWorkItemHandler();
        }
        return wih;
    }
    
    /**
     * エンジンのハンドラを返す。
     * 
     * @return エンジンハンドラ
     * @throws ServiceException エンジンハンドラの取得に失敗した場合
     */
    public WorkflowEngineHandler getWfEngineHandler() throws ServiceException {
        if (weh == null) {
            weh = new WorkflowEngineHandlerServiceLocator().getWorkflowEngineHandler();
        }
        return weh;
    }
    
    /**
     * 設定情報を返す。
     * 
     * @param key キー
     * @return キーに対応する値
     * @throws IOException ロードに失敗した場合
     */
    private String getNauticaWorkflowConfig(String key) throws IOException {
        InputStream is = 
            SingletonServices.class.getClassLoader().
            getResourceAsStream("../conf/nautica.properties");
        Properties props = new Properties();
        props.load(is);
        
        return (String) props.get(key);
    }
    
    /**
     * 設定されたプロセス定義IDを返す。
     * 
     * @param key キー
     * @return キーに対応する値
     * @throws IOException ロードに失敗した場合
     */
    public String getProcessDefID(String key) throws IOException {
        InputStream is = 
            SingletonServices.class.getClassLoader().
            getResourceAsStream("../conf/sample.properties");
        Properties props = new Properties();
        props.load(is);
        
        return (String) props.get(key);
    }
}