(*
   $Id$
   ISO TC184/SC4/WG12 N4062 - ISO/TS 10303-1705 Functional usage view - EXPRESS ARM
   Supersedes ISO TC184/SC4/WG12 N3342
*)

SCHEMA Functional_usage_view_arm;

 USE FROM Analytical_model_arm;		-- ISO/TS 10303-1603
 
 USE FROM Shape_property_assignment_arm;    -- ISO/TS 10303-1032
 
REFERENCE FROM Product_identification_arm(types_of_product); -- ISO/TS 10303-1017 

REFERENCE FROM Characterizable_object_arm(bag_to_set);  -- ISO/TS 10303-1765

  
	TYPE fuuv_am_port_assignment_select = EXTENSIBLE GENERIC_ENTITY SELECT BASED_ON analytical_model_port_assignment_select WITH  
		(Functional_unit_usage_view_terminal_definition);
	END_TYPE;
  
  
  ENTITY Equivalent_functional_terminals_assignment;
      name                 : STRING;   
      equivalent_terminals : SET[2:?] OF Functional_unit_usage_view_terminal_definition;
  END_ENTITY;
 
  ENTITY Equivalent_functional_unit_definition_assignment;
      name                                   : STRING;   
      equivalent_functional_unit_definitions : SET[2:?] OF Functional_unit_definition;
  END_ENTITY;

  ENTITY Functional_product
  	SUBTYPE OF (Information_product);
    UNIQUE 
      UR1: SELF\Product.id;
    WHERE 
      WR1 : SIZEOF([ 'functional' ] * types_of_product(SELF))= 1 ;
  END_ENTITY;
  
  ENTITY Functional_terminal_group;
      name              : STRING; 
      group_description : STRING;
      group_type        : STRING;
    UNIQUE
      UR1 : name;
  END_ENTITY;

  ENTITY Functional_terminal_group_assignment;
      composed_group                 : Functional_terminal_group;
      functional_usage_view_terminal : Scalar_terminal_definition;
  END_ENTITY;
 
  ENTITY Functional_unit_definition
    ABSTRACT SUPERTYPE 
    SUBTYPE OF (Information_definition, Item_shape);
      SELF\Product_view_definition.defined_version : Functional_version;
    DERIVE
      SELF\Item_shape.described_element : shapeable_item := SELF;
  END_ENTITY;

	ENTITY Functional_unit_make_from_relationship
		SUBTYPE OF (View_definition_relationship);
		  SELF\View_definition_relationship.relating_view : Functional_unit_usage_view;		
		  SELF\View_definition_relationship.related_view 	: Functional_unit_usage_view;
		WHERE
          WR1 : acyclic_functional_unit_make_from_relationship (SELF, [related_view], 
            'FUNCTIONAL_USAGE_VIEW_ARM.FUNCTIONAL_UNIT_MAKE_FROM_RELATIONSHIP');
	END_ENTITY;

  ENTITY Functional_unit_usage_view
    SUBTYPE OF (Functional_unit_definition);
     DERIVE analytical_model_application_reference : SET[0:?] OF Analytical_model_application := get_ama(access_mechanism[1]);
     INVERSE
      access_mechanism : SET[0:?] OF functional_unit_usage_view_terminal_definition FOR associated_functional_unit_definition;
     WHERE
      WR1: SIZEOF(analytical_model_application_reference) <= 1;
      WR2: NOT(SIZEOF(analytical_model_application_reference) = 1) OR
        (SIZEOF(QUERY( am <* access_mechanism |
           NOT((SIZEOF(USEDIN(am,'ANALYTICAL_MODEL_ARM.ANALYTICAL_MODEL_PORT_ASSIGNMENT.ASSIGNED_ITEM')) = 0) OR
              (SIZEOF(QUERY( ampa <* USEDIN(am, 'ANALYTICAL_MODEL_ARM.ANALYTICAL_MODEL_PORT_ASSIGNMENT.ASSIGNED_ITEM') |
                 NOT(analytical_model_application_reference[1] :=: ampa.associated_analytical_model_application) 
                 )) = 0))
        )) = 0);
  END_ENTITY;

  ENTITY Functional_unit_usage_view_terminal_definition
    SUPERTYPE OF (Scalar_terminal_definition);
      associated_functional_unit_definition : Functional_unit_usage_view;
      signal_name                           : STRING; 
    UNIQUE
      UR1 : signal_name,
 associated_functional_unit_definition;
  END_ENTITY;

  ENTITY Functional_unit_usage_view_terminal_definition_make_from_relationship;
      associated_make_from : Functional_unit_make_from_relationship;
      reusable_feature     : Functional_unit_usage_view_terminal_definition;
      resultant_feature    : Functional_unit_usage_view_terminal_definition;
    UNIQUE
      UR1 : reusable_feature,
 resultant_feature;
    WHERE
      WR1 : reusable_feature :<>: resultant_feature;
      WR2 : reusable_feature.associated_functional_unit_definition :<>: resultant_feature.associated_functional_unit_definition;
      WR3 : reusable_feature.associated_functional_unit_definition :=: 
      		associated_make_from\Functional_unit_make_from_relationship.relating_view;
      WR4 : resultant_feature.associated_functional_unit_definition :=: 
      		associated_make_from\Functional_unit_make_from_relationship.related_view;
      WR5 : acyclic_functional_unit_usage_view_terminal_definition_make_from_relationship
        (SELF, [resultant_feature], 
        'FUNCTIONAL_USAGE_VIEW_ARM.FUNCTIONAL_UNIT_USAGE_VIEW_TERMINAL_DEFINITION_MAKE_FROM_RELATIONSHIP');
  END_ENTITY;

  ENTITY Functional_version
  	SUBTYPE OF (Information_version);
	  SELF\Product_version.of_product : Functional_product;
  END_ENTITY;

  ENTITY Scalar_terminal_definition
    SUBTYPE OF (Functional_unit_usage_view_terminal_definition);
  END_ENTITY;

  ENTITY Scalar_terminal_definition_link;
      precedent_terminal_definition  : Scalar_terminal_definition;
      subsequent_terminal_definition : Scalar_terminal_definition;
    UNIQUE
      UR1 : precedent_terminal_definition,
 subsequent_terminal_definition;
    WHERE
      WR1 : precedent_terminal_definition :<>: subsequent_terminal_definition;
      WR2 : acyclic_scalar_terminal_definition_link (SELF,
        [subsequent_terminal_definition],
        'FUNCTIONAL_USAGE_VIEW_ARM.SCALAR_TERMINAL_DEFINITION_LINK');
  END_ENTITY;

  FUNCTION acyclic_functional_unit_make_from_relationship
    (relation : Functional_unit_make_from_relationship; relatives : SET[1:?] OF 
    Functional_unit_usage_view; specific_relation : STRING) : BOOLEAN; 
  LOCAL
     x : SET OF Functional_unit_make_from_relationship;
  END_LOCAL;

    IF relation.relating_view IN relatives THEN
      RETURN (FALSE);
    END_IF;
    x := QUERY(pd <* bag_to_set(USEDIN(relation.relating_view,
      'FUNCTIONAL_USAGE_VIEW_ARM.' + 'FUNCTIONAL_UNIT_MAKE_FROM_RELATIONSHIP.' +
      'RELATED_VIEW')) | specific_relation IN TYPEOF(pd));
    REPEAT i := 1 TO HIINDEX(x);
      IF NOT acyclic_functional_unit_make_from_relationship(x[i], relatives +
        relation.relating_view, specific_relation) THEN
        RETURN (FALSE);
      END_IF;
    END_REPEAT;
    RETURN (TRUE);
  END_FUNCTION; 

  FUNCTION acyclic_functional_unit_usage_view_terminal_definition_make_from_relationship
     (relation : Functional_unit_usage_view_terminal_definition_make_from_relationship; 
     relatives : SET[1:?] OF Functional_unit_usage_view_terminal_definition; 
     specific_relation: STRING) : BOOLEAN; 
     LOCAL
       x : SET OF Functional_unit_usage_view_terminal_definition_make_from_relationship;
     END_LOCAL;
    
     IF relation.reusable_feature IN relatives THEN
       RETURN (FALSE);
     END_IF;
     x := QUERY(pd <* bag_to_set(USEDIN(relation.reusable_feature,
      'FUNCTIONAL_USAGE_VIEW_ARM.' +
      'FUNCTIONAL_UNIT_USAGE_VIEW_TERMINAL_DEFINITION_MAKE_FROM_RELATIONSHIP.' +
      'RESULTANT_FEATURE')) | specific_relation IN TYPEOF(pd));
     REPEAT i := 1 TO HIINDEX(x);
       IF NOT
         acyclic_functional_unit_usage_view_terminal_definition_make_from_relationship(x[i],
         relatives + relation.reusable_feature, specific_relation) THEN
           RETURN (FALSE);
       END_IF;
     END_REPEAT;
    RETURN (TRUE);
  END_FUNCTION; 

  FUNCTION acyclic_scalar_terminal_definition_link
    (relation : Scalar_terminal_definition_link; relatives : SET[1:?] OF
    Scalar_terminal_definition; specific_relation : STRING) : BOOLEAN; 
    LOCAL
      x : SET OF Scalar_terminal_definition_link;
    END_LOCAL;

    IF relation.precedent_terminal_definition IN relatives THEN
      RETURN (FALSE);
    END_IF;
    x := QUERY(pd <* bag_to_set(USEDIN(relation.precedent_terminal_definition,
      'FUNCTIONAL_USAGE_VIEW_ARM.' + 'SCALAR_TERMINAL_DEFINITION_LINK.' +
      'SUBSEQUENT_TERMINAL_DEFINITION')) | specific_relation IN TYPEOF(pd));
    REPEAT i := 1 TO HIINDEX(x);
      IF NOT acyclic_scalar_terminal_definition_link(x[i], relatives +
        relation.precedent_terminal_definition, specific_relation) THEN
        RETURN (FALSE);
      END_IF;
    END_REPEAT;
   RETURN (TRUE);
  END_FUNCTION;

  FUNCTION get_ama(
	input : analytical_model_port_assignment_select) : SET OF Analytical_model_application;
   LOCAL
	ama : SET[0:?] OF Analytical_model_application := [];  --this gives us access to the information base
	ampa : SET[0:?] OF Analytical_model_port_assignment :=[];
   END_LOCAL;
	ampa := bag_to_set(USEDIN (input, 'ANALYTICAL_MODEL_ARM.'+'ANALYTICAL_MODEL_PORT_ASSIGNMENT.ASSIGNED_ITEM'));
	-- iterate over ampa
	REPEAT i := 1 to SIZEOF(ampa) by 1;
		ama := ama + ampa[i].associated_analytical_model_application;
	END_REPEAT;

	RETURN(ama);
  END_FUNCTION;

END_SCHEMA;
