/*
 ************************************************************************
 *
 * Copyright (c) 2003-2004, C&C Research Laboratories, NEC Europe Ltd.
 *
 * Copyright in this software belongs to C&C Research Laboratories,
 * Rathausallee 10, 53757 Sankt Augustin, Germany.
 *
 * 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 :           G.A. Kohring
 *  Created for Project :  GEMSS (IST-2001-37153)
 *
 ************************************************************************
 *
 */

package eu.gemss.components;

import java.io.IOException;
import java.util.Set;

import eu.gemss.signals.Signal;
import eu.gemss.signals.SignalHandler;

/**
 * An interface to the component framework. The <tt>ComponentManager</tt>
 * locates the components and coordinates their interactions within the 
 * confines of the framework.
 */
public interface ComponentManager {

    /**
     * Returns a set view of the known providers for the specified component.
     *
     * @param component A <tt>String</tt> identifying the components whose
     *      providers one wishes to know.
     * @return An unmodifiable <tt>Set</tt> containing those providers
     *      implementing the specified component.
     */
    public Set getProviders( String component );

    /**
     * Returns a set view of all the component types this organizer knows 
     * about. 
     * The members of this
     * set are <code>String</code>s which identify the components by their
     * fully qualified class name.
     *
     * @return An unmodifiable <tt>Set</tt> containing all the known 
     *      components.
     */
    public Set getComponents();

    /**
     * Returns a new instance of the specified component irrespective
     * of the provider.
     * <p>
     * Note: Repeated calls to this method are not guaranteed to use the 
     * same provider. 
     *
     * @return an object implementing the specified component or <tt>null</tt>
     *      if no implementation for the specified component is found, or if
     *      the component cannot be instantiated for whatever reason.
     * @param name a <code>String</code> containing the name of the component
     *      whose instance is to be returned.
     */
    public Object getInstance(String name);

    /**
     * Returns a new instance of the specified component from the specified
     * provider.
     * <p>
     *
     * @param component specifies the component whose implementation is
     *      requested.
     * @param providerName the name of the desired provider. This string
     *      must match the string returned by the <tt>getName()</tt> method of
     *      {@link eu.gemss.components.providers.Provider}.
     * @return an object implementing the specified component or <tt>null</tt>
     *      if no implementation for the specified component is found, or if
     *      the component cannot be instantiated for whatever reason, or if
     *      the specified provider does not provide the specified component.
     */
    public Object getInstance( String component, String providerName );

    /**
     * Returns a new instance of an object fulfilling the specified 
     * service request.
     *
     * @see eu.gemss.components.ServiceRequest
     * @param sr a <code>ServiceRequest</code> object specifying the desired
     *      service
     * @return an object implementing the desired service or <tt>null</tt>
     *      if the desired service cannot be fulfilled.
     * @throws InvalidRequestException if the service request contains
     *      invalid data.
     */
    public Object getInstance( ServiceRequest sr ) 
                                    throws InvalidRequestException ;

    /**
     * Initiate management of the specified object using the specified
     * id.  If an instance with the specified id is
     * already being managed by the component manager, then it will not 
     * be overwritten.
     * <p>
     * This method can be used by to 
     * place local object instances under the session 
     * management control of the component manager. For the purposes of
     * session management, the classes whose instances are inserted must
     * implement the Java <tt>Serializable</tt> interface.
     *
     * @see #sessions
     * @param id specifies a <tt>String</tt> to be used for latter 
     *      retrieval of this instance.
     * @param obj specifies the object to be managed.
     * @return <tt>true</tt> if the instance was successfully stored, or
     *      <tt>false</tt> if the specified id is already in use.
     */
    public boolean manageInstance( String id, Object obj );

    /**
     * Retrieves the specifed object from the store of managed objects.
     * <p>
     *
     * @param id a <code>String</code> containing the name of an
     *       object currently being managed by this component manager. 
     * @return the object corresponding to specified <code>String</code>, or
            <code>null</code> if the specified id is not in use.
     */
    public Object getManagedInstance(String id);

    /**
     * Returns the set of all objects assignable to the specified class name
     * from those currently being actively managed by the component
     * manager.
     * More specifically, if <code>c</code> is the class for the specified
     * class name, then this method returns the set
     * containing all objects, <code>o</code>, for which
     * <code>c.isAssignableFrom(o)</code> returns true.
     * <p>
     *
     * @see #manageInstance
     * @param className a <code>String</code> containing the fully qualified
     *       name of the class of objects to return.
     * @return a set consistiong of <code>Objects</code> belonging to the
     *      specified class.
     */
    public Set getManagedInstances( String className );

    /**
     * Returns the set of all ids currently in use. This set consists of
     * <code>String</code>s used to identify the instances of objects
     * being actively managed by the component manager.
     * <p>
     * 
     * @see #manageInstance
     * @return an unmodifiable Set of all the ids currently in use.
     */
    public Set getManagedInstanceIDs();

    /**
     * Terminate managment of the object corresponding to the specified id.
     * If the specified object implements the <code>Terminable</code>
     * interface, the its <code>terminate()</code> method will be called.
     * If this was the last reference to the object, then it will be 
     * scheduled for finalization.
     *
     * @see eu.gemss.components.Terminable
     * @param id corresponding to the instance to be deleted.
     * @return <tt>true</tt> if the instance was deleted or <tt>false</tt>
     *      if the user does not have permission to delete the specified
     *      instance.
     */
    public boolean terminate( String id );

    /**
     * Terminates the specified object. If the specified object is currently
     * being managed by this component manager, it will be removed from the
     * list of managed objects as well.
     *
     * @see eu.gemss.components.Terminable
     * @param t an object implementing the <code>Terminable</code> interface.
     * @return <tt>true</tt> if the instance was terminated or <tt>false</tt>
     *      if the object could not be terminated.
     */
    boolean terminate( Terminable t );

    /**
     * Retrieves a list of all the previously saved sessions which this
     * component manager knows about. 
     * <p>
     * What constitutes a session is application dependent.
     * At the minimum, a
     * session consists of all the serializable components which are
     * currently being actively managed. (A list of the active components 
     * can be found
     * using {@link #getManagedInstanceIDs}.) If the application has any 
     * serializable objects
     * which it wishes to associate with a session, then it can add them to
     * the session using {@link #manageInstance}
     * <strong>before</strong> calling {@link #saveSession}.
     * When a session is reloaded, these objects will then be available
     * using {@link #getInstance}.
     *
     * @see #manageInstance
     * @see #getManagedInstance
     * @see #getManagedInstances
     * @see #saveSession
     * @return an array of <code>String</code>s containing the session ids.
     * @throws IOException if their were any problems 
     *      contacting the session repository.
     */
    public String[] sessions() throws IOException ;

    /**
     * Saves the current session under the specified session id. Session ids
     * identify a unique session. Once a session is saved, it cannot be
     * changed. Hence, a session id cannot be reused until its corresponding
     * session has been deleted using the
     * {@link #deleteSession} method.
     *
     * @see #sessions
     * @param sessionID a <code>String</code> containing the session id.
     * @throws IOException if the session id is in use or an
     *      I/O error occurs while saving the session to a repository.
     */
    public void saveSession( String sessionID ) throws IOException;

    /**
     * Loads the specified session. 
     * <p> <strong>NOTE:  </strong> When loading a session from storage,
     * any active components with the same ids will be terminated and 
     * replaced by those from the stored session.
     *
     * @see #sessions
     * @param sessionID a <code>String</code> containing the session id.
     * @throws IOException if the session id is in use or an
     *      I/O error occurs while loading the session from the repository.
     */
    public void loadSession( String sessionID ) throws IOException;

    /**
     * Deletes the specified session id.
     *
     * @see #sessions
     * @param sessionID a <code>String</code> containing the session id.
     * @return <code>true</code> if the session id was successfully deleted
     *      or <code>false</code> if the session id could not be deleted
     *      due to a lack of permission.
     * @throws IOException if their were any problems 
     *      contacting the session repository.
     */
    public boolean deleteSession( String sessionID ) throws IOException ;

    /**
     * Registers the specified signal handler for the specified signal type.
     * When a signal of the specified type is emitted by any component, the
     * the specified handler will be called.
     *
     * @param sh the <tt>SignalHandler</tt> which will process the given 
     *      signal.
     * @param signalType a <tt>String</tt> indicating the signal type.
     *
     */
    public void registerSignalHandler( SignalHandler sh, String signalType );

    /**
     * Send a signal to the registered signal handlers, if any.
     *
     * @param signal the <tt>Signal</tt> to be sent to the handlers.
     * @return an array of processed signals. If there are no handlers
     *      registered for the given signal, then the array will be empty.
     *
     */
    public Signal[] generateSignal( Signal signal );

    /**
     * Starts the daemon components (if any). 
     * Some components may need to run
     * as daemons throughout the lifetime of the client. Such components can
     * be noted in the configuration file and then started here.
     * <p>
     * A daemon component must implement the {@link java.lang.Runnable}
     * interface.
     * <p>
     * This method calls the <code>getDaemons()</code> method from
     * {@link eu.gemss.components.Configuration} to get the list of 
     * daemons which need starting.
     *
     * @see eu.gemss.components.Configuration
     * @see java.lang.Runnable
     */
    public void startDaemons();
}
