(*
  $Id$
  ISO TC184/SC4/WG12 N2887 - ISO/IS 10303-41 Fundamentals of product description and support - EXPRESS
*) 


SCHEMA person_organization_schema;

REFERENCE FROM basic_attribute_schema   -- ISO 10303-41
  (description_attribute,
   get_description_value,
   get_id_value,
   get_name_value,
   get_role,
   id_attribute,
   name_attribute,
   object_role,
   role_association); 

REFERENCE FROM support_resource_schema   -- ISO 10303-41
  (bag_to_set,
   identifier,
   label,
   text); 


TYPE person_organization_select = SELECT
   (organization, 
    person, 
    person_and_organization);
END_TYPE; 

ENTITY address;
  internal_location : OPTIONAL label;
  street_number : OPTIONAL label;
  street : OPTIONAL label;
  postal_box : OPTIONAL label;
  town : OPTIONAL label;
  region : OPTIONAL label;
  postal_code : OPTIONAL label;
  country : OPTIONAL label;
  facsimile_number : OPTIONAL label;
  telephone_number : OPTIONAL label;
  electronic_mail_address : OPTIONAL label;
  telex_number : OPTIONAL label;
DERIVE
  name : label := get_name_value(SELF);
  url : identifier := get_id_value(SELF);
WHERE
  WR1: EXISTS(internal_location) OR EXISTS(street_number) OR EXISTS(street) OR EXISTS(postal_box) OR EXISTS(town) OR EXISTS(region) OR EXISTS(postal_code) OR EXISTS(country) OR EXISTS(facsimile_number) OR EXISTS(telephone_number) OR EXISTS(electronic_mail_address) OR EXISTS(telex_number);
END_ENTITY;

ENTITY organization;
  id : OPTIONAL identifier;
  name : label;
  description : OPTIONAL text;
END_ENTITY;

ENTITY organization_relationship;
  name : label;
  description : OPTIONAL text;
  relating_organization : organization;
  related_organization : organization;
END_ENTITY;

ENTITY organization_role;
  name : label;
DERIVE
  description : text := get_description_value(SELF);
WHERE
  WR1: SIZEOF (USEDIN (SELF, 'BASIC_ATTRIBUTE_SCHEMA.' + 'DESCRIPTION_ATTRIBUTE.DESCRIBED_ITEM')) <= 1;
END_ENTITY;

ENTITY organization_type;
  id : identifier;
  name : label;
  description : OPTIONAL text;
END_ENTITY;

ENTITY organization_type_relationship;
  id : identifier;
  name : label;
  description : OPTIONAL text;
  relating_organization_type : organization_type;
  related_organization_type : organization_type;
END_ENTITY;

ENTITY organizational_address
  SUBTYPE OF (address);
  organizations : SET[1:?] OF organization;
  description : OPTIONAL text;
END_ENTITY;

ENTITY organizational_project;
  name : label;
  description : OPTIONAL text;
  responsible_organizations : SET[1:?] OF organization;
DERIVE
  id : identifier := get_id_value (SELF);
WHERE
  WR1: SIZEOF (USEDIN (SELF, 'BASIC_ATTRIBUTE_SCHEMA.' + 'ID_ATTRIBUTE.IDENTIFIED_ITEM')) <= 1;
END_ENTITY;

ENTITY organizational_project_relationship;
  name : label;
  description : OPTIONAL text;
  relating_organizational_project : organizational_project;
  related_organizational_project : organizational_project;
END_ENTITY;

ENTITY person;
  id : identifier;
  last_name : OPTIONAL label;
  first_name : OPTIONAL label;
  middle_names : OPTIONAL LIST[1:?] OF label;
  prefix_titles : OPTIONAL LIST[1:?] OF label;
  suffix_titles : OPTIONAL LIST[1:?] OF label;
WHERE
  WR1: EXISTS(last_name) OR EXISTS(first_name);
END_ENTITY;

ENTITY person_and_organization;
  the_person : person;
  the_organization : organization;
DERIVE
  name : label := get_name_value (SELF);
  description : text := get_description_value(SELF);
  
WHERE
  WR1: SIZEOF (USEDIN (SELF, 'BASIC_ATTRIBUTE_SCHEMA.' + 'NAME_ATTRIBUTE.NAMED_ITEM')) <= 1;
  WR2: SIZEOF (USEDIN (SELF, 'BASIC_ATTRIBUTE_SCHEMA.' + 'DESCRIPTION_ATTRIBUTE.DESCRIBED_ITEM')) <= 1;
END_ENTITY;

ENTITY person_and_organization_role;
  name : label;
DERIVE
  description : text := get_description_value (SELF);
WHERE
  WR1: SIZEOF (USEDIN (SELF, 'BASIC_ATTRIBUTE_SCHEMA.' + 'DESCRIPTION_ATTRIBUTE.DESCRIBED_ITEM')) <= 1;
END_ENTITY;

ENTITY person_role;
  name : label;
DERIVE
  description : text := get_description_value (SELF);
WHERE
  WR1: SIZEOF (USEDIN (SELF, 'BASIC_ATTRIBUTE_SCHEMA.' + 'DESCRIPTION_ATTRIBUTE.DESCRIBED_ITEM')) <= 1;
END_ENTITY;

ENTITY person_type;
  id : identifier;
  name : label;
  description : OPTIONAL text;
END_ENTITY;

ENTITY person_type_definition;
  id : identifier;
  name : label;
  description : OPTIONAL text;
  formation : person_type_definition_formation;
END_ENTITY;

ENTITY person_type_definition_formation;
  id : identifier;
  name : label;
  description : OPTIONAL text;
  of_person_type : person_type;
END_ENTITY;

ENTITY person_type_definition_relationship;
  id : identifier;
  name : label;
  description : OPTIONAL text;
  relating_person_type_definition : person_type_definition;
  related_person_type_definition : person_type_definition;
END_ENTITY;

ENTITY personal_address
  SUBTYPE OF (address);
  people : SET[1:?] OF person;
  description : OPTIONAL text;
END_ENTITY;

ENTITY position_in_organization;
  id : identifier;
  name : label;
  description : OPTIONAL text;
END_ENTITY;

ENTITY position_in_organization_relationship;
  id : identifier;
  name : label;
  description : OPTIONAL text;
  relating_position_in_organization : position_in_organization;
  related_position_in_organization : position_in_organization;
END_ENTITY;

ENTITY position_in_organization_type;
  id : identifier;
  name : label;
  description : OPTIONAL text;
END_ENTITY;

FUNCTION acyclic_organization_relationship (relation : organization_relationship; relatives : SET [1:?] OF organization; specific_relation : STRING):BOOLEAN;
    LOCAL
      x : SET OF organization_relationship;
    END_LOCAL;

    IF relation.relating_organization IN relatives THEN
      RETURN (FALSE);
    END_IF;
    x := QUERY(org <* bag_to_set(USEDIN(relation.relating_organization, 'PERSON_ORGANIZATION_SCHEMA.' + 'ORGANIZATION_RELATIONSHIP.' + 'RELATED_ORGANIZATION')) | specific_relation IN TYPEOF(org));
    REPEAT i := 1 TO HIINDEX(x);
      IF NOT acyclic_organization_relationship(x[i], relatives + relation.relating_organization, specific_relation) THEN
        RETURN (FALSE);
      END_IF;
    END_REPEAT;
    RETURN (TRUE);
  END_FUNCTION; 

FUNCTION acyclic_organization_type_relationship
 (relation : organization_type_relationship; relatives : SET OF organization_type; specific_relation : STRING) : BOOLEAN; 
   LOCAL
      x : SET OF organization_type_relationship;
    END_LOCAL;

    IF relation.relating_organization_type IN relatives THEN
      RETURN (FALSE);
    END_IF;
    x := QUERY(orgtyp <* bag_to_set(USEDIN(relation.relating_organization_type, 'PERSON_ORGANIZATION_SCHEMA.' + 'ORGANIZATION_TYPE_RELATIONSHIP.' + 'RELATED_ORGANIZATION_TYPE')) | specific_relation IN TYPEOF(orgtyp));
    REPEAT i := 1 TO HIINDEX(x);
      IF NOT acyclic_organization_type_relationship(x[i], relatives + relation.relating_organization_type, specific_relation) THEN
        RETURN (FALSE);
      END_IF;
    END_REPEAT;
    RETURN (TRUE);
END_FUNCTION; 

FUNCTION acyclic_organizational_project_relationship (relation : organizational_project_relationship; relatives : SET [1:?] OF organizational_project; specific_relation : STRING):BOOLEAN;
    LOCAL
      x : SET OF organizational_project_relationship;
    END_LOCAL;

    IF relation.relating_organizational_project IN relatives THEN
      RETURN (FALSE);
    END_IF;
    x := QUERY(op <* bag_to_set(USEDIN(relation.relating_organizational_project, 'PERSON_ORGANIZATION_SCHEMA.' + 'ORGANIZATIONAL_PROJECT_RELATIONSHIP.' + 'RELATED_ORGANIZATIONAL_PROJECT')) | specific_relation IN TYPEOF(op));
    REPEAT i := 1 TO HIINDEX(x);
      IF NOT acyclic_organizational_project_relationship(x[i], relatives + relation.relating_organizational_project, specific_relation) THEN
        RETURN (FALSE);
      END_IF;
    END_REPEAT;
    RETURN (TRUE);
  END_FUNCTION; 

FUNCTION acyclic_person_type_definition_relationship
 (relation : person_type_definition_relationship; relatives : SET OF person_type_definition; specific_relation : STRING) : BOOLEAN; 
   LOCAL
      x : SET OF person_type_definition_relationship;
    END_LOCAL;

    IF relation.relating_person_type_definition IN relatives THEN
      RETURN (FALSE);
    END_IF;
    x := QUERY(ptdef <* bag_to_set(USEDIN(relation.relating_person_type_definition, 'PERSON_ORGANIZATION_SCHEMA.' + 'PERSON_TYPE_DEFINITION_RELATIONSHIP.' + 'RELATED_PERSON_TYPE_DEFINITION')) | specific_relation IN TYPEOF(ptdef));
    REPEAT i := 1 TO HIINDEX(x);
      IF NOT acyclic_person_type_definition_relationship(x[i], relatives + relation.relating_person_type_definition, specific_relation) THEN
        RETURN (FALSE);
      END_IF;
    END_REPEAT;
    RETURN (TRUE);
END_FUNCTION; 

FUNCTION acyclic_position_in_organization_relationship
 (relation : position_in_organization_relationship; relatives : SET OF position_in_organization; specific_relation : STRING) : BOOLEAN; 
   LOCAL
      x : SET OF position_in_organization_relationship;
    END_LOCAL;

    IF relation.relating_position_in_organization IN relatives THEN
      RETURN (FALSE);
    END_IF;
    x := QUERY(piorg <* bag_to_set(USEDIN(relation.relating_position_in_organization, 'PERSON_ORGANIZATION_SCHEMA.' + 'POSITION_IN_ORGANIZATION_RELATIONSHIP.' + 'RELATED_POSITION_IN_ORGANIZATION')) | specific_relation IN TYPEOF(piorg));
    REPEAT i := 1 TO HIINDEX(x);
      IF NOT acyclic_position_in_organization_relationship(x[i], relatives + relation.relating_position_in_organization, specific_relation) THEN
        RETURN (FALSE);
      END_IF;
    END_REPEAT;
    RETURN (TRUE);
END_FUNCTION; 

END_SCHEMA;  -- person_organization_schema
