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


SCHEMA product_definition_schema;

REFERENCE FROM application_context_schema   -- ISO 10303-41
  (product_context,
   product_definition_context); 

REFERENCE FROM basic_attribute_schema   -- ISO 10303-41
  (get_id_value,
   get_name_value,
   name_attribute); 

REFERENCE FROM document_schema   -- ISO 10303-41
  (document); 

REFERENCE FROM effectivity_schema   -- ISO 10303-41
  (effectivity); 

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


TYPE source = ENUMERATION OF 
   (made,
    bought,
    not_known);
END_TYPE; 

ENTITY product;
  id : identifier;
  name : label;
  description : OPTIONAL text;
  frame_of_reference : SET[1:?] OF product_context;
END_ENTITY;

ENTITY product_category;
  name : label;
  description : OPTIONAL text;
DERIVE
  id : identifier := get_id_value (SELF);
WHERE
  WR1: SIZEOF (USEDIN (SELF, 'BASIC_ATTRIBUTE_SCHEMA.' + 'ID_ATTRIBUTE.IDENTIFIED_ITEM')) <= 1;
END_ENTITY;

ENTITY product_category_relationship;
  name : label;
  description : OPTIONAL text;
  category : product_category;
  sub_category : product_category;
WHERE
  WR1: acyclic_product_category_relationship (SELF, [SELF.sub_category]);
END_ENTITY;

ENTITY product_definition;
  id : identifier;
  description : OPTIONAL text;
  formation : product_definition_formation;
  frame_of_reference : product_definition_context;
DERIVE
  name : label := get_name_value (SELF);
WHERE
  WR1: SIZEOF (USEDIN (SELF, 'BASIC_ATTRIBUTE_SCHEMA.' + 'NAME_ATTRIBUTE.NAMED_ITEM')) <= 1;
END_ENTITY;

ENTITY product_definition_context_association;
  definition : product_definition;
  frame_of_reference : product_definition_context;
  role : product_definition_context_role;
END_ENTITY;

ENTITY product_definition_context_role;
  name : label;
  description : OPTIONAL text;
END_ENTITY;

ENTITY product_definition_effectivity
  SUBTYPE OF (effectivity);
  usage : product_definition_relationship;
WHERE
  WR1: SIZEOF (USEDIN (SELF, 'MANAGEMENT_RESOURCES_SCHEMA.' + 'EFFECTIVITY_ASSIGNMENT.ASSIGNED_EFFECTIVITY')) = 0;
END_ENTITY;

ENTITY product_definition_formation;
  id : identifier;
  description : OPTIONAL text;
  of_product : product;
UNIQUE
  UR1: id, of_product;
END_ENTITY;

ENTITY product_definition_formation_relationship;
  id : identifier;
  name : label;
  description : OPTIONAL text;
  relating_product_definition_formation : product_definition_formation;
  related_product_definition_formation : product_definition_formation;
END_ENTITY;

ENTITY product_definition_formation_with_specified_source
  SUBTYPE OF (product_definition_formation);
  make_or_buy : source;
END_ENTITY;

ENTITY product_definition_relationship;
  id : identifier;
  name : label;
  description : OPTIONAL text;
  relating_product_definition : product_definition;
  related_product_definition : product_definition;
END_ENTITY;

ENTITY product_definition_substitute;
  description : OPTIONAL text;
  context_relationship : product_definition_relationship;
  substitute_definition : product_definition;
DERIVE
  name : label := get_name_value (SELF);
WHERE
  WR1: context_relationship.related_product_definition :<>: substitute_definition;
  WR2: SIZEOF (USEDIN (SELF, 'BASIC_ATTRIBUTE_SCHEMA.' + 'NAME_ATTRIBUTE.NAMED_ITEM')) <= 1;
END_ENTITY;

ENTITY product_definition_with_associated_documents
  SUBTYPE OF (product_definition);
  documentation_ids : SET[1:?] OF document;
END_ENTITY;

ENTITY product_related_product_category
  SUBTYPE OF (product_category);
  products : SET[1:?] OF product;
END_ENTITY;

ENTITY product_relationship;
  id : identifier;
  name : label;
  description : OPTIONAL text;
  relating_product : product;
  related_product : product;
END_ENTITY;

FUNCTION acyclic_product_category_relationship
 (relation : product_category_relationship; children : SET OF product_category) : BOOLEAN; 
LOCAL
      x : SET OF product_category_relationship;
      local_children : SET OF product_category;
    END_LOCAL;

    REPEAT i := 1 TO HIINDEX(children);
      IF relation.category :=: children[i] THEN
        RETURN (FALSE);
      END_IF;
    END_REPEAT;
    x := bag_to_set(USEDIN(relation.category, 'PRODUCT_DEFINITION_SCHEMA.' + 'PRODUCT_CATEGORY_RELATIONSHIP.SUB_CATEGORY'));
    local_children := children + relation.category;
    IF SIZEOF(x) > 0 THEN
      REPEAT i := 1 TO HIINDEX(x);
        IF NOT acyclic_product_category_relationship(x[i], local_children) THEN
          RETURN (FALSE);
        END_IF;
      END_REPEAT;
    END_IF;
    RETURN (TRUE);
END_FUNCTION; 

FUNCTION acyclic_product_definition_formation_relationship
 (relation : product_definition_formation_relationship; relatives : SET[1:?] OF product_definition_formation; specific_relation : STRING) : BOOLEAN; 
 LOCAL
      x : SET OF product_definition_formation_relationship;
    END_LOCAL;

    IF relation.relating_product_definition_formation IN relatives THEN
      RETURN (FALSE);
    END_IF;
    x := QUERY(pdf <* bag_to_set(USEDIN(relation.relating_product_definition_formation, 'PRODUCT_DEFINITION_SCHEMA.' + 'PRODUCT_DEFINITION_FORMATION_RELATIONSHIP.' + 'RELATED_PRODUCT_DEFINITION_FORMATION')) | specific_relation IN TYPEOF(pdf));
    REPEAT i := 1 TO HIINDEX(x);
      IF NOT acyclic_product_definition_formation_relationship(x[i], relatives + relation.relating_product_definition_formation, specific_relation) THEN
        RETURN (FALSE);
      END_IF;
    END_REPEAT;
    RETURN (TRUE);
END_FUNCTION; 

FUNCTION acyclic_product_definition_relationship
 (relation : product_definition_relationship; relatives : SET[1:?] OF product_definition; specific_relation : STRING) : BOOLEAN; 
LOCAL
      x : SET OF product_definition_relationship;
    END_LOCAL;

    IF relation.relating_product_definition IN relatives THEN
      RETURN (FALSE);
    END_IF;
    x := QUERY(pd <* bag_to_set(USEDIN(relation.relating_product_definition, 'PRODUCT_DEFINITION_SCHEMA.' + 'PRODUCT_DEFINITION_RELATIONSHIP.' + 'RELATED_PRODUCT_DEFINITION')) | specific_relation IN TYPEOF(pd));
    REPEAT i := 1 TO HIINDEX(x);
      IF NOT acyclic_product_definition_relationship(x[i], relatives + relation.relating_product_definition, specific_relation) THEN
        RETURN (FALSE);
      END_IF;
    END_REPEAT;
RETURN (TRUE);
END_FUNCTION; 

FUNCTION acyclic_product_relationship
 (relation : product_relationship; relatives : SET[1:?] OF product; specific_relation : STRING) : BOOLEAN; 
 LOCAL
      x : SET OF product_relationship;
    END_LOCAL;

    IF relation.relating_product IN relatives THEN
      RETURN (FALSE);
    END_IF;
    x := QUERY(prod <* bag_to_set(USEDIN(relation.relating_product, 'PRODUCT_DEFINITION_SCHEMA.' + 'PRODUCT_RELATIONSHIP.' + 'RELATED_PRODUCT')) | specific_relation IN TYPEOF(prod));
    REPEAT i := 1 TO HIINDEX(x);
      IF NOT acyclic_product_relationship(x[i], relatives + relation.relating_product, specific_relation) THEN
        RETURN (FALSE);
      END_IF;
    END_REPEAT;
    RETURN (TRUE);
END_FUNCTION; 

FUNCTION get_product_definitions
 (c_def_instance : product) : SET OF product_definition; 
  LOCAL
      pd_set : SET OF product_definition_formation := [];
      pdr_set : SET OF product_definition := [];
    END_LOCAL;

    pd_set := bag_to_set(USEDIN(c_def_instance, 'PRODUCT_DEFINITION_SCHEMA.PRODUCT_DEFINITION_FORMATION.OF_PRODUCT'));
    IF (SIZEOF(pd_set) < 1) THEN
      RETURN (pdr_set);
    END_IF;
    REPEAT i := 1 TO HIINDEX(pd_set);
      pdr_set := pdr_set + bag_to_set(USEDIN(pd_set[i], 'PRODUCT_DEFINITION_SCHEMA.PRODUCT_DEFINITION.FORMATION'));
    END_REPEAT;
    RETURN (pdr_set);
END_FUNCTION; 

END_SCHEMA;  -- product_definition_schema

