package de.uka.ipd.consensus.foundation.evolution;

import java.util.Properties;

import de.uka.ipd.consensus.foundation.ConsensusFoundationModule;
import de.uka.ipd.consensus.foundation.logging.LoggingManager;
import de.uka.ipd.consensus.foundation.ontology.OntologyManager;
import de.uka.ipd.consensus.foundation.rights.DynamicRightsManagerException;
import de.uka.ipd.consensus.foundation.schema.Association;
import de.uka.ipd.consensus.foundation.schema.Attribute;
import de.uka.ipd.consensus.foundation.schema.Topic;
import de.uka.ipd.consensus.foundation.schema.User;
import de.uka.ipd.consensus.foundation.user.UserManager;

/**
 * The EvolutionManager is responsible for major or destructive changes and keeping the ontology consistent.
 * 
 * <p>The EvolutionManager implementation can be configured with the key <code>cf.evolutionmanager</code>
 * in the <code>ConsensusFoundation.properties</code> configuration file. It's an optional component.</p>
 * 
 * <p>The implementation is loaded by the <code>ConsensusFoundation</code> constructor. For successful instantiation,
 * the EvolutionManager implementation must provide a default constructor without arguments.</p>
 * 
 * @author Thomas Much
 * @version 2006-06-14
 * @see de.uka.ipd.consensus.foundation.ConsensusFoundation
 * @see de.uka.ipd.consensus.foundation.ontology.OntologyManager
 */
public interface EvolutionManager extends ConsensusFoundationModule {

	/**
	 * <p>This method is called by the <code>ConsensusFoundation</code> constructor to initialize the EvolutionManager.
	 * @param config all entries from <code>ConsensusFoundation.properties</code>
	 * @param logging the successfully initialized LoggingManager instance
	 * @param users the the successfully initialized UserManager instance
	 * @param ontology the the successfully initialized OntologyManager instance
	 * @throws Exception if any error occurs (startup of the application is aborted in this case)
	 * @see de.uka.ipd.consensus.foundation.ConsensusFoundation#ConsensusFoundation()
	 */
	public void init(Properties config, LoggingManager logging, UserManager users, OntologyManager ontology) throws Exception;
	
	
	/**
	 * Deletes a topic and all dependant elements (attributes and, if it makes sense, associations), but not the subtopics of the topic.
	 * Especially for class topics this means that subclasses have to be moved higher in the hierarchy somehow.
	 * @param user the user who wants to delete the topic
	 * @param topic the topic to be deleted
	 * @throws EvolutionManagerException if the topic could not be deleted
	 * @throws DynamicRightsManagerException if the user is not allowed to delete the topic
	 * @throws java.lang.UnsupportedOperationException if the implementation does not support deletion of topics
	 * @see de.uka.ipd.consensus.foundation.schema.Topic#isClassTopic()
	 * @see de.uka.ipd.consensus.foundation.rights.DynamicRightsManager#mayDeleteTopic(User, Topic)
	 * @see de.uka.ipd.consensus.foundation.ontology.OntologyManager#deleteTopic(Topic)
	 * @see #deleteTopicAndSubtopics(User, Topic)
	 */
	public void deleteTopic(User user, Topic topic) throws EvolutionManagerException,DynamicRightsManagerException; 
	
	
	/**
	 * Deletes a topic and all dependant elements, including the subtopics of the topic.
	 * This method must take care if there are cycles in the topic hierarchy.
	 * @param user the user who wants to delete the topic
	 * @param topic the topic to be deleted
	 * @throws EvolutionManagerException if the topic and its subtopics could not be deleted
	 * @throws DynamicRightsManagerException if the user is not allowed to delete the topic and its subtopics
	 * @throws java.lang.UnsupportedOperationException if the implementation does not support deletion of topics
	 * @see de.uka.ipd.consensus.foundation.rights.DynamicRightsManager#mayDeleteTopic(User, Topic)
	 * @see de.uka.ipd.consensus.foundation.ontology.OntologyManager#deleteTopic(Topic)
	 * @see #deleteTopic(User, Topic)
	 */
	public void deleteTopicAndSubtopics(User user, Topic topic) throws EvolutionManagerException,DynamicRightsManagerException; 
	
	
	/**
	 * Deletes an association and all dependant elements (e.g. topics, if it makes sense).
	 * @param user the user who wants to delete the association
	 * @param assoc the association to be deleted
	 * @throws EvolutionManagerException if the association could not be deleted
	 * @throws DynamicRightsManagerException if the user is not allowed to delete the association
	 * @throws java.lang.UnsupportedOperationException if the implementation does not support deletion of associations
	 * @see de.uka.ipd.consensus.foundation.rights.DynamicRightsManager#mayDeleteAssociation(User, Association)
	 * @see de.uka.ipd.consensus.foundation.ontology.OntologyManager#deleteAssociation(Association)
	 */
	public void deleteAssociation(User user, Association assoc) throws EvolutionManagerException,DynamicRightsManagerException; 
	
	
	/**
	 * Deletes an attribute (and all dependant elements if there are any).
	 * @param user the user who wants to delete the attribute
	 * @param topic the topic from which the attribute will be removed
	 * @param attr the attribute to be deleted
	 * @throws EvolutionManagerException if the attribute could not be deleted
	 * @throws DynamicRightsManagerException if the user is not allowed to delete the attribute
	 * @throws java.lang.UnsupportedOperationException if the implementation does not support deletion of attributes
	 * @see de.uka.ipd.consensus.foundation.ontology.OntologyManager#deleteAttribute(Attribute)
	 */
	public void deleteAttribute(User user, Topic topic, Attribute attr) throws EvolutionManagerException,DynamicRightsManagerException; 

	
	/**
	 * Merges two topics.
	 * <p>Note that the topic returned is not necessarily one of the argument topics.
	 * An implementation may decide to return a newly created topic.</p>
	 * @param user the user who wants to merge the topics
	 * @param topic1 the first topic to be merged
	 * @param topic2 the second topic to be merged
	 * @return the merged topic
	 * @throws EvolutionManagerException if the two topics could not be merged
	 * @throws DynamicRightsManagerException if the user is not allowed to merge the topics
	 * @throws java.lang.UnsupportedOperationException if the implementation does not support merging of topics
	 * @see de.uka.ipd.consensus.foundation.rights.DynamicRightsManager#mayMergeTopics(User, Topic, Topic)
	 */
	public Topic mergeTopics(User user, Topic topic1, Topic topic2) throws EvolutionManagerException,DynamicRightsManagerException; 

	
	/**
	 * Converts an instance topic into a class topic.
	 * @param user the user who wants to convert the topic into a class topic
	 * @param instance the instance topic to be converted
	 * @return the converted class topic
	 * @throws EvolutionManagerException if the instance topic could not be converted into a class topic
	 * @throws DynamicRightsManagerException if the user is not allowed to convert the topic
	 * @throws java.lang.UnsupportedOperationException if the implementation does not support changing a topic's class flag
	 * @see de.uka.ipd.consensus.foundation.schema.Topic#isClassTopic()
	 */
	public Topic makeClass(User user, Topic instance) throws EvolutionManagerException,DynamicRightsManagerException; 
	
	
	/**
	 * Converts an instance topic into a class topic.
	 * <p>This is more than just calling <code>Topic.setClassTopic()</code> since the implementation has to take care
	 * what happens with subclasses of the class topic.
	 * @param user the user who wants to convert the topic into an instance topic
	 * @param cls the class topic to be converted
	 * @return the converted instance topic
	 * @throws EvolutionManagerException if the class topic could not be converted into an instance topic
	 * @throws DynamicRightsManagerException if the user is not allowed to convert the topic
	 * @throws java.lang.UnsupportedOperationException if the implementation does not support changing a topic's class flag
	 * @see de.uka.ipd.consensus.foundation.schema.Topic#isClassTopic()
	 */
	public Topic makeInstance(User user, Topic cls) throws EvolutionManagerException,DynamicRightsManagerException; 

	
	/**
	 * Registers a new EvolutionListener.
	 * @param listener the EvolutionListener to be added
	 */
	public void addEvolutionListener(EvolutionListener listener);
	
	
	/**
	 * Removes an EvolutionListener, if it is registered with the EvolutionManager (otherwise this call is ignored).
	 * @param listener the EvolutionListener to be removed
	 */
	public void removeEvolutionListener(EvolutionListener listener);

}
