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

import java.io.Serializable;
import java.util.Collection;

import de.uka.ipd.consensus.foundation.ontology.OntologyManagerException;
import de.uka.ipd.consensus.foundation.rights.DynamicRightsManagerException;

/**
 * This interface manages associations between topics which are separated into roles.
 * @author Thomas Much
 * @version 2006-06-14
 * @see Topic
 * @see AssociationRole
 * @see de.uka.ipd.consensus.foundation.ontology.OntologyManager#createAssociation(User, String, String, Topic)
 */
public interface Association extends Concept,Serializable,Comparable {

	/**
	 * Returns the type of the association.
	 * @return the associations's type or <code>null</code> if the association does not have a type
	 */
	public Topic getType();

	
	/**
	 * Sets the type of the association. If the implementation supports classes, the type must be a class topic.
	 * @param setter the user who wants to set the type
	 * @param type the type topic (or <code>null</code> to remove the type)
	 * @throws OntologyManagerException if the type could not be set
	 * @throws DynamicRightsManagerException if the user is not allowed to change the type
	 * @see Topic#isClassTopic()
	 * @see de.uka.ipd.consensus.foundation.rights.DynamicRightsManager#mayChangeAssociation(User, Association)
	 */
	public void setType(User setter, Topic type) throws OntologyManagerException,DynamicRightsManagerException;

	
	/**
	 * Returns a collection of all AssociationRole objects used by this association.
	 * This includes the typeless role if this association contains a typeless player topic.
	 * @param getter the user who wants to see the roles
	 * @return a possibly empty collection, never <code>null</code>
	 * @see AssociationRole
	 * @see de.uka.ipd.consensus.foundation.rights.DynamicRightsManager#mayViewTopic(User, Topic)
	 */
	public Collection getAssociationRoles(User getter);

	
	/**
	 * Returns the AssociationRole of a certain type.
	 * @param type the type topic of the desired role, <code>null</code> for the typeless role
	 * @return the role object of the given type or <code>null</code> if this association does not contain a player topic of the type
	 */
	public AssociationRole getAssociationRole(Topic type);


	/**
	 * Creates an association role of the given type if the role does not exist yet.
	 * The newly created or the already existing role is returned.
	 * @param adder the user who wants to add the role
	 * @param type the type topic of the role to be created, including <code>null</code> for the typeless role
	 * @return the role of the given type, never <code>null</code>
	 * @throws OntologyManagerException if the role could not be created
	 * @throws DynamicRightsManagerException if the user is not allowed to add the role
	 * @see de.uka.ipd.consensus.foundation.rights.DynamicRightsManager#mayChangeAssociation(User, Association)
	 */
	public AssociationRole addAssociationRole(User adder, Topic type) throws OntologyManagerException,DynamicRightsManagerException;
	
	
	/**
	 * Removes the association role of the given type. Its player topics are no longer part of this association afterwards
	 * (unless they are player of another role in this association).
	 * @param remover the user who wants to remove the role
	 * @param type the type of the role to be removed, including <code>null</code> for the typeless role
	 * @throws OntologyManagerException if the role could not be removed
	 * @throws DynamicRightsManagerException if the user is not allowed to remove the role
	 * @see de.uka.ipd.consensus.foundation.rights.DynamicRightsManager#mayChangeAssociation(User, Association)
	 */
	public void removeAssociationRole(User remover, Topic type) throws OntologyManagerException,DynamicRightsManagerException;


	/**
	 * Adds a topic to this association as a player of the given role. The AssociationRole is created if it does not exist yet.
	 * This is just a convenience method and simply delegates to AssociationRole.addTopic()!
	 * @param adder the user who wants to add the topic
	 * @param topic the topic to be added to this association
	 * @param roleType the player role of the topic, including <code>null</code> for the typeless role
	 * @throws OntologyManagerException if the topic could not be added
	 * @throws DynamicRightsManagerException if the user is not allowed to add the topic
	 * @see AssociationRole#addTopic(User, Topic)
	 * @see de.uka.ipd.consensus.foundation.rights.DynamicRightsManager#mayChangeAssociation(User, Association)
	 */
	public void addTopic(User adder, Topic topic, Topic roleType) throws OntologyManagerException,DynamicRightsManagerException;

	
	/**
	 * Removes a topic from the given role if it is player of the role.
	 * If the topic is no player of the role of the role does not exist, the call is ignored.
	 * This is just a convenience method and simply delegates to AssociationRole.removeTopic()!
	 * @param remover the user who wants to remove the topic
	 * @param topic the topic to be removed
	 * @param roleType the role that the topic to be removed plays, including <code>null</code> for the typeless role
	 * @throws OntologyManagerException if the topic could not be removed
	 * @throws DynamicRightsManagerException if the user is not allowed to remove the topic
	 * @see AssociationRole#removeTopic(User, Topic)
	 * @see de.uka.ipd.consensus.foundation.rights.DynamicRightsManager#mayChangeAssociation(User, Association)
	 */
	public void removeTopic(User remover, Topic topic, Topic roleType) throws OntologyManagerException,DynamicRightsManagerException;

	
	/**
	 * Queries if the topic is player of the given role in this association.
	 * This is just a convenience method and simply delegates to AssociationRole.hasTopic()!
	 * @param topic the queried topic
	 * @param roleType the role that this topic must play, including <code>null</code> for the typeless role
	 * @return <code>true</code> if the topic is player of the given role in this association, <code>false</code> otherwise
	 * @see AssociationRole#hasTopic(Topic)
	 */
	public boolean hasTopic(Topic topic, Topic roleType);


	/**
	 * Queries if the topic is player of any role (that the user is allowed to see) in this association.
	 * @param user the user who does the query
	 * @param topic the queried topic
	 * @return <code>true</code> if the topic is player of any role in this association, <code>false</code> otherwise
	 * @see de.uka.ipd.consensus.foundation.rights.DynamicRightsManager#mayViewTopic(User, Topic)
	 * @see AssociationRole#hasTopic(Topic)
	 */
	public boolean hasTopic(User user, Topic topic);
	
	
	/**
	 * Returns a collection of Topic player objects of the given role.
	 * This is just a convenience method and simply delegates to AssociationRole.getTopics()!
	 * @param getter the user who wants to see the topics
	 * @param roleType the role type,  ncluding <code>null</code> for the typeless role
	 * @return a possibly empty collection, never <code>null</code>
	 * @see de.uka.ipd.consensus.foundation.rights.DynamicRightsManager#mayViewTopic(User, Topic)
	 * @see AssociationRole#getTopics(User)
	 */
	public Collection getTopics(User getter, Topic roleType);

}
