(*
 * $Id$
 *
 * JSDAI(TM), a way to implement STEP, ISO 10303
 * Copyright (C) 1997-2008, LKSoftWare GmbH, Germany
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License
 * version 3 as published by the Free Software Foundation (AGPL v3).
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * JSDAI is a registered trademark of LKSoftWare GmbH, Germany
 * This software is also available under commercial licenses.
 * See also http://www.jsdai.net/
 *)

(*
   Derived from ISO TC184/SC4/WG12 N3588 - ISO/CD-TS 10303-1739 Production rule - EXPRESS ARM
   by LKSoftWare GmbH for implementation purpose within IDA-STEP(TM)
*)

SCHEMA Production_rule_xim;

REFERENCE FROM Product_identification_xim(types_of_product); -- ISO/TS 10303-1017 

	USE FROM Specification_document_xim;    --  ISO/CD-TS 10303-1747
	USE FROM Software_xim;	-- ISO/TS 10303-1746

	USE FROM Date_time_assignment_xim; -- ISO/TS 10303-1014
	USE FROM Activity_xim; -- ISO/TS 10303-1047

USE FROM Identification_assignment_xim;
USE FROM Product_identification_xim;

USE FROM Production_rule_mim;

 REFERENCE FROM Specification_document_xim(get_document_definition);	-- ISO/TS 10303-1747

TYPE pr_documented_element_select = EXTENSIBLE GENERIC_ENTITY SELECT BASED_ON documented_element_select WITH 
   (Rule_set_armx);
END_TYPE; 
(* Available from MIM
TYPE pr_identification_item = SELECT BASED_ON identification_item WITH 
   (Rule_set_armx);
END_TYPE; *)

TYPE clause_select = SELECT (Simple_clause_armx, Complex_clause_armx);
END_TYPE;

TYPE constants = EXTENSIBLE SELECT (count_measure, descriptive_measure, Logical_representation_item);
END_TYPE;

TYPE function_symbol = SELECT (descriptive_measure, built_in_functions);
END_TYPE;

TYPE built_in_functions = EXTENSIBLE ENUMERATION OF (ATTR_VAL);
END_TYPE;

TYPE expression_syntax = EXTENSIBLE ENUMERATION OF (EXPRESS);
END_TYPE;

TYPE predicate_symbol = STRING;
END_TYPE;

TYPE scope_select = SELECT (Rule_definition_armx, Rule_set_armx, Rule_set_group_armx);
END_TYPE;

TYPE term_select = SELECT (Symbol_armx, constants, Func_armx, Scalar_variable_armx, Row_value_armx, Row_variable); 
END_TYPE;

ENTITY Abstract_variable_armx
  ABSTRACT SUPERTYPE OF (ONEOF (Scalar_variable_armx, Row_variable_armx))
  SUBTYPE OF (abstract_variable);
  -- Accessable from property_definition.name
  -- name : STRING;
  SELF\property_definition.name RENAMED scope : scope_select;
 UNIQUE 
  UR1 : name, scope;
END_ENTITY;

ENTITY Atomic_formula_armx
  ABSTRACT SUPERTYPE OF (ONEOF (Rule_condition_armx, Ground_fact_armx))
  SUBTYPE OF (atomic_formula);
  SELF\representation_item.name RENAMED predicate_symbol : predicate_symbol;  
  terms : LIST OF term_select;
  DERIVE
   -- Overlaps with attribute terms
    SELF\compound_representation_item.item_element : compound_item_definition :=?;
END_ENTITY;

ENTITY Attribute_assertion_armx
  SUBTYPE OF (Fact_type_armx, attribute_assertion);
   entity_type : STRING;
   attribute : STRING;
  DERIVE
   -- Overlaps with both attributes
    SELF\representation.items : SET[1:?] OF representation_item :=?;
END_ENTITY; 

ENTITY Back_chaining_rule_armx
  SUBTYPE OF (Rule_definition_armx, back_chaining_rule);
  head : Rule_condition_armx;
  body : LIST OF Rule_condition_armx;
 WHERE
  WR1: SELF.head.positive = TRUE;
  WR2:  local_vars_of(SELF.head) <= local_vars_of(SELF.body);
END_ENTITY;

ENTITY Complex_clause_armx
  ABSTRACT SUPERTYPE OF (ONEOF (Complex_conjunctive_clause_armx, Complex_disjunctive_clause_armx))
  SUBTYPE OF (complex_clause);
  clauses : LIST [2:?] OF clause_select;
  DERIVE
   -- Overlaps with attribute clauses
    SELF\compound_representation_item.item_element : compound_item_definition :=?;
END_ENTITY;

ENTITY Complex_conjunctive_clause_armx
  SUBTYPE OF (Complex_clause_armx, complex_conjunctive_clause); 
END_ENTITY;

ENTITY Complex_disjunctive_clause_armx
  SUBTYPE OF (Complex_clause_armx, complex_disjunctive_clause); 
END_ENTITY;

ENTITY Entity_assertion_armx
  SUBTYPE OF (Fact_type_armx, entity_assertion);
END_ENTITY;

ENTITY Enum_reference_prefix_armx
  SUBTYPE OF (enum_reference_prefix);
  SELF\descriptive_representation_item.description RENAMED prefix : STRING;
END_ENTITY;

ENTITY Extent_armx
  SUBTYPE OF (extent);
  source : STRING;
  variable_id : OPTIONAL STRING;
  query_expression : STRING;
  syntax : OPTIONAL expression_syntax;
END_ENTITY;

ENTITY Fact_type_armx
  ABSTRACT SUPERTYPE OF (ONEOF (Entity_assertion_armx, Attribute_assertion_armx))
  SUBTYPE OF (fact_type);
   SELF\property_definition.definition RENAMED source     : Extent_armx;
   SELF\property_definition.name RENAMED predicate_symbol : STRING;
END_ENTITY;

ENTITY Forward_chaining_rule_armx
  SUBTYPE OF (Rule_definition_armx, forward_chaining_rule);
  premise : clause_Select; 
  conclusion : Literal_conjunction_armx;
  WHERE
  WR1:  local_vars_of(SELF.conclusion) <= local_vars_of(SELF.premise);
END_ENTITY;

ENTITY Func_armx
  SUBTYPE OF (func);
  SELF\representation_item.name RENAMED func_sym : function_symbol;
  terms : LIST OF term_select;
  DERIVE
   -- Overlaps with attribute terms
    SELF\compound_representation_item.item_element : compound_item_definition :=?;
END_ENTITY;

ENTITY Global_assignment_armx
  SUBTYPE OF (global_assignment);
  SELF\representation_item_relationship.relating_representation_item RENAMED variable : Abstract_variable_armx;
  SELF\representation_item_relationship.related_representation_item RENAMED val       : term_select;
 WHERE
  WR1: NOT(contains_variable(SELF.val));
END_ENTITY;

ENTITY Ground_fact_armx
 SUBTYPE OF (Atomic_formula_armx, ground_fact);
 WHERE
  WR1: SIZEOF(QUERY(r <* SELF\Atomic_formula_armx.terms | contains_variable(r))) = 0;
END_ENTITY;

ENTITY Literal_conjunction_armx
  SUBTYPE OF (Simple_clause_armx, literal_conjunction);
END_ENTITY;

ENTITY Literal_disjunction_armx
  SUBTYPE OF (Simple_clause_armx, literal_disjunction);
END_ENTITY;

ENTITY Row_value_armx
  SUBTYPE OF (row_value);
  values : LIST OF term_select;
  DERIVE
   -- Overlaps with attribute values
    SELF\compound_representation_item.item_element : compound_item_definition :=?;
 WHERE
  WR1: SIZEOF(QUERY(v <* SELF.values | contains_variable(v))) = 0;
  WR2: SIZEOF(QUERY(v <* SELF.values | 'PRODUCTION_RULE_XIM.ROW_VALUE_ARMX' IN TYPEOF(v))) = 0;
END_ENTITY;

ENTITY Row_variable_armx
 SUBTYPE OF (Abstract_variable_armx, row_variable);
END_ENTITY;

 ENTITY Rule_action_armx
    ABSTRACT SUPERTYPE OF (ONEOF (Rule_submission,
 Rule_adoption,
 Rule_rejection,
 Rule_supersedence_armx,
 Rule_creation,
 Rule_expiration,
 Rule_change_request,
 Rule_request,
 Rule_modification))
 	(* CONNOTATIONAL *) SUBTYPE OF (rule_action);
      subject_rule              : Rule_version;
	DERIVE
  		subject_action_assignment: SET[0:?] OF organization_or_person_in_organization_assignment_select :=
         QUERY(temp <* USEDIN(SELF,'PERSON_ORGANIZATION_ASSIGNMENT_xim.'+
         'organization_or_person_in_organization_assignment_select.ITEMS') |
                         (temp.role = 'subject action assignment') );
        SELF\action.description : text := ?;
        SELF\action.name : label := ?;
        SELF\action.chosen_method : action_method := ?;
    UNIQUE
      UR1 : subject_rule,
 subject_action_assignment;
	WHERE
   		WR1 : EXISTS (subject_action_assignment) AND sizeof(subject_action_assignment) = 1;
  END_ENTITY;

  ENTITY Rule_adoption
    (* CONNOTATIONAL *) SUBTYPE OF (Rule_action_armx);
  END_ENTITY;

  ENTITY Rule_change_request
    (* CONNOTATIONAL *) SUBTYPE OF (Rule_action_armx);
      SELF\action.description RENAMED change_reason : STRING;
  END_ENTITY;

  ENTITY Rule_creation
    (* CONNOTATIONAL *) SUBTYPE OF (Rule_action_armx);
  END_ENTITY;

ENTITY Rule_condition_armx
 SUBTYPE OF (Atomic_formula_armx, rule_condition);
  positive : BOOLEAN;
  DERIVE
    -- Overlaps with attribute "positive"
    SELF\representation_item.name : label :=?;
END_ENTITY;

ENTITY Rule_definition_armx
  ABSTRACT SUPERTYPE OF (ONEOF (Forward_chaining_rule_armx, Back_chaining_rule_armx))
  SUBTYPE OF (Rule_software_definition_armx, rule_definition);
END_ENTITY; 

  ENTITY Rule_expiration
    (* CONNOTATIONAL *) SUBTYPE OF (Rule_action_armx);
      expiration_rationale : STRING;
  END_ENTITY;

  ENTITY Rule_justification
  	(* CONNOTATIONAL *) SUBTYPE OF (Rule_action_armx);
      justified_action        : Rule_action_armx;
      SELF\action.description RENAMED justification_rationale : STRING;
  	WHERE
	  	WR1: SELF <> justified_action;       
  END_ENTITY;

  ENTITY Rule_modification
    (* CONNOTATIONAL *) SUBTYPE OF (Rule_action_armx);
      modification_rationale : Rule_change_request;
  END_ENTITY;

  ENTITY Rule_priority
  (* CONNOTATIONAL *) SUBTYPE OF (representation);
      priority         : INTEGER;
      prioritized_rule : Rule_definition_armx;
    DERIVE
      SELF\representation.items : SET [1:?] OF representation_item := ?;
      SELF\representation.context_of_items : representation_context := ?;
      SELF\representation.name : label := ?;
    WHERE
      WR1 : priority >= 0;
  END_ENTITY;
  
  ENTITY Rule_product
  	(* CONNOTATIONAL *) SUBTYPE OF (Software);
  	WHERE 
  		WR1 : 'rule'  IN types_of_product(SELF);
  END_ENTITY;

  ENTITY Rule_rejection
    (* CONNOTATIONAL *) SUBTYPE OF (Rule_action_armx);
      SELF\action.description RENAMED rejection_reason : STRING;
  END_ENTITY;

  ENTITY Rule_request
    (* CONNOTATIONAL *) SUBTYPE OF (Rule_action_armx);
  END_ENTITY;

ENTITY Rule_set_armx
   SUBTYPE OF (Rule_software_definition_armx, rule_set);
   conflict_resolution_strategy : OPTIONAL STRING;
   rule_member : SET[1:?] OF Rule_priority;
 DERIVE  
   engine: SET[1:1] OF Document_definition :=
		get_document_definition(SELF, 'engine', 
		'SPECIFICATION_DOCUMENT_XIM.LANGUAGE_REFERENCE_MANUAL');   
 INVERSE
   purpose : applied_identification_assignment FOR items;
 WHERE
   WR1: purpose.role = 'purpose' ;
END_ENTITY;

  ENTITY Rule_set_group_armx
    (* CONNOTATIONAL *) SUBTYPE OF (Rule_software_definition_armx, rule_set_group);
      elements : SET[2:?] OF Rule_set_armx;
  END_ENTITY;

  ENTITY Rule_software_definition_armx 
    SUPERTYPE OF (ONEOF (Rule_definition_armx,
 			Rule_set_group_armx, Rule_set_armx))
    (* CONNOTATIONAL *) SUBTYPE OF (Software_definition, rule_software_definition); 			
    SELF\Product_definition.formation : Rule_version;
  END_ENTITY;

  ENTITY Rule_submission
    (* CONNOTATIONAL *) SUBTYPE OF (Rule_action_armx);
      SELF\action.description RENAMED submission_rationale : STRING;
  END_ENTITY;

  ENTITY Rule_supersedence_armx
    (* CONNOTATIONAL *) SUBTYPE OF (Rule_action_armx, rule_supersedence);
      superseded_rule : Rule_version;
  END_ENTITY;

  ENTITY Rule_version
    (* CONNOTATIONAL *) SUBTYPE OF (Software_version);
			SELF\product_definition_formation.of_product : Rule_product;    
    INVERSE
      management_action		: SET[1:?] OF rule_action_armx FOR subject_rule;
      product_definition	: SET[1:?] OF rule_definition_armx FOR formation;
  END_ENTITY;

ENTITY Scalar_variable_armx
 SUBTYPE OF (Abstract_variable_armx, scalar_variable);
END_ENTITY;

ENTITY Simple_clause_armx
  ABSTRACT SUPERTYPE OF (ONEOF (Literal_conjunction_armx, Literal_disjunction_armx))
  SUBTYPE OF (simple_clause);
  formulas : LIST [1:?] OF Rule_condition_armx;
END_ENTITY;

ENTITY Symbol_armx
  SUBTYPE OF (symbol);
  -- available from supertype representation_item
  -- name : STRING;
END_ENTITY;

FUNCTION contains_variable (x : Term_select) : BOOLEAN;
  IF ('PRODUCTION_RULE_XIM.ABSTRACT_VARIABLE_ARMX' IN TYPEOF(x)) THEN RETURN (TRUE);
      ELSE IF (('PRODUCTION_RULE_XIM.FUNC_ARMX' IN TYPEOF(X)) AND
              (SIZEOF(QUERY(y <* x.terms | contains_variable(y))) > 0)) 
              THEN RETURN (TRUE);
              ELSE RETURN (FALSE);
           END_IF;
  END_IF;
END_FUNCTION;

FUNCTION local_vars_aux (thing : GENERIC; accum : SET [0:?] OF Scalar_variable_armx) 
                                                : SET [0:?] OF Scalar_variable_armx;
  LOCAL i,j,k : INTEGER; END_LOCAL;
  IF (('PRODUCTION_RULE_XIM.ABSTRACT_VARIABLE_ARMX' IN TYPEOF(thing)) AND 
      ('PRODUCTION_RULE_XIM.RULE_DEFINITION' IN (TYPEOF(thing.scope))))
   THEN accum := accum + thing;
   ELSE IF ('PRODUCTION_RULE_XIM.RULE_CONDITION_ARMX' IN TYPEOF(thing))
        THEN REPEAT i := 1 TO HIINDEX(thing\Atomic_formula_armx.terms);
                accum := local_vars_aux(thing\Atomic_formula_armx.terms[i],accum);
             END_REPEAT;
        ELSE IF ('PRODUCTION_RULE_XIM.SIMPLE_CLAUSE_ARMX' IN TYPEOF(thing))
             THEN REPEAT j := 1 TO HIINDEX(thing.formulas);
                        accum := local_vars_aux(thing.formulas[j],accum);
                  END_REPEAT;
             ELSE IF ('PRODUCTION_RULE_XIM.COMPLEX_CLAUSE_ARMX' IN TYPEOF(thing))
                  THEN REPEAT k := 1 TO HIINDEX(thing.clauses);
                        accum := local_vars_aux(thing.clauses[k],accum);
                       END_REPEAT;
                  END_IF;
             END_IF;
        END_IF;
  END_IF;
  RETURN(accum);
END_FUNCTION;

FUNCTION local_vars_of (thing : GENERIC) : SET [0:?] OF Scalar_variable_armx;
  LOCAL
    accum : SET [0:?] OF Scalar_variable_armx := [];
  END_LOCAL;
  RETURN (local_vars_aux(thing, accum));
END_FUNCTION;

RULE max_one_entity_prefix FOR (Enum_reference_prefix_armx);
 WHERE
   SIZEOF(QUERY(x <* Enum_reference_prefix_armx | TRUE)) <= 1;
END_RULE;

RULE rule_software_definition_constraint FOR (Product_view_definition);
WHERE
   WR1: SIZEOF (QUERY ( pvd <* Product_view_definition | ( NOT('PRODUCTION_RULE_XIM.' + 'RULE_SOFTWARE_DEFINITION_ARMX' 
                       IN TYPEOF(pvd))) 
                       AND ('PRODUCTION_RULE_XIM.' + 'RULE_VERSION' IN TYPEOF (pvd . defined_version)))) = 0 ;
END_RULE; 

RULE rule_version_constraint FOR (product_definition_formation);
WHERE
   WR1: SIZEOF (QUERY(pv <* product_definition_formation | (NOT('PRODUCTION_RULE_XIM.' + 'RULE_VERSION' IN TYPEOF(pv))) 
                      AND ( 'PRODUCTION_RULE_XIM.' + 'RULE_PRODUCT' IN TYPEOF(pv.of_product)))) = 0 ;
END_RULE;

END_SCHEMA; 