// -*- IDL -*-

//=============================================================================
/**
 *  @file    PortableGroup.idl
 */
//=============================================================================

#ifndef _PORTABLEGROUP_IDL_
#define _PORTABLEGROUP_IDL_

#include "tao/PortableServer/PortableServer_include.pidl"
#include "CosNaming.idl"
#include "tao/IOP.pidl"
#include "tao/GIOP.pidl"
#include <orb.idl>
#include "PortableGroup_Simple_DS.idl"

module PortableGroup
{
  typeprefix PortableGroup "omg.org";

  /// MembershipStyle
  const string PG_MEMBERSHIP_STYLE =
  "org.omg.PortableGroup.MembershipStyle";

  /// InitialNumberMembers
  const string PG_INITIAL_NUMBER_MEMBERS =
  "org.omg.PortableGroup.InitialNumberMembers";

  /// MinimumNumberMembers
  const string PG_MINIMUM_NUMBER_MEMBERS =
  "org.omg.PortableGroup.MinimumNumberMembers";

  /// Factories
  const string PG_FACTORIES = "org.omg.PortableGroup.Factories";

  typedef sequence <octet> GroupIIOPProfile; // tag = TAG_GROUP_IIOP

  // Specification of Common Types and Exceptions for Group Management
  interface GenericFactory;

  typedef CORBA::RepositoryId _TypeId;
  typedef Object ObjectGroup;
  typedef sequence<ObjectGroup> ObjectGroups;
  typedef CosNaming::Name Name;
  typedef any Value;

  struct Property {
    Name nam;
    Value val;
  };

  typedef sequence<Property> Properties;
  typedef Name Location;
  typedef sequence<Location> Locations;
  typedef Properties Criteria;

  struct FactoryInfo {
    GenericFactory the_factory;
    Location the_location;
    Criteria the_criteria;
  };
  typedef sequence<FactoryInfo> FactoryInfos;

  typedef long MembershipStyleValue;
  const MembershipStyleValue MEMB_APP_CTRL = 0;
  const MembershipStyleValue MEMB_INF_CTRL = 1;

  typedef FactoryInfos FactoriesValue;
  typedef unsigned short InitialNumberMembersValue;
  typedef unsigned short MinimumNumberMembersValue;

  exception InterfaceNotFound {};
  exception ObjectGroupNotFound {};
  exception MemberNotFound {};
  exception ObjectNotFound {};
  exception MemberAlreadyPresent {};
  exception ObjectNotCreated {};
  exception ObjectNotAdded {};
  /// TAO Specific: TypeConfict exception
  exception TypeConflict {};
  exception UnsupportedProperty {
    Name nam;
    Value val;
  };

  exception InvalidProperty {
    Name nam;
    Value val;
  };

  exception NoFactory {
    Location the_location;
    _TypeId type_id;
  };

  exception InvalidCriteria {
    Criteria invalid_criteria;
  };

  exception CannotMeetCriteria {
    Criteria unmet_criteria;
  };

  // Specification of PropertyManager Interface
  interface PropertyManager {

    void set_default_properties (in Properties props)
      raises (InvalidProperty, UnsupportedProperty);

    Properties get_default_properties();

    void remove_default_properties (in Properties props)
      raises (InvalidProperty, UnsupportedProperty);

    void set_type_properties (in _TypeId type_id, in Properties overrides)
      raises (InvalidProperty, UnsupportedProperty);

    Properties get_type_properties(in _TypeId type_id);

    void remove_type_properties (in _TypeId type_id, in Properties props)
      raises (InvalidProperty, UnsupportedProperty);

    void set_properties_dynamically
      (in ObjectGroup object_group, in Properties overrides)
      raises (ObjectGroupNotFound,
              InvalidProperty,
              UnsupportedProperty);

    Properties get_properties (in ObjectGroup object_group)
      raises (ObjectGroupNotFound);
  }; // endPropertyManager


  // Specification of ObjectGroupManager Interface
  interface ObjectGroupManager {
    ObjectGroup create_member (in ObjectGroup object_group,
                               in Location the_location,
                               in _TypeId type_id,
                               in Criteria the_criteria)
      raises (ObjectGroupNotFound,
              MemberAlreadyPresent,
              NoFactory,
              ObjectNotCreated,
              InvalidCriteria,
              CannotMeetCriteria);

    ObjectGroup add_member (in ObjectGroup object_group,
                            in Location the_location,
                            in Object member)
      raises (ObjectGroupNotFound,
              MemberAlreadyPresent,
              ObjectNotAdded);

    ObjectGroup remove_member (in ObjectGroup object_group,
                               in Location the_location)
      raises (ObjectGroupNotFound, MemberNotFound);

    Locations locations_of_members (in ObjectGroup object_group)
      raises (ObjectGroupNotFound);

    ObjectGroups groups_at_location (in Location the_location);

    ObjectGroupId get_object_group_id (in ObjectGroup object_group)
      raises (ObjectGroupNotFound);

    ObjectGroup get_object_group_ref (in ObjectGroup object_group)
      raises (ObjectGroupNotFound);

    Object get_member_ref (in ObjectGroup object_group,
                           in Location loc)
      raises (ObjectGroupNotFound, MemberNotFound);

    // TAO-specific extension.
    ObjectGroup get_object_group_ref_from_id (
      in ObjectGroupId group_id)
      raises (ObjectGroupNotFound);

  }; // end ObjectGroupManager


  // Specification of GenericFactory Interface
  interface GenericFactory {
    typedef any FactoryCreationId;

    Object create_object (in _TypeId type_id,
                          in Criteria the_criteria,
                          out FactoryCreationId factory_creation_id)
      raises (NoFactory,
              ObjectNotCreated,
              InvalidCriteria,
              InvalidProperty,
              CannotMeetCriteria);

    void delete_object (in FactoryCreationId factory_creation_id)
      raises (ObjectNotFound);

  }; // end GenericFactory

  ///////////////////////
  // The following FactoryRegistry interface is not included in the OMG PortableGroup IDL.
  // It's an extension needed as part of implementing the FT CORBA specification.


  /**
   * a name for the role the object will play
   * This allows multiple objects that implement the same interface (TypeId)
   * to exist at a location as long as they play different roles.
   */
  typedef CORBA::Identifier RoleName;

  /**
   * Reserved criteria name for specifing role.
   */
  const string role_criterion = "org.omg.portablegroup.Role";

  /**
   * Interface to allow generic factories for replicas to register themselves.
   * Factories are distinguished by the role to be played by the created-object (role) and the
   * location at which they create the object (FactoryInfo.the_location)
   *
   * Because this is an extension to the FT CORBA specification applications that wish to
   * adhere to the specification as written should use the type id as the role name when
   * interacting with the FactoryRegistry.
   */
  interface FactoryRegistry
  {
    /**
     * register a factory to create objects of the given type
     * at the location given in the FactoryInfo.
     *
     * @param role the role the object-to-be-created plays.
     * @param type_id type id of the object-to-be-created.
     * @param factory_info information about the factory including its location.
     * @throws MemberAlreadyPresent if there is already a factory for this type of object
     *         at this location.
     * @throws TypeConflict if the specified type_id is different from the type_id previously
     *         registered for this role.
     */
    void register_factory(in RoleName role, in _TypeId type_id, in FactoryInfo factory_info)
      raises (MemberAlreadyPresent, TypeConflict);

    /**
     * Remove the registration of a factory.
     * @param role the role played by the object formerly created by this factory.
     * @param the_location where the factory formerly created objects.
     * @throws MemberNotFound if no factory is available for the given role at this location.
     */
    void unregister_factory(in RoleName role, in Location the_location)
      raises (MemberNotFound);

    /**
     * Remove the registration of all factories that create a particular type of object.
     * If no factories exist for the given type, the registry is unchanged.
     * This is not an error.
     * @param role the role played by the object formerly created by this factory.
     */
    void unregister_factory_by_role(in RoleName role);

    /**
     * Remove the registration of all factories that create objects at a particular location.
     * If the location is unknown the registry is unchanged.
     * This is not an error.
     * @param the_location where the factories formerly created objects.
     */
    void unregister_factory_by_location(in Location the_location);

    /**
     * List all the factories that create objects that fill a given role
     * If the role is unknown, an empty list is returned.  This is not an error.
     * @param role the type of object the factories create.
     * @param type_id what type of object is created to fill this role.
     */
    FactoryInfos list_factories_by_role(in RoleName role, out _TypeId type_id);

    /**
     * List all the factories that create a objects at a given location.
     * If no factories are registered for this location, an empty list is returned.
     * This is not an error.
     * @param the_location where the factories create objects.
     */
    FactoryInfos list_factories_by_location(in Location the_location);

  }; // end of FactoryRegistry


  const string TAO_UPDATE_OBJECT_GROUP_METHOD_NAME = "tao_update_object_group";

  interface TAO_UpdateObjectGroup {
    /**
     *  Pseudo used method to update IOGR in Object Group Members
     *  TAO specific.  The CORBA spec. doesn't address the issue.
     */
    void tao_update_object_group (
        in string iogr,
        in PortableGroup::ObjectGroupRefVersion version,
        in boolean is_primary);
  };

  exception NotAGroupObject {};
  typedef sequence <PortableServer::ObjectId> IDs;

  local interface GOA : PortableServer::POA {
    PortableServer::ObjectId create_id_for_reference(in Object the_ref)
      raises (NotAGroupObject);

    IDs reference_to_ids(in Object the_ref)
      raises (NotAGroupObject);

    void associate_reference_with_id (in Object ref,
                                      in PortableServer::ObjectId oid)
      raises (NotAGroupObject);

    void disassociate_reference_with_id (in Object ref,
                                         in PortableServer::ObjectId oid)
      raises (NotAGroupObject);
  };
}; // end PortableGroup

#endif  /* _PORTABLEGROUP_IDL_ */
