/**
  * File: SubgroupsHandler.idl
  * Content: UMA corba definition for the Domain Group Handler's subgroup operations
  * Author: LuisM Pena
  * Date: 28th November 2000
  * Version: 0.51.00
  * Last change:
  *         12th April 2001: state transfer inclusion
  *
  *
  **/

#ifndef SUBGROUPS_HANDLER_IDL
#define SUBGROUPS_HANDLER_IDL

#include "DomainExceptions.idl"
#include "StateTransfer.idl"

module sensei
{

  module middleware
  {

    module domains
    {

      /***********************************************************************/
      /************************* SUBGROUP ************************************/
      /***********************************************************************/

      typedef long SubgroupId;
      typedef sequence<SubgroupId> SubgroupIdsList;
      const long EVERY_SUBGROUP = 0;
      const long MAX_STATIC_SUBGROUP_ID = 65535; //static subgroups cannot have a bigger group id

      /***********************************************************************/
      /************************* SUBGROUPS HANDLER EXCEPTION *****************/
      /***********************************************************************/

      enum SubgroupsHandlerExceptionReason
      {
        SubgroupIdAlreadyInUse,       //Subgroup ID already in use
        InvalidStaticSubgroupId,      //Subgroup ID given to register an static subgroup is not valid
        InvalidDynamicSubgroupId,     //Subgroup ID given to register an static subgroup is not valid
        DynamicBehaviourNotRegistered //Dynamic behaviour not registered
      };

      exception SubgroupsHandlerException
      {
        SubgroupsHandlerExceptionReason reason;
      };

      /***********************************************************************/
      /************************* DYNAMIC SUBGROUP INFO ***********************/
      /***********************************************************************/

      /**
       * Defines the information associated to a dynamic subgroup, supplied by the application
       */
      valuetype DynamicSubgroupInfo
      {
      };

      /**
       * Defines a convenient DynamicSubgroupInfo where the information is specified as a String
       */
      valuetype DynamicSubgroupInfoAsString : DynamicSubgroupInfo
      {
        public string info;
      };
      /***********************************************************************/
      /************************* DYNAMIC SUBGROUPS USER **********************/
      /***********************************************************************/

      /**
       * Defines the interface to be used by members using the SubgroupsHandler interface
       * with dynamic groups
       */
      interface DynamicSubgroupsUser
      {
        /**
         * Request during state transfer to accept an existing dynamic subgroup; a subgroup must be returned,
         */
        GroupMember acceptSubgroup(in SubgroupId id, in DynamicSubgroupInfo info);

        /**
         * Notification that a subgroup has been dynamically created. A subgroup must be returned,
         */
        GroupMember subgroupCreated(in GroupMemberId creator, in SubgroupId id, in DynamicSubgroupInfo info);

        /**
         * Notification that a subgroup has been dynamically removed.
         */
        void subgroupRemoved(in GroupMemberId remover, in SubgroupId id, in DynamicSubgroupInfo info);
      };

      /***********************************************************************/
      /************************* SUBGROUPS HANDLER ***************************/
      /***********************************************************************/

      /**
       *  Interface supporting subgroups handling
       **/
      interface SubgroupsHandler
      {
        /**
         * Sets a DynamicSubgroupsUser listener. This user must be set before the member joins
         * a group, or an exception is raised
         */
        void setDynamicSubgroupsUser(in DynamicSubgroupsUser user)
          raises (MemberStateException);

        /**
          * Registers a static subgroup with a specific ID. This ID must be unique in the object and also
          * in the group. The group cannot have been activated yet, or an exception is raised.
          * Every member must have defined the same subgroups when the group is joined.
          * Once joined, it is not possible anymore to use registerSubgroup, as the subgroups
          * must be dynamically registered.
          * The subgroups registered with this method cannot be later unregistered.
          * The subgroupId must be a valid static subgroup Id (lower or equal to MAX_STATIC_SUBGROUP_ID)
          * or the subgroup is not registered and an exception is raised
          * @exception MemberStateException if the member has not yet joined a group, or it has been expulsed
          * @exception SubgroupsHandlerException if the subgroupId specified is not valid (not static)
          **/
        void registerSubgroup(in SubgroupId uniqueSubgroupId, in GroupMember subgroup)
         raises (MemberStateException, SubgroupsHandlerException);

        /**
          * Registers a group dynamically, only possible when the member belongs already to a group and
          * has registered a dynamic subgroups user.
          * When this method is invoked, every member in the group, included this one, receives a invocation
          * through createdSubgroup, and a Subgroup must be supplied.
          * @exception MemberStateException if the member has not yet joined a group, or it has been expulsed
          * @exception SubgroupsHandlerException if the member does not support dynamic groups
          **/
        void castSubgroupCreation(in DynamicSubgroupInfo info)
         raises (MemberStateException, SubgroupsHandlerException);

        /**
          * Registers a group dynamically, only possible when the member belongs already to a group and
          * has registered a dynamic subgroups user.
          * When this method is invoked, every member in the group, included this one, receives a invocation
          * through createdSubgroup, and a Subgroup must be supplied.
          * this call blocks until the subgroup is registered, returning the created subgroupId
          * @exception MemberStateException if the member has not yet joined a group, or it has been expulsed
          * @exception SubgroupsHandlerException if the member does not support dynamic groups
          **/
        SubgroupId createSubgroup(in DynamicSubgroupInfo info, in GroupMember subgroup)
         raises (MemberStateException, SubgroupsHandlerException);

         /**
          * Removes the given subgroup. Only dynamic subgroups can be removed.
          * If the group is static, an exception is raised. If the subgroup does not exist, false is returned
          * Every member in the group receives a removedSubgroup notification
          * @exception MemberStateException if the member has not yet joined a group, or it has been expulsed
          * @exception SubgroupsHandlerException if the member does not support dynamic groups or the
          *       subgroupId given is describes a static subgroup
          */
         boolean removeSubgroup(in SubgroupId id, in DynamicSubgroupInfo info)
           raises (MemberStateException, SubgroupsHandlerException);

         /**
          * Returns the existing groups, statics and dynamics
          */
        SubgroupIdsList getSubgroups();

         /**
          * Returns the subgroup associated to a given subgroupId, null if not existing
          */
        GroupMember getSubgroup(in SubgroupId id);

         /**
          * Returns the subgroupId for a group. If the group is not valid, EVERY_SUBGROUP is returned
          */
        SubgroupId getSubgroupId(in GroupMember subgroup);
      };
    };
  };
};

#endif