/* DomainManagement.idl
   declares Domain, which manages domain members and domain policies
	    some policies used to manage domains
   $Id: DomainManagement.idl,v 1.20 2001/02/06 15:43:49 jacorb Exp $
*/


#include <orb.idl> 
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;


            /***** 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);

                    CORBA::PolicyList getPolicies();     // get all policies of the domain
                    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);
                    ObjectList    getMembers();               // list all object members
                    unsigned long getMemberCount();

                }; // 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();
            };
        };
    };
};
