/* DomainManagement.idl
   declares Domain, which manages domain members and domain policies
   some policies used to manage domains
*/


#include <orb.idl>
module org {
  module jacorb {
    module orb {
        module domain { // domain management

            /***** types *****/

            interface Domain;                      // forward declarations
            interface Membership;
            interface GraphNode;
            interface DomainNamingContext;
            interface DomainFactory;
            interface PolicyFactory;
            interface MetaPolicy;
            interface ObjectDomainMapper;

            typedef sequence <Domain> DomainList;
            typedef sequence <Object> ObjectList;
            typedef sequence <CORBA::PolicyType> PolicyTypeList;


            // for listeners that want to be informed of changes
            // in domain membership. Some policies might want to
            // know so that they can update displayed information
            // in specialized editors

            interface MembershipListener
            {
                oneway void memberRemoved(in Object exMember);
                oneway void memberAdded(in Object newbie);
            };


            /***** Domain *****/

            // a domain object manages two sets:
            // 1) set of object members
            // 2) set of domain policies

            exception PolicyTypeAlreadyDefined { CORBA::PolicyType type; };

            interface Domain : CORBA::DomainManager, GraphNode, Membership,
                DomainNamingContext, DomainFactory, PolicyFactory,
                ObjectDomainMapper
            {

                // the name of the domain
                attribute string name;

                // Policy operations

                // checks whether this domain has a policy of type "type"
                boolean hasPolicyOfType(in CORBA::PolicyType type);

                // sets the policy of the specified type
                // Pre : NOT hasPolicyOfType( policy.policy_type() )
                // Post:     hasPolicyOfType( policy.policy_type() )
                void set_domain_policy(in CORBA::Policy policy)
                    raises (PolicyTypeAlreadyDefined);

                // potentially overwrites a policy, use with care,
                // if unsecure, use set_domain_policy instead
                void overwrite_domain_policy(in CORBA::Policy policy);

                // removes a policy from the domain
                // Post:  NOT hasPolicyOfType( type )
                void deletePolicyOfType(in CORBA::PolicyType type);

                // get all policies of the domain
                CORBA::PolicyList getPolicies();
                unsigned long     getPolicyCount();

                // operations for managing set of object members

                void       insertMember(in Object obj);
                void       deleteMember(in Object obj);
                boolean       hasMember(in Object obj);
                // list all object members
                ObjectList    getMembers();
                unsigned long getMemberCount();

                // add and remove listeners
                void addMembershipListener( in MembershipListener listener );
                void removeMembershipListener( in MembershipListener listener );

            }; // Domain

            interface ORBDomain : Domain
            {
                // Pre :  The domain aDomain is in the same process capsule as the ORBDomain
                // Post:  isLocalTo(aDomain)
                void insertLocalDomain(in Domain aDomain);

                boolean isLocalTo(in Domain aDomain);

                // Post: NOT isLocalTo(aDomain)
                void removeLocalDomain(in Domain aDomain);

                void updateODMCache(in Object obj, in DomainList group);
                void invalidateODMCache(in Object obj);
                // adds  the domain aDomain to the  domains of obj
                // in the cache

                void addToODMCache(in Object obj, in Domain aDomain);
                // removes the domain  aDomain from the domains of
                // obj in the cache
                void removeFromODMCache(in Object obj, in Domain aDomain);

            };

            // ObjectNaming: provides an object in a domain with a name
            // the name is a key locally in the domain scope

            typedef string Name;
            typedef sequence <Name> NameList;
            exception NameAlreadyDefined { Name name; };
            exception InvalidName {        Name name; };

            interface DomainNamingContext
            {
                /// object names
                // the prefix used for auto naming
                attribute string NameAutoPrefix;

                // inserts an object as member into this domain, names it
                void insertMemberWithName(in Name objName, in Object obj)
                    raises (NameAlreadyDefined);

                // renames an object identified by its old name
                void renameMember(in string oldName, in string newName)
                    raises (InvalidName, NameAlreadyDefined);

                // object -> name
                Name getNameOf(in Object obj);

                // name -> object
                // returns  null if there  is no object  with name
                // objName in this domain
                Object resolveName(in Name objName);

                /// domain path names

                attribute string separator;	// default is "/"

                // finds a domain child identified by childName
                // returns null if there is no such child
                Domain findChild(in Name childName);

                // renames a child domain
                void renameChildDomain(in Name oldName, in Name newName)
                    raises (InvalidName, NameAlreadyDefined);

                // resolves a domain pathname, recursive version of findChild
                Domain resolveDomainPathName(in Name pathname) raises (InvalidName);

                NameList getPathNames();
                //  returns a list  of domain  path names  of this
                // domain may be  more than one, because there may
                // be multiple paths to the root domain
            };

            interface Membership
            {
                // obj -> list of domains
                DomainList getDomains(in Object obj);

                // obj -> Policy
                CORBA::Policy getPolicy( in Object obj,
                                         in CORBA::PolicyType type);

            }; // Membership



            interface DomainFactory
            {
                // Creates  a Domain object  with "initialMembers"
                // as initial members and "initialPolicies" as the
                // policies to begin  with. Both can be null which
                // then means empty.
                Domain createDomain
                    (
                     in ObjectList        initialMembers,
                     in CORBA::PolicyList initialPolicies,
                     in string            name
                     );

                //  creates  an   empty  domain  with  no  initial
                //  members,  no initial  policies  and the  empty
                //  string  as name  this  is  just a  convenience
                // operation
                Domain createEmptyDomain();

                // Pre: aDomain.getChildCount() == 0
                // destroys the domain aDomain, further use is prohibited
                void destroy(in Domain aDomain);
            };


            /********* graph node **********************/
            //  a  graph  node  supports  operation to  walk  a  graph
            // hierarchy up- and down

             interface GraphNode
             {

                 exception ClosesCycle {};

                 //  returns True  iff this  domain manager  has no
                 // parent domain services
                 boolean isRoot();

                 // only for testing, normally not here
                 Domain getRootDomain();

                 // boolean    hasIndirectMember(in Object obj);
                 // ObjectList getIndirectMembers();
                 // list all indirect object members


                 //  extending  policy  operations:  retrieves  the
                 // effecive policy for this domain may be computed
                 // dynamically depending on parent domain policies
                 CORBA::Policy getEffectiveDomainPolicy(in CORBA::PolicyType type);

                 // child domains

                 /* inserts a domain into this domain as a (direct)
                    child  domain
                    Pre:  NOT child.isReachable(this)
                    (to   prevent  cycles)   the   precondition  of
                    Domain.addParent  also  needs  to be  satisfied

                    Post:          this.hasChild(child)         AND
                    child.hasParent(this) */
                 void insertChild(in Domain child)
                     raises (ClosesCycle, NameAlreadyDefined );

                 // returns  true iff domain "aDomain"  is a direct
                 // child domain of this domain
                 boolean hasChild(in Domain aDomain);

                 // returns  true iff there exists  a directed path
                 //  from   this  domain  downwards   to  the  node
                 // "aDomain" (used to prevent cicles)
                 boolean isReachable(in Domain aDomain);

                 // returns  the (direct) child  domains registered
                 // at this domain
                 DomainList getChilds();

                 // returns the number of childs
                 unsigned long getChildCount();
                 // deletes a child domain
                 // Post:     NOT this.hasChild(domain_manager)
                 //       AND NOT domain_manager.hasParent(this)
                 void deleteChild(in Domain child);

                 // operations to walk and manage the domain hierarchy upwards

                 // Pre :
                 // Post: this.hasParent(parentDS) AND parentDS.hasChild(this)
                 //       AND NOT this.isRoot()
                 //       AND parentDS.getRootDomainService() == this.getRootDomainService()
                 //       (this is now a child domain of the parent domain parentDS and
                 //        they have the same root domain service)
                 void insertParent(in Domain parentDomain)  raises (ClosesCycle, NameAlreadyDefined);

                 // Post: NOT this.hasParent(parentDS) AND
                 // NOT parentDS.hasChild(this)
                 void deleteParent(in Domain parentDomain);

                 boolean       hasParent(in Domain parentDomain);
                 DomainList    getParents();
                 unsigned long getParentCount();

             };

            /************************* invariant ************************************

                  all domain  managers dm  and all domain  services ds
                  must fullfill the  invariants 1) dm.hasParent(ds) ==
                  ds.hasChild(dm), in other words dm and ds must agree
                  if there is a parent-child relationship between them

                  2)  Every  two  domain  (managers) d1  and  d2  must
                      follow:

                      a) NOT  (d1.hasChildOfAnyLevel(d2)    AND
                      d2.hasChildOfAnyLevel(d1)
                      (there are  no cycles in the domain graph)      #

                      b)         ((d1.hasChildOfAnyLevel(d2)        OR
                      d2.hasChildOfAnyLevel(d1)  ) =>  d1.getRoot() ==
                      d2.getRoot() (if there  exist a path between two
                      nodes, they must have the same unique root) */

            /***** ObjectDomainMapper (ODM) ****/

            // manages mappings of the form
            //
            //          object reference -> [dm(1), dm(2), ..., dm(n)]
            //               where dm(i), i from 1 to n, are domain managers

            interface ObjectDomainMapper
            {
                // Post: hasMapping(obj) AND  dms == getMapping(obj)
                //       AND for all dm e dms: areMapped(obj, dm)
                void insertMapping(in Object obj, in DomainList dms);

                // Post: NOT hasMapping(object)
                void deleteMapping(in Object obj);

                // Pre : hasMapping(obj)
                // returns the domain manager list associated with object obj
                DomainList getMapping(in Object obj);

                // is there a mapping defined for obj ? (could also be
                // the empty list)
                boolean hasMapping (in Object obj);

                // is obj mapped to dm ?
                boolean areMapped(in Object obj, in Domain dm);

                // Post: hasMapping(obj) AND areMapped(obj, dm)
                void addToMapping(in Object obj, in Domain dm);

                // Post: NOT areMapped(obj, dm)
                    void removeFromMapping(in Object obj, in Domain dm);

            };

            // **************  policies  *******************

            // policy types
            const CORBA::PolicyType MANAGEMENT_POLICY_ID          = 110;
            const CORBA::PolicyType PROPERTY_POLICY_ID            = 112;
            const CORBA::PolicyType META_PROPERTY_POLICY_ID       = 113;
            const CORBA::PolicyType CONFLICT_RESOLUTION_POLICY_ID = 114;
            const CORBA::PolicyType INITIAL_MAP_POLICY_ID         = 115;

            const CORBA::PolicyType TEST_POLICY_ID                = 120;


            interface ManagementPolicy : CORBA::Policy
            {
                //  a human  readable and  very short  (1-2 words)
                // description of this policy, may be displayed in
                // list or tree views
                attribute string short_description;

                // a human readable description and explanation of
                //  this  policy, may  be  displayed in  graphical
                // (help or properties) dialogs
                attribute string long_description;

            };

            // a meta policy manages other policies
            interface MetaPolicy : ManagementPolicy
            {
                // a list  of policy types for which  this policy is a
                // meta policy,  that means a meta policy  can be meta
                // for any number of policy types
                // Type zero stands for all policy types.
                readonly attribute PolicyTypeList managedTypes;
            };


            interface ConflictResolutionPolicy : MetaPolicy
            {
                // predefined strategies:
                const short FIRST       = 1;
                const short PARENT_RULES= 2;
                const short CHILD_RULES = 3;
                // to be continued...

                // returns the strategy of the used conflict resolution policy
                readonly attribute short strategy;

                //  Pre:   all  the   domain  managers  in   the  list
                //  overlappingDMs  overlap in  their  policy of  type
                //  overlapType
                // Post: returns a policy of type overlapType
                CORBA::Policy resolveConflict(in DomainList overlappingDMs,
                                              in CORBA::PolicyType overlapType);
            };

            // decides to which domain managers a new object reference gets mapped
            interface InitialMapPolicy : ManagementPolicy
            {
                // predefinded strategies:
                const short DEFAULT_DOMAIN = 1;
                const short TYPE_DOMAINS   = 2;
                // to be continued...

                // returns the strategy of the used initial map policy
                readonly attribute short strategy;

                // returns a list of domain managers, to which the newly created object
                    // reference "newReference" shall be associated with in respect to
                // a given root
                // Pre : newReference isn't mapped to any domain manager
                //       AND rootDomain.isRoot()
                // Post: for all dm e returned list:
                //                (dm == rootDomain  OR root.hasChildOfAnyLevel(dm)
                //
                DomainList OnReferenceCreation(in Object newReference,
                                               in Domain rootDomain);
            };

            interface InitialMapToDefaultDomainPolicy : InitialMapPolicy
            {
                Domain getDefaultDomain();
                void   setDefaultDomain(in Domain defaultDomain);
            };


            // types for PropertyPolicy
            typedef string PropertyName;
            typedef string PropertyValue;

            typedef sequence <PropertyName> PropertyNameList;
            exception PropertyAlreadyDefined {};

            //  A  property  policy   stands  for  a  whole  class  of
            // policies.  Therefore its type  can be set.  It  holds a
            // list of properties. A property consists of a name and a
            // value.

            interface PropertyPolicy: ManagementPolicy
            {
                // the name of the property policy itself
                attribute string name;

                // sets the type of this policy
                void setPolicyType(in CORBA::PolicyType type);

                // adds a new property.
                void put(in PropertyName name, in PropertyValue value)
                    raises (PropertyAlreadyDefined);

                // return  a list of  all valid property  names. These
                //  names can be  used to  get a  value of  a specific
                // property
                PropertyNameList getPropertyNames();

                // resolves the value  of a named property, returns ""
                // if property is undef
                PropertyValue getValueOfProperty(in PropertyName name);

                //  changes  the   property  value.  The  property  is
                //  identified by  its property  name If  the property
                // doesn't exist prior to operation call, the property
                // is inserted
                void changeValueOfProperty( in PropertyName name,
                                            in PropertyValue newValue);

                // returns true iff name is defined in property list
                boolean containsProperty(in PropertyName name);

                // removes a property
                // Post: NOT containsProperty(name)
                void removeProperty(in PropertyName name);

                // returns the number of valid properties
                long getPropertyCount();
            };



            // extension of a property policy by a meta policy
            interface MetaPropertyPolicy : MetaPolicy, PropertyPolicy
            {
                // sets the types for  which this property policy is a
                // meta policy
                void setManagedTypes(in PolicyTypeList types);
            };



            interface PolicyFactory // : CORBA::PolicyFactory
            {
                CORBA::Policy create_policy(in CORBA::PolicyType type,
                                            in any initValue)
                    raises (CORBA::PolicyError);

                InitialMapPolicy  createInitialMapPolicy(in short whichOne);
                ConflictResolutionPolicy createConflictResolutionPolicy(in short whichOne);
                PropertyPolicy      createPropertyPolicy();
                MetaPropertyPolicy  createMetaPropertyPolicy();
            };


            // a simple test policy
            interface TestPolicy : CORBA::Policy {
                attribute string description;
                string testFunction();
                string toString();
            };
        };
    };
};
};
