(*
   $Id$
   ISO TC184/SC4/WG12 N4714 - ISO/CD-TS 10303-1654 Characteristic - EXPRESS ARM
   Supersedes ISO TC184/SC4/WG12 N3909
*)

SCHEMA Characteristic_arm;
    USE FROM Basic_data_representation_arm;  -- ISO/CD-TS 10303-1773
	USE FROM Document_assignment_arm;	-- ISO/TS 10303-1122
	USE FROM Extended_measure_representation_arm;	-- ISO/TS 10303-1106
	USE FROM External_library_arm; -- ISO/CD-TS 10303-1778
	USE FROM Value_with_unit_extension_arm;	-- ISO/TS 10303-1753
  
  REFERENCE FROM Characterizable_object_arm(bag_to_set);     -- ISO/TS 10303-xxxx
  
  REFERENCE FROM Qualified_measure_arm(pre_defined_type_qualifiers); -- ISO/CD-TS 10303-1782  	
  
  TYPE characteristic = SELECT
    (String_representation_item,
    Numerical_item_with_unit,
    Value_list,
    Value_set);
  END_TYPE;

  TYPE c_documented_element_select = EXTENSIBLE SELECT BASED_ON documented_element_select WITH 
    (Property_value_representation);
  END_TYPE; 
  
  TYPE range_class = ENUMERATION OF
    (closed,
     lower_open,
     upper_open,
     open);
  END_TYPE;

  TYPE scalar_or_coordinated_characteristics = SELECT
    (Property_value_representation,
     characteristic);
  END_TYPE;

  ENTITY Characteristic_data_table
    SUBTYPE OF (Representation_item);
      property_value : LIST[1:?] OF Characteristic_data_table_row;
    WHERE
      WR1: SIZEOF(QUERY( pv <* property_value |
                  NOT (SIZEOF(pv.cell) = SIZEOF(property_value[1].cell))
                  )) = 0;
  END_ENTITY;

  ENTITY Characteristic_data_table_header
    SUBTYPE OF (Independent_property);
    DERIVE
      column : LIST [1:?] OF Independent_property := get_characterized_column_headers(SELF);
    WHERE
      WR1: EXISTS(column) AND (SIZEOF(column) > 1);
  END_ENTITY;

  ENTITY Characteristic_data_table_header_link
    SUBTYPE OF (Independent_property, Independent_property_relationship);
      SELF\Independent_property_relationship.relating RENAMED precedent : Independent_property;
      SELF\Independent_property_relationship.related RENAMED subsequent : Independent_property;
    DERIVE
      SELF\Independent_property_relationship.relation_type : STRING := 'sequence';
      table : Characteristic_data_table_header := get_table(SELF);            
    UNIQUE
      UR1: precedent, table;  
      UR2: subsequent, table;        
    WHERE
      WR1: EXISTS(table);
  END_ENTITY;

  ENTITY Characteristic_data_table_representation
    SUBTYPE OF (Property_value_representation);
      SELF\Representation.items : SET[1:1] OF Characteristic_data_table;
  END_ENTITY;

  ENTITY Characteristic_data_table_row
    SUBTYPE OF (Representation_item);
      cell : LIST [1:?] OF characteristic;
  END_ENTITY;

  ENTITY Externally_defined_type_qualifier
    SUBTYPE OF (Type_qualifier);
      external_source : External_source;
    WHERE
      WR1: NOT(name IN pre_defined_type_qualifiers);
  END_ENTITY;

  ENTITY Length_tolerance_characteristic
    SUBTYPE OF(Tolerance_characteristic);
    WHERE
      WR1 : ('CHARACTERISTIC_ARM.STATISTICAL_TOLERANCE_CHARACTERISTIC' IN TYPEOF(SELF)) OR
            ('CHARACTERISTIC_ARM.SYMMETRICAL_TOLERANCE_CHARACTERISTIC' IN TYPEOF(SELF)) OR
            ('CHARACTERISTIC_ARM.PLUS_MINUS_TOLERANCE_CHARACTERISTIC' IN TYPEOF(SELF)) OR
        (SIZEOF(QUERY(it <* SELF\Representation.items |
          NOT('VALUE_WITH_UNIT_EXTENSION_ARM.LENGTH_DATA_ELEMENT' IN TYPEOF(it))
         )) = 0);
      WR2 : NOT('CHARACTERISTIC_ARM.SYMMETRICAL_TOLERANCE_CHARACTERISTIC' IN TYPEOF(SELF)) OR
        (SIZEOF(QUERY(it <* SELF\Representation.items |
        ('VALUE_WITH_UNIT_EXTENSION_ARM.LENGTH_DATA_ELEMENT' IN TYPEOF(it))
           )) = 1);
      WR3 : NOT('CHARACTERISTIC_ARM.STATISTICAL_TOLERANCE_CHARACTERISTIC' IN TYPEOF(SELF)) OR
        (SIZEOF(QUERY(it <* SELF\Representation.items |
        ('VALUE_WITH_UNIT_EXTENSION_ARM.LENGTH_DATA_ELEMENT' IN TYPEOF(it))
           )) = 1);
      WR4 : NOT EXISTS(SELF\Representation.description);
      WR5 : NOT('CHARACTERISTIC_ARM.PLUS_MINUS_TOLERANCE_CHARACTERISTIC' IN TYPEOF(SELF)) OR
        (SIZEOF(QUERY(it <* SELF\Representation.items |
          NOT(('EXTENDED_MEASURE_REPRESENTATION_ARM.VALUE_WITH_TOLERANCES' IN TYPEOF(it)) AND
             ('VALUE_WITH_UNIT_EXTENSION_ARM.LENGTH_DATA_ELEMENT' IN TYPEOF(it\Value_with_tolerances.item_value)))
         )) = 0);
  END_ENTITY;

  ENTITY Maximum_tolerance_characteristic
    SUBTYPE OF (Tolerance_characteristic);
      SELF\Representation.items : SET [1:1] OF Value_limit;
    WHERE
      WR1: SELF\Representation.items[1]\Value_limit.qualifiers[1]\Type_qualifier.name = 'maximum';      
  END_ENTITY;

  ENTITY Minimum_tolerance_characteristic
    SUBTYPE OF (Tolerance_characteristic);
      SELF\Representation.items : SET [1:1] OF Value_limit;
    WHERE
      WR1: SELF\Representation.items[1]\Value_limit.qualifiers[1]\Type_qualifier.name = 'minimum';      
  END_ENTITY;

  ENTITY Nominal_tolerance_characteristic
    SUBTYPE OF (Tolerance_characteristic);
      SELF\Representation.items : SET[1:1] OF Qualified_numerical_item_with_unit;
    WHERE
      WR1: SELF\Representation.items[1]\Qualified_representation_item.qualifiers[1]\Type_qualifier.name = 'nominal';
  END_ENTITY;

  ENTITY Plus_minus_tolerance_characteristic
    SUBTYPE OF (Tolerance_characteristic);
      SELF\Representation.items : SET [1:1] OF Value_with_tolerances;
  END_ENTITY;

  ENTITY Range_characteristic
    SUBTYPE OF (Property_value_representation);
      SELF\Representation.items : SET[2:2] OF Numerical_item_with_unit;
      range_type				: range_class;
    WHERE
      WR1 : TYPEOF(SELF\Representation.items[1]) =
          TYPEOF(SELF\Representation.items[2]);
      WR2 : TYPEOF(SELF\Representation.items[1]\Value_with_unit.unit) =
          TYPEOF(SELF\Representation.items[2]\Value_with_unit.unit);
      WR3 : valid_range(SELF\Representation.items[1],
                      SELF\Representation.items[2]);          
  END_ENTITY;

  ENTITY Statistical_tolerance_characteristic
    SUBTYPE OF (Tolerance_characteristic);
      SELF\Representation.items : SET [2:?] OF Numerical_item_with_unit;
  END_ENTITY;

  ENTITY Symmetrical_tolerance_characteristic
    SUBTYPE OF (Tolerance_characteristic);
      SELF\Representation.items : SET[2:2] OF Numerical_item_with_unit;
    WHERE
      WR1: SIZEOF(QUERY( ri <* 
         SELF\representation.items |
        'VALUE_WITH_UNIT_EXTENSION_ARM.RATIO_DATA_ELEMENT' IN TYPEOF(ri))) = 1;
  END_ENTITY;

  ENTITY Text_representation_item
  	SUBTYPE OF (String_representation_item);
  END_ENTITY;

  ENTITY Tolerance_characteristic
    ABSTRACT SUPERTYPE OF ((ONEOF (Minimum_tolerance_characteristic,
      Statistical_tolerance_characteristic,
      Symmetrical_tolerance_characteristic,
      Maximum_tolerance_characteristic,
      Plus_minus_tolerance_characteristic,
      Nominal_tolerance_characteristic)) ANDOR Length_tolerance_characteristic)
    SUBTYPE OF (Property_value_representation);
    WHERE
      WR1: SELF\Representation.context_of_items\Representation_context.id = 'tolerance values';
      WR2 : NOT EXISTS(SELF\Representation.name);
  END_ENTITY;

  SUBTYPE_CONSTRAINT exclusive_property_value_representation_characteristic FOR Property_value_representation;
    ONEOF (Range_characteristic, Tolerance_characteristic);
  END_SUBTYPE_CONSTRAINT;

  SUBTYPE_CONSTRAINT type_qualifier_subtypes FOR Type_qualifier;
    ONEOF(Externally_defined_type_qualifier, Pre_defined_type_qualifier);
  END_SUBTYPE_CONSTRAINT;
  
  FUNCTION get_value (
         input1 : string;
         np : SET OF Representation_item) : Numerical_item_with_unit;
    REPEAT i := 1 to SIZEOF(np) by 1;
      IF input1 = np[i]\Representation_item.name THEN
        RETURN(np[i]);
      END_IF;
    END_REPEAT;
    RETURN(?);
  END_FUNCTION;

  FUNCTION valid_range(input1 : Numerical_item_with_unit;
                       input2 : Numerical_item_with_unit) : BOOLEAN;
    RETURN(TRUE);
  END_FUNCTION; 

  FUNCTION get_characterized_column_headers(input : Characteristic_data_table_header): LIST [1:?] OF Independent_property;
    LOCAL
      middle : SET [1:?] OF Independent_property;
      result : LIST [1:?] OF Independent_property;
      links  : SET [1:?] OF Characteristic_data_table_header_link;
      temp   : Independent_property;
      precedent : SET [0:?] OF Characteristic_data_table_header_link;
      subsequent : SET [0:?] OF Characteristic_data_table_header_link;
    END_LOCAL;
    -- Collect all headers
    links := bag_to_set(USEDIN(input, 'CHARACTERISTIC_ARM.' + 'CHARACTERISTIC_DATA_TABLE_HEADER_LINK.TABLE'));
    -- Collect all Independent_properties
    REPEAT i := 1 to HIINDEX(links);
      middle := middle + links[i]\Characteristic_data_table_header_link.precedent;
      middle := middle + links[i]\Characteristic_data_table_header_link.subsequent;
    END_REPEAT;
    result[1] := ?;
    -- Now need to construct the resulting list
    REPEAT i := 1 to HIINDEX(middle);
      precedent := bag_to_set(QUERY (l <* (USEDIN(middle[i], 'CHARACTERISTIC_ARM.' + 
        'CHARACTERISTIC_DATA_TABLE_HEADER_LINK.PRECEDENT')) | l.table = input));
      -- illegal chain
      IF (SIZEOF(precedent) > 1) THEN
        RETURN(?);
      END_IF;
      -- check if this is not last member
      IF (SIZEOF(precedent) = 1) THEN
        subsequent := bag_to_set(QUERY (l <* (USEDIN(middle[i], 'CHARACTERISTIC_ARM.' + 
          'CHARACTERISTIC_DATA_TABLE_HEADER_LINK.SUBSEQUENT')) | l.table = input));
        -- we found first member
        IF (SIZEOF(subsequent) = 0) THEN
          result[1] := middle[i];
          ESCAPE;
        END_IF;
      END_IF;
    END_REPEAT;
    -- if there is no first member found yet - chain is broken
    IF (result[1] = ?) THEN
      RETURN (?);
    END_IF;
    temp := result[1];
    REPEAT i := 2 to HIINDEX(middle);
      result[i] := precedent[1]\Characteristic_data_table_header_link.subsequent;
      precedent := bag_to_set(QUERY (l <* (USEDIN(result[i], 'CHARACTERISTIC_ARM.' + 
        'CHARACTERISTIC_DATA_TABLE_HEADER_LINK.PRECEDENT')) | l.table = input));
      IF (HIINDEX(middle) = i) THEN
        ESCAPE;
      END_IF;
      -- illegal chain
      IF (SIZEOF(precedent) <> 1) THEN
        RETURN(?);
      END_IF;
    END_REPEAT; 
    RETURN (result);
  END_FUNCTION;

  FUNCTION get_table(input : Characteristic_data_table_header_link): Characteristic_data_table_header;
    LOCAL
      middle : BAG [0:?] OF Independent_property_relationship;
    END_LOCAL;
      middle := QUERY (ipr <* (USEDIN(input, 'INDEPENDENT_PROPERTY_ARM.' + 
        'INDEPENDENT_PROPERTY_RELATIONSHIP.RELATED')) | ipr.relation_type = 'decomposition');      
      REPEAT i := 1 to HIINDEX(middle);       
        IF('CHARACTERISTIC_ARM.CHARACTERISTIC_DATA_TABLE_HEADER' IN TYPEOF(middle[i].relating))THEN
          RETURN (middle[i].relating);
        END_IF;
      END_REPEAT;
      RETURN (?);
  END_FUNCTION;

  SUBTYPE_CONSTRAINT c_representation_item_subtypes FOR Representation_item; 
	(ONEOF (Characteristic_data_table,
	  Characteristic_data_table_row));
  END_SUBTYPE_CONSTRAINT;

END_SCHEMA;
