/*
 * $RCSfile: AdapterStubImpl.java,v $
 * $Date: 2006/01/26 14:48:59 $
 * $Revision: 1.2.2.3 $
 * $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.
 */
 
/*
 * AdapterStubImpl.java 
 * 
 * @author Prawee Sriplakich, Andrey Sadovykh (LIP6)
 * @version $Revision: 1.2.2.3 $ $Date: 2006/01/26 14:48:59 $
 */
package org.eclipse.mddi.modelbus.adapter.user.impl;

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

import org.apache.log4j.Logger;
import org.eclipse.mddi.modelbus.adapter.infrastructure.AdapterContainerImpl;
import org.eclipse.mddi.modelbus.adapter.infrastructure.DeploymentException;
import org.eclipse.mddi.modelbus.adapter.infrastructure.LoggerConfigurator;
import org.eclipse.mddi.modelbus.adapter.infrastructure.model_manipulation.DescriptionUtil;
import org.eclipse.mddi.modelbus.adapter.infrastructure.model_manipulation.ModelUtil;
import org.eclipse.mddi.modelbus.adapter.infrastructure.notification.NotifServiceManager;
import org.eclipse.mddi.modelbus.adapter.infrastructure.notification.NotifServiceNotAvailableException;
import org.eclipse.mddi.modelbus.adapter.infrastructure.registry.DefaultToolSelector;
import org.eclipse.mddi.modelbus.adapter.infrastructure.registry.RegistryManager;
import org.eclipse.mddi.modelbus.adapter.infrastructure.registry.RegistryNotAvailableException;
import org.eclipse.mddi.modelbus.adapter.infrastructure.registry.ToolSelectionStrategy;
import org.eclipse.mddi.modelbus.adapter.infrastructure.serialize.Serializer;
import org.eclipse.mddi.modelbus.adapter.infrastructure.serialize.emf_xmi.Xmi2EmfConversion;
import org.eclipse.mddi.modelbus.adapter.infrastructure.transport.TransportManager;
import org.eclipse.mddi.modelbus.adapter.user.AdapterStub;
import org.eclipse.mddi.modelbus.adapter.user.ToolStub;
import org.eclipse.mddi.modelbus.adapter.user.consumer.GenericConsumer;
import org.eclipse.mddi.modelbus.adapter.user.consumer.NoToolAvailableException;
import org.eclipse.mddi.modelbus.adapter.user.consumer.SpecificConsumer;
import org.eclipse.mddi.modelbus.adapter.user.consumer.SpecificInterfaceManager;
import org.eclipse.mddi.modelbus.adapter.user.consumer.impl.GenericConsumerImpl;
import org.eclipse.mddi.modelbus.adapter.user.notification.NotificationPublisher;
import org.eclipse.mddi.modelbus.description.concrete.Tool;

public class AdapterStubImpl implements AdapterStub {

    /**
     * Properties of the Adapter
     */
    Properties properties = null;
    
    
    /**
     * EMF object representing the tool description
     */
    Tool toolDescription = null;    
    

    private GenericConsumerImpl si = new GenericConsumerImpl(this);
    
    /**
     * Reference to a set of objects implementing Tool interfaces.
     * Allows linking the Adapter to the tool implementation
     */
    ToolStub toolStub = new ToolStubImpl();
    
    
    /**
     * tool selector applies the policies for selecting provider tools to be invoked.
     * This attribute can be changed if the consumer tool want to use its own policies for selecting tools.
     */
    ToolSelectionStrategy toolSelector = new DefaultToolSelector();
    
    
    TransportManager transportManager;
    
    
    private static Logger logger = Logger.getLogger(AdapterStubImpl.class);
    
    
    /**
     * Instanciation of an Adaptor.
     * 
     * @param initProperties allow Adapter to locate the resources necessary for execution.
     *   The properties include the followings: 
     *      <p>"registry_location"  URL specifying the Web Services location of the Registry
     *      <p>"notification_service_location" URL specifying the Web Services location of the NotificationService
     *      <p>"tool_desc_file" Path location of tool description file in XMI format
     * @throws DeploymentException
     */
    public AdapterStubImpl(Properties initProperties) throws DeploymentException  {
        LoggerConfigurator.configure();
        properties = initProperties;
        String registry_loc = properties.getProperty(PROP_REGISTRY_LOCATION); 
        transportManager = new TransportManager(this);
        
        DeploymentException ex = new DeploymentException();
        if(registry_loc!=null) {
          try {
            // create a client that manages the communication with Registry
              RegistryManager.getInstance().getRegistryClient(registry_loc);
          } catch (RegistryNotAvailableException e) {
            ex.addProblem("RegistryNotAvailable", e);
          }
        }
        String ns_loc = properties.getProperty(PROP_NOTIF_LOCATION);
        if(ns_loc!=null) {
          try {
            // create a client that manages the communication with Notification Service  
              NotifServiceManager.getInstance().getNotificationServiceClient(ns_loc);
          } catch (NotifServiceNotAvailableException e) {
            ex.addProblem("NotifServiceNotAvaiable", e);
          }    
        }
        try {
            loadDescription();
        } catch (IOException e) {
            ex.addProblem("Bad tool description file", e);
        }
        if(ex.hasProblems()) {
            throw ex;    
        }              
    }
    
    




    private void loadDescription() throws IOException {
        String toolDescFile = properties.getProperty(PROP_TOOL_DESC_FILE);
        if(toolDescFile==null) {
          //This is a consumer-only tool, perhaps
          return;    
        }
        Collection emfobjs = Xmi2EmfConversion.convertFromFile(toolDescFile, false);
        Collection col = ModelUtil.findElementByType(emfobjs, "Tool");
        if(col.isEmpty()) {
           throw new IOException("No tool description found in " +toolDescFile);
        } else if(col.size()>1) {
           logger.warn("Warning. Several Tool Description found in " + toolDescFile);    
        }
        toolDescription = (Tool)col.iterator().next();
        //Adding all meta-model defitinitions to the toolDescription
        DescriptionUtil.importAllMetamodels(toolDescription);
        
    }
    
    
    /**
     * Allows the tool to invoke Modeling Services of other tools via the Generic interface
     * @param toolName The name of the tool providing Modeling Services
     * @return an object responsible for invoking Modeling Services
     * @deprecated
     * @see getGenericConsumer
     */
    public GenericConsumer getGenericServiceInvocation() {
        
        return getGenericConsumer();
    }
    
    /**
     * Allows the tool to invoke Modeling Services of other tools via the Generic interface
     * @param toolName The name of the tool providing Modeling Services
     * @return an object responsible for invoking Modeling Services
     */
    public GenericConsumer getGenericConsumer() {
        return si;
    }
    
    
    /**
     * Allows the tool to invoke Modeling Services of other tools via tool-specific interfaces
     * @param toolName The name of the tool providing Modeling Services
     * @return an object responsible for invoking Modeling Services
     */
    public SpecificConsumer getSpecificServiceInvocation(String modelingServiceInterfaceName) throws NoToolAvailableException {
        SpecificConsumer i = SpecificInterfaceManager.getInstance().getSpecificInterface(modelingServiceInterfaceName);
        if(i!=null) return i;
        throw new NoToolAvailableException("for ModelingServiceInterface " +modelingServiceInterfaceName);
    }
    

    /**
     * Allows the tool to publish notifications via its Adapter
     * @return An object that allows publishing notifications
     */
    public NotificationPublisher getNotificationPublisher() throws NotifServiceNotAvailableException {
        String notif_loc = properties.getProperty(PROP_NOTIF_LOCATION);
        if(notif_loc==null) {
           throw new NotifServiceNotAvailableException("no location specified", null);
        }
        NotificationPublisher pub;
        pub = NotifServiceManager.getInstance().getNotificationServiceClient(notif_loc);
        return pub;
    }
    

    /**
     * Allows obtaining the Tool implementation from the Adaptor
     * @return Reference to a set of objects implementing Tool interfaces
     */
    public ToolStub getToolStub() {
        return toolStub;
    }
    
    
    
    
    


    /**
     * Allows consulting tool description 
     * (for internal use inside ModelBus).
     * @return an EMF object representing the tool description
     */
    public Tool getToolDescription() {
        return toolDescription;
    }

    /**
     * @param toolDescription The toolDescription to set.
     */
    public void setToolDescription(Tool toolDescription) {
        this.toolDescription = toolDescription;
    }
    
    
    
    
    /**
     * @return Returns the prop.
     */
    public Properties getProperties() {
        return properties;
    }






    /**
     * @return Returns the toolSelector.
     */
    public ToolSelectionStrategy getToolSelector() {
        return toolSelector;
    }






    /**
     * @param toolSelector The toolSelector to set.
     */
    public void setToolSelector(ToolSelectionStrategy toolSelector) {
        this.toolSelector = toolSelector;
    }






    /**
     * @return Returns the transportManager.
     */
    public TransportManager getTransportManager() {
        return transportManager;
    }






    public void deploy() throws DeploymentException {
        AdapterContainerImpl.getInstance().deployAdapter(this);        
    }






    public void undeploy() throws DeploymentException {
        AdapterContainerImpl.getInstance().undeployAdapter(this);       
    }






    public void setSerializer(Serializer serializer) {
        getTransportManager().setSerializer(serializer);
        
    }



    
}
