job:  #9554  full checking, one small bug remaining

.// still a bug in aoth reference checking
.//
.// For each class in the model do the following:
.//   Search for duplicate identifiers in the instance extent.
.//   Match referential attribute values with identifier attribute values.
.//   Find unconditional formalizer from a participant in a simple association.
.//   Find unconditional participant from a formalizer in a simple association.
.//   For an associator in a linked association ensure both ends have an instance.
.//   From the one end of an associative, find the unconditional associator.
.//   From the other end of an associative, find the unconditional associator.
.//   For a subtype, ensure a supertype is present.
.//   For a supertype, ensure exactly one subtype is present.
.//
.// Iterate over the given class.
.function t_class_instance_iteration .// string
  .param string key_letters
  .param string inner_body
select many $l{key_letters}s from instances of ${key_letters};
for each $l{key_letters} in $l{key_letters}s
${inner_body}
end for;
.end function
.//
.// Ensure no duplicate instance identifiers.
.function t_duplication .// string
  .param string key_letters
  .param string where_clause
  .param integer Numb
  select many duplicate_$l{key_letters}s from instances of ${key_letters} where ( ${where_clause} );
  if ( cardinality duplicate_$l{key_letters}s != 1 )
    LOG::LogInfo( message: "uniqueness violation in ${key_letters} for identifier $t{Numb}" );
    break;
  end if;
.end function
.//
.// Select across link to required instance.
.function t_participation .// string
  .param string left_side
  .param string right_side
  .param integer Numb
  .param string multiplicity
  .param string phrase
  .param string attribute_comparison
  .if ( "" != phrase )
  select ${multiplicity} $l{right_side} related by $l{left_side}->${right_side}[R$t{Numb}.'${phrase}'];
  .else
  select ${multiplicity} $l{right_side} related by $l{left_side}->${right_side}[R$t{Numb}];
  .end if
  if ( empty $l{right_side} )
  .if ( "" != phrase )
    LOG::LogInfo( message: "instance not found ${left_side}->${right_side}[R$t{Numb}.'${phrase}']" );
  .else
    LOG::LogInfo( message: "instance not found ${left_side}->${right_side}[R$t{Numb}]" );
  .end if
    break;
  .if ( "" != attribute_comparison )
  else
    if ( not ( ${attribute_comparison} ) )
      LOG::LogInfo( message: "referentials do not match identifiers between ${left_side} and ${right_side}" );
      break;
    end if;
  .end if
  end if;
.end function
.//
.// Loop through looking for a subtype.
.function t_supertype_loop .// string
  .param string super
  .param integer Numb
  .param string Loop_Body
  subtype_count = 0;
${Loop_Body}
  if ( subtype_count < 1 )
    LOG::LogInfo( message: "subtype not found from ${super} across R$t{Numb}" );
    break;
  elif ( subtype_count > 1 )
    LOG::LogInfo( message: "more than one subtype found from ${super} across R$t{Numb}" );
    break;
  else
    // nop
  end if;
.end function
.//
.// Be sure supertype is present.
.function t_sub_to_super .// string
  .param string sub
  .param string super
  .param integer Numb
  select one $l{super} related by $l{sub}->${super}[R$t{Numb}];
  if ( empty $l{super} )
    LOG::LogInfo( message: "supertype not found across ${sub}->${super}[R$t{Numb}]" );
    break;
  end if;
.end function
.//
.// Look for a particular subtype.
.function t_super_to_sub .// string
  .param string super
  .param string sub
  .param integer Numb
  select one $l{sub} related by $l{super}->${sub}[R$t{Numb}];
  if ( not_empty $l{sub} )
    subtype_count = subtype_count + 1;
  end if;
.end function
.//
.function instance_uniqueness .// string
  .param inst_ref o_id
  .select one o_obj related by o_id->O_OBJ[R104]
  .assign where_clause = ""
  .assign prefix = ""
  .select many o_oidas related by o_id->O_OIDA[R105]
  .for each o_oida in o_oidas
    .assign clause = "selected." + o_oida.localAttributeName + " == " + $l{o_obj.Key_Lett} + "." + o_oida.localAttributeName
    .assign where_clause = where_clause + prefix + clause
    .assign prefix = " and "
  .end for
  .invoke r = t_duplication( o_obj.Key_Lett, where_clause, o_id.Oid_ID + 1 )
${r.body}
.end function
.//
.function compare_referentials_to_identifiers
  .param string rgo_name
  .param string rto_name
  .param inst_ref r_rgo
  .param inst_ref r_rto
  .//
  .assign where_clause = ""
  .assign conjunction = ""
  .select many o_oidas related by r_rto->O_ID[R109]->O_OIDA[R105]
  .for each o_oida in o_oidas
    .// Get the identifying attribute corresponding to this <o_oida> instance.
    .select any o_attr related by o_oida->O_ATTR[R105] where (selected.Attr_ID == o_oida.Attr_ID)
    .select any o_rtida related by r_rto->O_RTIDA[R110] where ((selected.Attr_ID == o_oida.Attr_ID) and ((selected.Obj_ID == o_oida.Obj_ID) and (selected.Oid_ID == o_oida.Oid_ID)))
    .// There can be more than one valid O_REF here, so get _any_ one.
    .// Note:  If MANY <o_rtida>, we need to rip through the (possible) combined referentials,
    .// unlinking any non-constrained elements.
    .select any o_ref related by o_rtida->O_REF[R111] where ( (selected.Obj_ID == r_rgo.Obj_ID) and (selected.OIR_ID == r_rgo.OIR_ID) )
    .// Get the referential attribute corresponding to the current <o_attr>.
    .select one ref_o_attr related by o_ref->O_RATTR[R108]->O_ATTR[R106]
    .select one o_dbattr related by o_attr->O_BATTR[R106]->O_DBATTR[R107]
    .// template here
    .assign clause = rto_name + "." + o_oida.localAttributeName + " == " + rgo_name + "." + ref_o_attr.Name
    .assign where_clause = where_clause + conjunction + clause
    .assign conjunction = " and "
  .end for
${where_clause}\
.end function
.//
.function participant_participation .// string
  .param inst_ref o_obj
  .select many r_parts related by o_obj->R_OIR[R201]->R_RTO[R203]->R_PART[R204]
  .for each r_part in r_parts
    .select one r_simp related by r_part->R_SIMP[R207]
    .select one r_rel related by r_simp->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select one r_form related by r_simp->R_FORM[R208]
      .if ( not_empty r_form )
        .if ( not r_form.Cond )
          .select one r_rgo related by r_form->R_RGO[R205]
          .select one target_o_obj related by r_rgo->R_OIR[R203]->O_OBJ[R201]
          .assign card = "one"
          .if ( r_form.Mult )
            .assign card = "any"
          .end if
          .assign phrase = ""
          .if ( r_part.Obj_ID == r_form.Obj_ID )
            .assign phrase = r_form.Txt_Phrs
          .end if
          .select one r_rto related by r_part->R_RTO[R204]
          .invoke r = compare_referentials_to_identifiers( $l{o_obj.Key_Lett}, $l{target_o_obj.Key_Lett}, r_rgo, r_rto )
          .assign comparison = r.body
          .invoke r = t_participation( o_obj.Key_Lett, target_o_obj.Key_Lett, r_rel.Numb, card, phrase, comparison )
  // participant participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${target_o_obj.Name}(${target_o_obj.Key_Lett})
${r.body}
        .end if
      .else
  // unformalized association R$t{r_rel.Numb}
      .end if
    .end if
  .end for
.end function
.//
.function formalizer_participation .// string
  .param inst_ref o_obj
  .select many r_forms related by o_obj->R_OIR[R201]->R_RGO[R203]->R_FORM[R205]
  .for each r_form in r_forms
    .select one r_simp related by r_form->R_SIMP[R208]
    .select one r_rel related by r_simp->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select one r_part related by r_simp->R_PART[R207]
      .if ( not r_part.Cond )
        .select one r_rto related by r_part->R_RTO[R204]
        .select one target_o_obj related by r_rto->R_OIR[R203]->O_OBJ[R201]
        .assign card = "one"
        .if ( r_part.Mult )
          .assign card = "any"
        .end if
        .assign phrase = ""
        .if ( r_part.Obj_ID == r_form.Obj_ID )
          .assign phrase = r_part.Txt_Phrs
        .end if
        .select one r_rgo related by r_form->R_RGO[R205]
        .invoke r = compare_referentials_to_identifiers( $l{o_obj.Key_Lett}, $l{target_o_obj.Key_Lett}, r_rgo, r_rto )
        .assign comparison = r.body
        .invoke r = t_participation( o_obj.Key_Lett, target_o_obj.Key_Lett, r_rel.Numb, card, phrase, comparison )
  // formalizer participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${target_o_obj.Name}(${target_o_obj.Key_Lett})
${r.body}
      .end if
    .end if
  .end for
.end function
.//
.function associator_participation .// string
  .param inst_ref o_obj
  .select many r_assrs related by o_obj->R_OIR[R201]->R_RGO[R203]->R_ASSR[R205]
  .for each r_assr in r_assrs
    .select one r_assoc related by r_assr->R_ASSOC[R211]
    .select one r_rel related by r_assoc->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select one r_aone related by r_assoc->R_AONE[R209]
      .select one r_aoth related by r_assoc->R_AOTH[R210]
      .select one aone_r_rto related by r_aone->R_RTO[R204]
      .select one aone_o_obj related by aone_r_rto->R_OIR[R203]->O_OBJ[R201]
      .select one aoth_r_rto related by r_aoth->R_RTO[R204]
      .select one aoth_o_obj related by aoth_r_rto->R_OIR[R203]->O_OBJ[R201]
      .assign phrase = ""
      .if ( r_aone.Obj_ID == r_aoth.Obj_ID )
        .assign phrase = r_aone.Txt_Phrs
      .end if
      .select one r_rgo related by r_assr->R_RGO[R205]
      .invoke r = compare_referentials_to_identifiers( $l{o_obj.Key_Lett}, $l{aone_o_obj.Key_Lett}, r_rgo, aone_r_rto )
      .assign comparison = r.body
      .invoke r = t_participation( o_obj.Key_Lett, aone_o_obj.Key_Lett, r_rel.Numb, "one", phrase, comparison )
  // associator one participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${aone_o_obj.Name}(${aone_o_obj.Key_Lett})
${r.body}
      .assign phrase = ""
      .if ( r_aone.Obj_ID == r_aoth.Obj_ID )
        .assign phrase = r_aoth.Txt_Phrs
      .end if
      .invoke r = compare_referentials_to_identifiers( $l{o_obj.Key_Lett}, $l{aoth_o_obj.Key_Lett}, r_rgo, aoth_r_rto )
      .assign comparison = r.body
      .invoke r = t_participation( o_obj.Key_Lett, aoth_o_obj.Key_Lett, r_rel.Numb, "one", phrase, comparison )
  // associator other participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${aoth_o_obj.Name}(${aoth_o_obj.Key_Lett})
${r.body}
    .end if
  .end for
.end function
.//
.function aone_participation .// string
  .param inst_ref o_obj
  .select many r_aones related by o_obj->R_OIR[R201]->R_RTO[R203]->R_AONE[R204]
  .for each r_aone in r_aones
    .select one r_assoc related by r_aone->R_ASSOC[R209]
    .select one r_rel related by r_assoc->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select one r_aoth related by r_assoc->R_AOTH[R210]
      .if ( not r_aoth.Cond )
        .select one r_rgo related by r_assoc->R_ASSR[R211]->R_RGO[R205]
        .select one target_o_obj related by r_rgo->R_OIR[R203]->O_OBJ[R201]
        .assign phrase = ""
        .if ( r_aone.Obj_ID == r_aoth.Obj_ID )
          .assign phrase = r_aoth.Txt_Phrs
        .end if
        .assign card = "one"
        .if ( r_aoth.Mult )
          .assign card = "any"
        .end if
        .select one r_rto related by r_aone->R_RTO[R204]
        .invoke r = compare_referentials_to_identifiers( $l{o_obj.Key_Lett}, $l{target_o_obj.Key_Lett}, r_rgo, r_rto )
        .assign comparison = r.body
        .invoke r = t_participation( o_obj.Key_Lett, target_o_obj.Key_Lett, r_rel.Numb, card, phrase, comparison )
  // aone participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${target_o_obj.Name}(${target_o_obj.Key_Lett})
${r.body}
      .end if
    .end if
  .end for
.end function
.//
.function aoth_participation .// string
  .param inst_ref o_obj
  .select many r_aoths related by o_obj->R_OIR[R201]->R_RTO[R203]->R_AOTH[R204]
  .for each r_aoth in r_aoths
    .select one r_assoc related by r_aoth->R_ASSOC[R210]
    .select one r_rel related by r_assoc->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select one r_aone related by r_assoc->R_AONE[R209]
      .if ( not r_aone.Cond )
        .select one r_rgo related by r_assoc->R_ASSR[R211]->R_RGO[R205]
        .select one target_o_obj related by r_rgo->R_OIR[R203]->O_OBJ[R201]
        .assign phrase = ""
        .if ( r_aone.Obj_ID == r_aoth.Obj_ID )
          .assign phrase = r_aone.Txt_Phrs
        .end if
        .assign card = "one"
        .if ( r_aone.Mult )
          .assign card = "any"
        .end if
        .select one r_rto related by r_aoth->R_RTO[R204]
        .invoke r = compare_referentials_to_identifiers( $l{o_obj.Key_Lett}, $l{target_o_obj.Key_Lett}, r_rgo, r_rto )
        .assign comparison = r.body
        .invoke r = t_participation( o_obj.Key_Lett, target_o_obj.Key_Lett, r_rel.Numb, card, phrase, comparison )
  // aoth participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${target_o_obj.Name}(${target_o_obj.Key_Lett})
${r.body}
      .end if
    .end if
  .end for
.end function
.//
.function supertype_participation .// string
  .param inst_ref o_obj
  .assign loop_body = ""
  .select many r_supers related by o_obj->R_OIR[R201]->R_RTO[R203]->R_SUPER[R204]
  .for each r_super in r_supers
    .select one r_subsup related by r_super->R_SUBSUP[R212]
    .select one r_rel related by r_subsup->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select many r_subs related by r_subsup->R_SUB[R213]
      .for each r_sub in r_subs
        .select one source_o_obj related by r_sub->R_RGO[R205]->R_OIR[R203]->O_OBJ[R201]
        .invoke r = t_super_to_sub( o_obj.Key_Lett, source_o_obj.Key_Lett, r_rel.Numb )
        .assign loop_body = loop_body + r.body
      .end for
      .invoke r = t_supertype_loop( o_obj.Key_Lett, r_rel.Numb, loop_body )
  // super to sub participation R$t{r_rel.Numb}:  supertype ${o_obj.Name}(${o_obj.Key_Lett})
${r.body}
    .end if
  .end for
.end function
.//
.function subtype_participation .// string
  .param inst_ref o_obj
  .select many r_subs related by o_obj->R_OIR[R201]->R_RGO[R203]->R_SUB[R205]
  .for each r_sub in r_subs
    .select one r_subsup related by r_sub->R_SUBSUP[R213]
    .select one r_rel related by r_subsup->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select one target_o_obj related by r_subsup->R_SUPER[R212]->R_RTO[R204]->R_OIR[R203]->O_OBJ[R201]
      .invoke r = t_sub_to_super( o_obj.Key_Lett, target_o_obj.Key_Lett, r_rel.Numb )
  // sub to super participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${target_o_obj.Name}(${target_o_obj.Key_Lett})
${r.body}
    .end if
  .end for
.end function
.//
.// Return true if the element exists (nested) in the given package name.
.function in_ep_pkg .// boolean
  .param inst_ref ep_pkg
  .param string ep_pkg_Name
  .assign inpkg = false
  .if ( not_empty ep_pkg )
    .if ( ep_pkg_Name == ep_pkg.Name )
      .assign inpkg = true
    .else
      .select one ep_pkg related by ep_pkg->PE_PE[R8001]->EP_PKG[R8000]
      .invoke r = in_ep_pkg( ep_pkg, ep_pkg_Name )
      .assign inpkg = r.result
    .end if
  .end if
  .assign attr_result = inpkg
.end function
.//
.function generate_actions .// string
// For each class in the model do the following:
//   Search for duplicate identifiers in the instance extent.
//   Find unconditional formalizer from a participant in a simple association.
//   Find unconditional participant from a formalizer in a simple association.
//   For an associator in a linked association ensure both ends have an instance.
//   For the one end of an associative, find the unconditional associator.
//   For the other end of an associative, find the unconditional associator.
//   For a subtype, be sure a supertype is present.
//   For a supertype, be sure exactly one subtype is present.
// Show only the first violation of any particular rule in each extent.
  .select many o_objs from instances of O_OBJ
  .for each o_obj in o_objs
    .select one ep_pkg related by o_obj->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .assign text = ""
      .select many o_ids related by o_obj->O_ID[R104]
      .for each o_id in o_ids
        .select one o_oida related by o_id->O_OIDA[R105]
        .if ( not_empty o_oida )
          .invoke r = instance_uniqueness( o_id )
          .assign text = text + r.body
        .end if
      .end for
      .// participant
      .invoke r = participant_participation( o_obj )
      .assign text = text + r.body
      .// formalizer
      .invoke r = formalizer_participation( o_obj )
      .assign text = text + r.body
      .// associator
      .invoke r = associator_participation( o_obj )
      .assign text = text + r.body
      .// aone
      .invoke r = aone_participation( o_obj )
      .assign text = text + r.body
      .// aoth
      .invoke r = aoth_participation( o_obj )
      .assign text = text + r.body
      .// subtype
      .invoke r = subtype_participation( o_obj )
      .assign text = text + r.body
      .// supertype
      .invoke r = supertype_participation( o_obj )
      .assign text = text + r.body
      .// iterate
      .invoke r = t_class_instance_iteration( o_obj.Key_Lett, text )
${r.body}
    .end if
  .end for
  .//
.end function
.//
.function ooaofooa_check_referential_integrity .// string
  .invoke r = generate_actions()
${r.body}
.end function
.//
.invoke r = ooaofooa_check_referential_integrity()
${r.body}
.emit to file "../ooa.txt"

.// TODO - compare referential attribute values
.// TODO - _exactly_ one subtype
.//
.// Iterate over the given class.
.function t_class_instance_iteration .// string
  .param string key_letters
  .param string inner_body
select many $l{key_letters}s from instances of ${key_letters};
for each $l{key_letters} in $l{key_letters}s
${inner_body}
end for;
.end function
.//
.// Ensure no duplicate instance identifiers.
.function t_duplication .// string
  .param string key_letters
  .param string where_clause
  .param integer Numb
  select many duplicate_$l{key_letters}s from instances of ${key_letters} where ( ${where_clause} );
  if ( cardinality duplicate_$l{key_letters}s != 1 )
    LOG::LogInfo( message: "uniqueness violation in ${key_letters} for identifier $t{Numb}" );
    break;
  end if;
.end function
.//
.// Select across link to required instance.
.function t_participation .// string
  .param string left_side
  .param string right_side
  .param integer Numb
  .param string multiplicity
  .param string phrase
  .param string attribute_comparison
  .if ( "" != phrase )
  select ${multiplicity} $l{right_side} related by $l{left_side}->${right_side}[R$t{Numb}.'${phrase}'];
  .else
  select ${multiplicity} $l{right_side} related by $l{left_side}->${right_side}[R$t{Numb}];
  .end if
  if ( empty $l{right_side} )
  .if ( "" != phrase )
    LOG::LogInfo( message: "instance not found ${left_side}->${right_side}[R$t{Numb}.'${phrase}']" );
  .else
    LOG::LogInfo( message: "instance not found ${left_side}->${right_side}[R$t{Numb}]" );
  .end if
    break;
  .if ( "" != attribute_comparison )
  else
    if ( not ( ${attribute_comparison} ) )
      LOG::LogInfo( message: "referentials do not match identifiers between ${left_side} and ${right_side}" );
      break;
    end if;
  .end if
  end if;
.end function
.//
.// Loop through looking for a subtype.
.function t_supertype_loop .// string
  .param string super
  .param integer Numb
  .param string Loop_Body
${Loop_Body}
  LOG::LogInfo( message: "subtype not found from ${super} across R$t{Numb}" );
  break;
.end function
.//
.// Be sure supertype is present.
.function t_sub_to_super .// string
  .param string sub
  .param string super
  .param integer Numb
  select one $l{super} related by $l{sub}->${super}[R$t{Numb}];
  if ( empty $l{super} )
    LOG::LogInfo( message: "supertype not found across ${sub}->${super}[R$t{Numb}]" );
    break;
  end if;
.end function
.//
.// Look for a particular subtype.
.function t_super_to_sub .// string
  .param string super
  .param string sub
  .param integer Numb
  select one $l{sub} related by $l{super}->${sub}[R$t{Numb}];
  if ( not_empty $l{sub} )
    continue;
  end if;
.end function
.//
.function instance_uniqueness .// string
  .param inst_ref o_id
  .select one o_obj related by o_id->O_OBJ[R104]
  .assign where_clause = ""
  .assign prefix = ""
  .select many o_oidas related by o_id->O_OIDA[R105]
  .for each o_oida in o_oidas
    .assign clause = "selected." + o_oida.localAttributeName + " == " + $l{o_obj.Key_Lett} + "." + o_oida.localAttributeName
    .assign where_clause = where_clause + prefix + clause
    .assign prefix = " and "
  .end for
  .invoke r = t_duplication( o_obj.Key_Lett, where_clause, o_id.Oid_ID + 1 )
${r.body}
.end function
.//
.function compare_referentials_to_identifiers
  .param string rto_name
  .param string rgo_name
  .param inst_ref r_rto
  .param inst_ref r_rgo
  .//
  .assign where_clause = ""
  .assign conjunction = ""
  .select many o_oidas related by r_rto->O_ID[R109]->O_OIDA[R105]
  .for each o_oida in o_oidas
    .// Get the identifying attribute corresponding to this <o_oida> instance.
    .select any o_attr related by o_oida->O_ATTR[R105] where (selected.Attr_ID == o_oida.Attr_ID)
    .select any o_rtida related by r_rto->O_RTIDA[R110] where ((selected.Attr_ID == o_oida.Attr_ID) and ((selected.Obj_ID == o_oida.Obj_ID) and (selected.Oid_ID == o_oida.Oid_ID)))
    .// There can be more than one valid O_REF here, so get _any_ one.
    .// Note:  If MANY <o_rtida>, we need to rip through the (possible) combined referentials,
    .// unlinking any non-constrained elements.
    .select any o_ref related by o_rtida->O_REF[R111] where ( (selected.Obj_ID == r_rgo.Obj_ID) and (selected.OIR_ID == r_rgo.OIR_ID) )
    .// Get the referential attribute corresponding to the current <o_attr>.
    .select one ref_o_attr related by o_ref->O_RATTR[R108]->O_ATTR[R106]
    .select one o_dbattr related by o_attr->O_BATTR[R106]->O_DBATTR[R107]
    .// template here
    .assign clause = rto_name + "." + o_attr.Name + " == " + rgo_name + "." + ref_o_attr.Name
    .assign where_clause = where_clause + conjunction + clause
    .assign conjunction = " and "
  .end for
${where_clause}\
.end function
.//
.function participant_participation .// string
  .param inst_ref o_obj
  .select many r_parts related by o_obj->R_OIR[R201]->R_RTO[R203]->R_PART[R204]
  .for each r_part in r_parts
    .select one r_simp related by r_part->R_SIMP[R207]
    .select one r_rel related by r_simp->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select one r_form related by r_simp->R_FORM[R208]
      .if ( not_empty r_form )
        .if ( not r_form.Cond )
          .select one r_rgo related by r_form->R_RGO[R205]
          .select one target_o_obj related by r_rgo->R_OIR[R203]->O_OBJ[R201]
          .assign card = "one"
          .if ( r_form.Mult )
            .assign card = "any"
          .end if
          .assign phrase = ""
          .if ( r_part.Obj_ID == r_form.Obj_ID )
            .assign phrase = r_form.Txt_Phrs
          .end if
          .select one r_rto related by r_part->R_RTO[R204]
          .invoke r = compare_referentials_to_identifiers( $l{o_obj.Key_Lett}, $l{target_o_obj.Key_Lett}, r_rto, r_rgo )
          .assign comparison = r.body
          .invoke r = t_participation( o_obj.Key_Lett, target_o_obj.Key_Lett, r_rel.Numb, card, phrase, comparison )
  // participant participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${target_o_obj.Name}(${target_o_obj.Key_Lett})
${r.body}
        .end if
      .else
  // unformalized association R$t{r_rel.Numb}
      .end if
    .end if
  .end for
.end function
.//
.function formalizer_participation .// string
  .param inst_ref o_obj
  .select many r_forms related by o_obj->R_OIR[R201]->R_RGO[R203]->R_FORM[R205]
  .for each r_form in r_forms
    .select one r_simp related by r_form->R_SIMP[R208]
    .select one r_rel related by r_simp->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select one r_part related by r_simp->R_PART[R207]
      .if ( not r_part.Cond )
        .select one target_o_obj related by r_part->R_RTO[R204]->R_OIR[R203]->O_OBJ[R201]
        .assign card = "one"
        .if ( r_part.Mult )
          .assign card = "any"
        .end if
        .assign phrase = ""
        .if ( r_part.Obj_ID == r_form.Obj_ID )
          .assign phrase = r_part.Txt_Phrs
        .end if
        .invoke r = t_participation( o_obj.Key_Lett, target_o_obj.Key_Lett, r_rel.Numb, card, phrase, "" )
  // formalizer participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${target_o_obj.Name}(${target_o_obj.Key_Lett})
${r.body}
      .end if
    .end if
  .end for
.end function
.//
.function associator_participation .// string
  .param inst_ref o_obj
  .select many r_assrs related by o_obj->R_OIR[R201]->R_RGO[R203]->R_ASSR[R205]
  .for each r_assr in r_assrs
    .select one r_assoc related by r_assr->R_ASSOC[R211]
    .select one r_rel related by r_assoc->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select one r_aone related by r_assoc->R_AONE[R209]
      .select one r_aoth related by r_assoc->R_AOTH[R210]
      .select one aone_o_obj related by r_aone->R_RTO[R204]->R_OIR[R203]->O_OBJ[R201]
      .select one aoth_o_obj related by r_aoth->R_RTO[R204]->R_OIR[R203]->O_OBJ[R201]
      .assign phrase = ""
      .if ( r_aone.Obj_ID == r_aoth.Obj_ID )
        .assign phrase = r_aone.Txt_Phrs
      .end if
      .invoke r = t_participation( o_obj.Key_Lett, aone_o_obj.Key_Lett, r_rel.Numb, "one", phrase, "" )
  // associator one participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${aone_o_obj.Name}(${aone_o_obj.Key_Lett})
${r.body}
      .assign phrase = ""
      .if ( r_aone.Obj_ID == r_aoth.Obj_ID )
        .assign phrase = r_aoth.Txt_Phrs
      .end if
      .invoke r = t_participation( o_obj.Key_Lett, aoth_o_obj.Key_Lett, r_rel.Numb, "one", phrase, "" )
  // associator other participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${aoth_o_obj.Name}(${aoth_o_obj.Key_Lett})
${r.body}
    .end if
  .end for
.end function
.//
.function aone_participation .// string
  .param inst_ref o_obj
  .select many r_aones related by o_obj->R_OIR[R201]->R_RTO[R203]->R_AONE[R204]
  .for each r_aone in r_aones
    .select one r_assoc related by r_aone->R_ASSOC[R209]
    .select one r_rel related by r_assoc->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select one r_aoth related by r_assoc->R_AOTH[R210]
      .if ( not r_aoth.Cond )
        .select one target_o_obj related by r_assoc->R_ASSR[R211]->R_RGO[R205]->R_OIR[R203]->O_OBJ[R201]
        .assign phrase = ""
        .if ( r_aone.Obj_ID == r_aoth.Obj_ID )
          .assign phrase = r_aoth.Txt_Phrs
        .end if
        .assign card = "one"
        .if ( r_aoth.Mult )
          .assign card = "any"
        .end if
        .invoke r = t_participation( o_obj.Key_Lett, target_o_obj.Key_Lett, r_rel.Numb, card, phrase, "" )
  // aone participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${target_o_obj.Name}(${target_o_obj.Key_Lett})
${r.body}
      .end if
    .end if
  .end for
.end function
.//
.function aoth_participation .// string
  .param inst_ref o_obj
  .select many r_aoths related by o_obj->R_OIR[R201]->R_RTO[R203]->R_AOTH[R204]
  .for each r_aoth in r_aoths
    .select one r_assoc related by r_aoth->R_ASSOC[R210]
    .select one r_rel related by r_assoc->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select one r_aone related by r_assoc->R_AONE[R209]
      .if ( not r_aone.Cond )
        .select one target_o_obj related by r_assoc->R_ASSR[R211]->R_RGO[R205]->R_OIR[R203]->O_OBJ[R201]
        .assign phrase = ""
        .if ( r_aone.Obj_ID == r_aoth.Obj_ID )
          .assign phrase = r_aone.Txt_Phrs
        .end if
        .assign card = "one"
        .if ( r_aone.Mult )
          .assign card = "any"
        .end if
        .invoke r = t_participation( o_obj.Key_Lett, target_o_obj.Key_Lett, r_rel.Numb, card, phrase, "" )
  // aoth participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${target_o_obj.Name}(${target_o_obj.Key_Lett})
${r.body}
      .end if
    .end if
  .end for
.end function
.//
.function supertype_participation .// string
  .param inst_ref o_obj
  .assign loop_body = ""
  .select many r_supers related by o_obj->R_OIR[R201]->R_RTO[R203]->R_SUPER[R204]
  .for each r_super in r_supers
    .select one r_subsup related by r_super->R_SUBSUP[R212]
    .select one r_rel related by r_subsup->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select many r_subs related by r_subsup->R_SUB[R213]
      .for each r_sub in r_subs
        .select one source_o_obj related by r_sub->R_RGO[R205]->R_OIR[R203]->O_OBJ[R201]
        .invoke r = t_super_to_sub( o_obj.Key_Lett, source_o_obj.Key_Lett, r_rel.Numb )
        .assign loop_body = loop_body + r.body
      .end for
      .invoke r = t_supertype_loop( o_obj.Key_Lett, r_rel.Numb, loop_body )
  // super to sub participation R$t{r_rel.Numb}:  supertype ${o_obj.Name}(${o_obj.Key_Lett})
${r.body}
    .end if
  .end for
.end function
.//
.function subtype_participation .// string
  .param inst_ref o_obj
  .select many r_subs related by o_obj->R_OIR[R201]->R_RGO[R203]->R_SUB[R205]
  .for each r_sub in r_subs
    .select one r_subsup related by r_sub->R_SUBSUP[R213]
    .select one r_rel related by r_subsup->R_REL[R206]
    .select one ep_pkg related by r_rel->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .select one target_o_obj related by r_subsup->R_SUPER[R212]->R_RTO[R204]->R_OIR[R203]->O_OBJ[R201]
      .invoke r = t_sub_to_super( o_obj.Key_Lett, target_o_obj.Key_Lett, r_rel.Numb )
  // sub to super participation R$t{r_rel.Numb}:  ${o_obj.Name}(${o_obj.Key_Lett}) -> ${target_o_obj.Name}(${target_o_obj.Key_Lett})
${r.body}
    .end if
  .end for
.end function
.//
.// Return true if the element exists (nested) in the given package name.
.function in_ep_pkg .// boolean
  .param inst_ref ep_pkg
  .param string ep_pkg_Name
  .assign inpkg = false
  .if ( not_empty ep_pkg )
    .if ( ep_pkg_Name == ep_pkg.Name )
      .assign inpkg = true
    .else
      .select one ep_pkg related by ep_pkg->PE_PE[R8001]->EP_PKG[R8000]
      .invoke r = in_ep_pkg( ep_pkg, ep_pkg_Name )
      .assign inpkg = r.result
    .end if
  .end if
  .assign attr_result = inpkg
.end function
.//
.function generate_actions .// string
// For each class in the model do the following:
//   Search for duplicate identifiers in the instance extent.
//   Find unconditional formalizer from a participant in a simple association.
//   Find unconditional participant from a formalizer in a simple association.
//   For an associator in a linked association ensure both ends have an instance.
//   For the one end of an associative, find the unconditional associator.
//   For the other end of an associative, find the unconditional associator.
//   For a subtype, be sure a supertype is present.
//   For a supertype, be sure exactly one subtype is present.
// Show only the first violation of any particular rule in each extent.
  .select many o_objs from instances of O_OBJ
  .for each o_obj in o_objs
    .select one ep_pkg related by o_obj->PE_PE[R8001]->EP_PKG[R8000]
    .invoke r = in_ep_pkg( ep_pkg, "ooaofooa" )
    .if ( r.result )
      .assign text = ""
      .select many o_ids related by o_obj->O_ID[R104]
      .for each o_id in o_ids
        .select one o_oida related by o_id->O_OIDA[R105]
        .if ( not_empty o_oida )
          .invoke r = instance_uniqueness( o_id )
          .assign text = text + r.body
        .end if
      .end for
      .// participant
      .invoke r = participant_participation( o_obj )
      .assign text = text + r.body
      .// formalizer
      .invoke r = formalizer_participation( o_obj )
      .assign text = text + r.body
      .// associator
      .invoke r = associator_participation( o_obj )
      .assign text = text + r.body
      .// aone
      .invoke r = aone_participation( o_obj )
      .assign text = text + r.body
      .// aoth
      .invoke r = aoth_participation( o_obj )
      .assign text = text + r.body
      .// subtype
      .invoke r = subtype_participation( o_obj )
      .assign text = text + r.body
      .// supertype
      .invoke r = supertype_participation( o_obj )
      .assign text = text + r.body
      .// iterate
      .invoke r = t_class_instance_iteration( o_obj.Key_Lett, text )
${r.body}
    .end if
  .end for
  .//
.end function
.//
.function ooaofooa_check_referential_integrity .// string
  .invoke r = generate_actions()
${r.body}
.end function
.//
.invoke r = ooaofooa_check_referential_integrity()
${r.body}
.emit to file "../ooa.txt"


job #52 - Change the way I make use of the te_c.OptDisabled flag which is now honored in this area of the code.

.//============================================================================
.// $RCSfile: q.class.sem.arc,v $
.//
.// Description:
.// This archetype file contains functions for generating the structural
.// (state event matrix e.g., SEM) aspects of object state machines.
.//
.// Notice:
.// (C) Copyright 1998-2013 Mentor Graphics Corporation
.//     All rights reserved.
.//
.// This document contains confidential and proprietary information and
.// property of Mentor Graphics Corp.  No part of this document may be
.// reproduced without the express written permission of Mentor Graphics Corp.
.//============================================================================
.//
.//
.//===========================================================================
.// Build information about the state machine event.
.//===========================================================================
.function GetMaxEventInfo
  .param inst_ref o_obj
  .param boolean is_ism
  .//
  .assign attr_number = 0
  .if ( is_ism )
    .select many event_set related by o_obj->SM_ISM[R518]->SM_SM[R517]->SM_EVT[R502]->SM_SEVT[R525]->SM_EVT[R525]
    .assign attr_number = cardinality event_set
  .else
    .select many event_set related by o_obj->SM_ASM[R519]->SM_SM[R517]->SM_EVT[R502]
    .assign attr_number = cardinality event_set
  .end if
  .//
  .if ( attr_number != 0 )
    .// Decrement by one, since event enums start at zero.
    .assign attr_number = attr_number - 1
  .end if
.end function
.//
.//============================================================================
.// Return <body> the declaration (e.g., header file guts) of the
.// possible state enumerations for a state machine.
.// This function may be used for either an Instance State Model (ISM) or
.// Assigner State Model (ASM).
.//
.// Output Fragment Attributes:
.// <body> An ordered enumeration of the states in the state model.
.//
.// Predicates:
.// Attributes of SM_STATE.Order have been initialized (ascending).
.//============================================================================
.function GetStateEnumsFromStateSet
  .param inst_ref sm_sm
  .//
  .select one te_sm related by sm_sm->TE_SM[R2043]
  .select many te_states related by sm_sm->SM_STATE[R501]->TE_STATE[R2037]
  .if ( not_empty te_states )
/*
 * enumeration of state model states for class
 */
    .assign state_count = 0
    .while ( state_count < te_sm.num_states )
      .for each te_state in te_states
        .if ( te_state.Order == state_count )
#define ${te_state.enumerator} ${te_state.number}  /* state [$t{te_state.Numb}]:  (${te_state.Name}) */
          .assign max_state_value = te_state.enumerator
          .break for
        .end if
      .end for
      .assign state_count = state_count + 1
    .end while
  .else
/* WARNING! No states defined for state model */
  .end if
  .//
.end function
.//
.//============================================================================
.// Return the enumeration of initial state of the state machine.
.//============================================================================
.function GetInstanceInitialStateEnum
  .param inst_ref o_obj
  .//
  .assign attr_result = "0"
  .select one ism related by o_obj->SM_ISM[R518]
  .if ( not_empty ism )
    .select any te_state related by o_obj->SM_ISM[R518]->SM_SM[R517]->SM_STATE[R501]->TE_STATE[R2037] where (selected.Order == 0)
    .if ( not_empty te_state )
      .assign attr_result = te_state.enumerator
    .end if
  .end if
.end function
.//
.//============================================================================
.// Build enumeration (using #defines) defining event numbers.
.//============================================================================
.function CreateStateModelEventEnum
  .param inst_ref sm_sm
  .//
  .select one te_sm related by sm_sm->TE_SM[R2043]
  .// get the locally used events first
  .select many te_evts related by sm_sm->SM_EVT[R502]->SM_SEVT[R525]->SM_EVT[R525]->TE_EVT[R2036]
  .assign attr_no_events = true
  .assign event_order = 0
  .if ( not_empty te_evts )
/*
 * enumeration of state model event numbers
 */
    .select one te_c related by te_sm->TE_CLASS[R2072]->TE_C[R2064]
    .assign attr_no_events = false
    .assign num_events = cardinality te_evts
    .assign event_count = 0
    .assign last_order = 0
    .while ( event_count < num_events )
      .for each te_evt in te_evts
        .if ( te_evt.Order > last_order )
          .assign last_order = te_evt.Order
        .end if
        .if ( ( te_evt.Order == event_count ) and ( te_evt.Used or te_c.OptDisabled ) )
          .select one sm_evt related by te_evt->SM_EVT[R2036]
          .assign event_comment = sm_evt.Drv_Lbl
          .if ( sm_evt.Mning != "" )
            .assign event_comment = "${sm_evt.Drv_Lbl}:'${sm_evt.Mning}'"
          .end if
#define ${te_evt.Enumerator} ${event_order}  /* ${event_comment} */
          .assign event_order = event_order + 1
          .break for
        .end if
      .end for
      .assign event_count = event_count + 1
    .end while
  .end if
  .//
  .select many poly_event_set related by sm_sm->SM_EVT[R502]->SM_PEVT[R525]->SM_EVT[R525]
  .if ( not_empty poly_event_set )

/*
 * Enumeration of polymorphic event numbers
 */
    .assign attr_no_events = false
    .for each event in poly_event_set
      .select one te_evt related by event->TE_EVT[R2036]
      .assign event_comment = event.Drv_Lbl
      .if ( event.Mning != "" )
        .assign event_comment = "${event.Drv_Lbl}:'${event.Mning}'"
      .end if
#define ${te_evt.Enumerator} ${event_order}  /* ${event_comment} */
      .assign event_order = event_order + 1
    .end for
  .end if
  .if ( attr_no_events == true )
/* note:  no events defined in state model */
  .end if
.end function
.//
.//============================================================================
.// Create the State Event Matrix (SEM) for a state model.
.//
.// The SEM provides an exhaustive mapping of current state and received event
.// combinations to the next state (if any). Each class state has an entry
.// in the SEM for each possible event that the object can receive.
.// If a particular state does not deal with a particular event then the state
.// action is assigned as either a _dont care_ or _cant happen_ (as assigned
.// in the analysis xtUML).
.// The Row Index of the SEM corresponds to the architecturally enumerated
.// current state of the object.  Row 0 is the uninitialized state
.// of the object, which services creation event transitions.
.// The Column Index of the SEM corresponds to the architecturally enumerated
.// event numbers of events that may be received by the state machine.
.//============================================================================
.function CreateStateEventMatrixTable
  .param inst_ref sm_sm
  .select any te_file from instances of TE_FILE
  .select any te_typemap from instances of TE_TYPEMAP
  .select one te_sm related by sm_sm->TE_SM[R2043]
  .select one te_c related by te_sm->TE_CLASS[R2072]->TE_C[R2064]
  .// Watch out for incomplete xtUML models.
  .if ( (te_sm.num_states > 0) and (te_sm.num_events > 0) )
    .assign state_count = 0
    .select many te_evts related by sm_sm->SM_EVT[R502]->SM_SEVT[R525]->SM_EVT[R525]->TE_EVT[R2036] where ( selected.Used )
    .if ( te_c.OptDisabled )
      .select many te_evts related by sm_sm->SM_EVT[R502]->SM_SEVT[R525]->SM_EVT[R525]->TE_EVT[R2036]
    .end if
    .assign num_events = cardinality te_evts
    .select many sm_states related by sm_sm->SM_STATE[R501]
    .select any sm_state related by sm_sm->SM_STATE[R501]
    .//
    .// Create a row for the initial state (0).
    .invoke r = CreateStateEventMatrixRow( sm_state, te_evts, state_count, num_events )
    .assign first_row = r.body
    .assign other_rows = ""
    .//
    .// Create a row for each real state in the SEM
    .assign state_count = state_count + 1
    .while ( state_count <= te_sm.num_states )
      .for each sm_state in sm_states
        .select one te_state related by sm_state->TE_STATE[R2037]
        .if ( te_state.number == state_count )
          .assign comment = "  /* row ${state_count}:  ${te_state.enumerator} (${te_state.Name}) */\n"
          .invoke r = CreateStateEventMatrixRow( sm_state, te_evts, state_count, num_events )
          .assign other_rows = ( other_rows + ",\n" ) + ( comment + r.body )
          .break for
        .end if
      .end for
      .assign state_count = state_count + 1
    .end while
    .include "${te_file.arc_path}/t.class.sem.matrix.c"
  .end if
.end function
.//
.//============================================================================
.// Create a row in the State Event Matrix (SEM) for a state model.
.//============================================================================
.function CreateStateEventMatrixRow
  .param inst_ref sm_state
  .param inst_ref_set te_evts
  .param integer order
  .param integer num_events
  .select any te_eq from instances of TE_EQ
  .assign event_number = 0
  .assign event_count = 0
  .assign row = ""
  .assign delimiter = ""
  .select any empty_sm_txn from instances of SM_TXN where ( false )
  .select any empty_sm_eign from instances of SM_EIGN where ( false )
  .// Here we use event_count and event_number, because we may skip events
  .// that are not used.  Soon there will be a reflexive on TE_EVT.
  .// Guard by limiting loop to 256 events.
  .while ( ( event_count < num_events ) and ( event_number < 256 ) )
    .assign cell = ""
    .assign found = false
    .for each te_evt in te_evts
      .if ( te_evt.Order == event_number )
        .assign found = true
        .assign sm_txn = empty_sm_txn
        .assign sm_eign = empty_sm_eign
        .if ( 0 == order )
          .// Deal with creation event transitions.
          .select one sm_txn related by te_evt->SM_EVT[R2036]->SM_SEVT[R525]->SM_LEVT[R526]->SM_CRTXN[R509]->SM_TXN[R507]
        .else
          .// Deal with normal transitions.
          .select any sm_seme related by te_evt->SM_EVT[R2036]->SM_SEVT[R525]->SM_SEME[R503] where ( selected.SMstt_ID == sm_state.SMstt_ID )
          .select one sm_nstxn related by sm_seme->SM_NSTXN[R504]
          .if ( not_empty sm_nstxn )
            .// NOTE:  To avoid problems with PE, we need the following to
            .// bypass metamodel issues when a PE and a local event both
            .// have transitions between the same state pairs.
            .select any sm_txn related by sm_state->SM_SM[R501]->SM_TXN[R505] where ( selected.Trans_ID == sm_nstxn.Trans_ID )
          .else
            .select one sm_eign related by sm_seme->SM_EIGN[R504]
          .end if
        .end if
        .if ( not_empty sm_txn )
          .select one next_te_state related by sm_txn->SM_STATE[R506]->TE_STATE[R2037]
          .select one txn_te_act related by sm_txn->SM_TAH[R530]->SM_AH[R513]->SM_ACT[R514]->TE_ACT[R2022]
          .if ( not_empty txn_te_act )
            .// We have a transition action.  Prepend number to cell.
            .assign cell = "(${txn_te_act.number}<<8) + "
          .end if
          .assign cell = ( delimiter + cell ) + next_te_state.enumerator
        .elif ( not_empty sm_eign )
          .assign cell = delimiter + te_eq.ignored
        .else
          .assign cell = delimiter + te_eq.cant_happen
        .end if
        .assign delimiter = ", "
        .break for
      .end if
    .end for
    .assign event_number = event_number + 1
    .if ( found )
      .assign event_count = event_count + 1
    .end if
    .assign row = row + cell
  .end while
  { ${row} }\
.end function
.//
.//============================================================================
.// Output the array of pointers that refer to the actions of the states.
.//============================================================================
.function CreateStateActionArray
  .param inst_ref te_c
  .param inst_ref sm_sm
  .select any te_file from instances of TE_FILE
  .select one te_sm related by sm_sm->TE_SM[R2043]
  .select many te_states related by sm_sm->SM_STATE[R501]->TE_STATE[R2037]
  .// Watch out for incomplete (or non-active) xtUML models.
  .assign state_space = te_sm.num_states + 1
  .assign state_names = ""
  .if ( te_sm.num_states > 0 )
    .assign delimiter = ","
    .assign state_action_rows = ""
    .assign state_count = 0
    .while ( state_count < te_sm.num_states )
      .if ( state_count == ( te_sm.num_states - 1 ) )
        .assign delimiter = ""
      .end if
      .for each te_state in te_states
        .if ( te_state.Order == state_count )
          .select one te_act related by te_state->SM_STATE[R2037]->SM_MOAH[R511]->SM_AH[R513]->SM_ACT[R514]->TE_ACT[R2022]
          .assign state_action_rows = state_action_rows + "    (${te_sm.action_type}) ${te_act.GeneratedName}${delimiter}  /* ${te_state.Name} */\n"
          .assign state_names = state_names + "    ""${te_state.Name}""${delimiter}\n"
          .break for
        .end if
      .end for
      .assign state_count = state_count + 1
    .end while
    .include "${te_file.arc_path}/t.class.sem.state_action_array.c"
  .end if
  .if ( te_c.StateTrace )
    .include "${te_file.arc_path}/t.class.sem.state_names.c"
  .end if
.end function
.//
.//============================================================================
.// Output the array of pointers that refer to the actions on the transitions.
.//============================================================================
.function CreateTransitionActionArray
  .param inst_ref sm_sm
  .select any te_file from instances of TE_FILE
  .select one te_sm related by sm_sm->TE_SM[R2043]
  .select many te_acts related by sm_sm->SM_TXN[R505]->SM_TAH[R530]->SM_AH[R513]->SM_ACT[R514]->TE_ACT[R2022]
  .assign num_te_acts = cardinality te_acts
  .if ( num_te_acts > 0 )
    .assign delimiter = ","
    .assign txn_action_rows = ""
    .for each te_act in te_acts
      .if ( last te_acts )
        .assign delimiter = ""
      .end if
      .assign txn_action_rows = txn_action_rows + "    (${te_sm.action_type}) ${te_act.GeneratedName}${delimiter}\n"
    .end for
    .include "${te_file.arc_path}/t.class.sem.txn_action_array.c"
  .end if
.end function
.//
.//===========================================================================
.// Output an event dispatcher for polymorphic event propagation.
.//===========================================================================
.function CreatePolymorphicEventDispatcher
  .param inst_ref o_obj
  .param inst_ref_set r_rels
  .//
  .select any te_eq from instances of TE_EQ
  .select any te_instance from instances of TE_INSTANCE
  .select any te_string from instances of TE_STRING
  .select any te_typemap from instances of TE_TYPEMAP
  .select one te_class related by o_obj->TE_CLASS[R2019]
  .if ( not_empty r_rels )
    .assign num_poly_rels = cardinality r_rels
    .if ( num_poly_rels == 1 )
  if ( 0 != GetIsPolymorphicEvent( event ) ) {
    .for each rel in r_rels
      .// for loop needed to get the one poly relationship.
      .invoke method_name = GetSuperTypePolymorphicEventMethodName( te_class, rel )
    ${method_name.result}( (${te_class.GeneratedName} *) instance, event );
    .end for
  }\
    .else
      .// Multidirectional subtyping
      .select one te_sm related by o_obj->SM_ISM[R518]->SM_SM[R517]->TE_SM[R2043]
  if ( 0 != GetIsPolymorphicEvent( event ) ) {
    /* Multidirectional subtyping hierarchy:  Pass PE down all active legs.  */
    ${te_eq.base_event_type} * copy;
      .for each rel in r_rels
        .invoke method_name = GetSuperTypePolymorphicEventMethodName( te_class, rel )
    /* Propagate event down R${rel.Numb}  */
    copy = Escher_AllocateOoaEvent();
    ${te_instance.module}${te_string.memmove}( copy, event, sizeof( ${te_sm.events_union} ) );
    ${method_name.result}( instance, copy );
    ${te_instance.module}${te_eq.delete}( copy );
      .end for
  }\
    .end if
  .end if
.end function
.//
.//===========================================================================
.// Ouput the routine that will dispatch events for a class.
.//===========================================================================
.function CreateInstanceStateModelEventDispatcher
  .param inst_ref te_c
  .param inst_ref o_obj
  .param boolean  gen_declaration
  .//
  .select any te_callout from instances of TE_CALLOUT
  .select any te_eq from instances of TE_EQ
  .select any te_file from instances of TE_FILE
  .select any te_instance from instances of TE_INSTANCE
  .select any te_prefix from instances of TE_PREFIX
  .select any te_trace from instances of TE_TRACE
  .select any te_target from instances of TE_TARGET
  .select any te_typemap from instances of TE_TYPEMAP
  .select one te_class related by o_obj->TE_CLASS[R2019]
  .select any polymorphic_event from instances of SM_PEVT
  .//
  .if ( gen_declaration )
    .include "${te_file.arc_path}/t.class.idispatch.h"
  .else
    .// Watch out for possibly incomplete models!
    .select one sm_sm related by o_obj->SM_ISM[R518]->SM_SM[R517]
    .select one te_sm related by sm_sm->TE_SM[R2043]
    .invoke poly_rels = GetPolymorphicRelationshipCollection( o_obj )
    .assign poly_rel_set = poly_rels.result
    .//
    .invoke r = AutoInitializeUniqueIDs( te_class, "i" )
    .assign init_uniques = r.body
    .invoke max_event = GetMaxEventInfo( o_obj, true )
    .invoke r = GetDomainTypeIDFromString( te_c.Name )
    .assign dom_id = r.result
    .invoke poly_dispatch = CreatePolymorphicEventDispatcher( o_obj, poly_rel_set )
    .assign poly_dispatcher = poly_dispatch.body
    .//
    .// Does this state model have any self-creation transitions?
    .assign can_self_create = false
    .select any sm_crtxn related by sm_sm->SM_EVT[R502]->SM_SEVT[R525]->SM_LEVT[R526]->SM_CRTXN[R509]
    .if ( not_empty sm_crtxn )
      .assign can_self_create = true
    .end if
    .//
    .// Does this state model have any self-deletion transitions?
    .assign can_self_delete = false
    .select many final_state_set related by sm_sm->SM_STATE[R501] where ( selected.Final != 0 )
    .select many te_states related by final_state_set->TE_STATE[R2037]
    .if ( not_empty te_states )
      .assign can_self_delete = true
    .end if
    .select any evt_cant_happen related by sm_sm->SM_STATE[R501]->SM_SEME[R503]->SM_CH[R504]
    .select any evt_ignored related by sm_sm->SM_STATE[R501]->SM_SEME[R503]->SM_EIGN[R504]
    .select any nlevt related by o_obj->SM_ISM[R518]->SM_SM[R517]->SM_EVT[R502]->SM_SEVT[R525]->SM_NLEVT[R526]
    .include "${te_file.arc_path}/t.class.idispatch.c"
  .end if
.end function
.//

.//============================================================================
.// $RCSfile: q.class.sem.arc,v $
.//
.// Description:
.// This archetype file contains functions for generating the structural
.// (state event matrix e.g., SEM) aspects of object state machines.
.//
.// Notice:
.// (C) Copyright 1998-2013 Mentor Graphics Corporation
.//     All rights reserved.
.//
.// This document contains confidential and proprietary information and
.// property of Mentor Graphics Corp.  No part of this document may be
.// reproduced without the express written permission of Mentor Graphics Corp.
.//============================================================================
.//
.//
.//===========================================================================
.// Build information about the state machine event.
.//===========================================================================
.function GetMaxEventInfo
  .param inst_ref o_obj
  .param boolean is_ism
  .//
  .assign attr_number = 0
  .if ( is_ism )
    .select many event_set related by o_obj->SM_ISM[R518]->SM_SM[R517]->SM_EVT[R502]->SM_SEVT[R525]->SM_EVT[R525]
    .assign attr_number = cardinality event_set
  .else
    .select many event_set related by o_obj->SM_ASM[R519]->SM_SM[R517]->SM_EVT[R502]
    .assign attr_number = cardinality event_set
  .end if
  .//
  .if ( attr_number != 0 )
    .// Decrement by one, since event enums start at zero.
    .assign attr_number = attr_number - 1
  .end if
.end function
.//
.//============================================================================
.// Return <body> the declaration (e.g., header file guts) of the
.// possible state enumerations for a state machine.
.// This function may be used for either an Instance State Model (ISM) or
.// Assigner State Model (ASM).
.//
.// Output Fragment Attributes:
.// <body> An ordered enumeration of the states in the state model.
.//
.// Predicates:
.// Attributes of SM_STATE.Order have been initialized (ascending).
.//============================================================================
.function GetStateEnumsFromStateSet
  .param inst_ref sm_sm
  .//
  .select one te_sm related by sm_sm->TE_SM[R2043]
  .select many te_states related by sm_sm->SM_STATE[R501]->TE_STATE[R2037]
  .if ( not_empty te_states )
/*
 * enumeration of state model states for class
 */
    .assign state_count = 0
    .while ( state_count < te_sm.num_states )
      .for each te_state in te_states
        .if ( te_state.Order == state_count )
#define ${te_state.enumerator} ${te_state.number}  /* state [$t{te_state.Numb}]:  (${te_state.Name}) */
          .assign max_state_value = te_state.enumerator
          .break for
        .end if
      .end for
      .assign state_count = state_count + 1
    .end while
  .else
/* WARNING! No states defined for state model */
  .end if
  .//
.end function
.//
.//============================================================================
.// Return the enumeration of initial state of the state machine.
.//============================================================================
.function GetInstanceInitialStateEnum
  .param inst_ref o_obj
  .//
  .assign attr_result = "0"
  .select one ism related by o_obj->SM_ISM[R518]
  .if ( not_empty ism )
    .select any te_state related by o_obj->SM_ISM[R518]->SM_SM[R517]->SM_STATE[R501]->TE_STATE[R2037] where (selected.Order == 0)
    .if ( not_empty te_state )
      .assign attr_result = te_state.enumerator
    .end if
  .end if
.end function
.//
.//============================================================================
.// Build enumeration (using #defines) defining event numbers.
.//============================================================================
.function CreateStateModelEventEnum
  .param inst_ref sm_sm
  .//
  .select one te_sm related by sm_sm->TE_SM[R2043]
  .// get the locally used events first
  .select many te_evts related by sm_sm->SM_EVT[R502]->SM_SEVT[R525]->SM_EVT[R525]->TE_EVT[R2036]
  .assign attr_no_events = true
  .assign event_order = 0
  .if ( not_empty te_evts )
/*
 * enumeration of state model event numbers
 */
    .select one te_c related by te_sm->TE_CLASS[R2072]->TE_C[R2064]
    .assign attr_no_events = false
    .assign num_events = cardinality te_evts
    .assign event_count = 0
    .assign last_order = 0
    .while ( event_count < num_events )
      .for each te_evt in te_evts
        .if ( te_evt.Order > last_order )
          .assign last_order = te_evt.Order
        .end if
        .if ( ( te_evt.Order == event_count ) and ( te_evt.Used or te_c.OptDisabled ) )
          .select one sm_evt related by te_evt->SM_EVT[R2036]
          .assign event_comment = sm_evt.Drv_Lbl
          .if ( sm_evt.Mning != "" )
            .assign event_comment = "${sm_evt.Drv_Lbl}:'${sm_evt.Mning}'"
          .end if
#define ${te_evt.Enumerator} ${event_order}  /* ${event_comment} */
          .assign event_order = event_order + 1
          .break for
        .end if
      .end for
      .assign event_count = event_count + 1
    .end while
  .end if
  .//
  .select many poly_event_set related by sm_sm->SM_EVT[R502]->SM_PEVT[R525]->SM_EVT[R525]
  .if ( not_empty poly_event_set )

/*
 * Enumeration of polymorphic event numbers
 */
    .assign attr_no_events = false
    .for each event in poly_event_set
      .select one te_evt related by event->TE_EVT[R2036]
      .assign event_comment = event.Drv_Lbl
      .if ( event.Mning != "" )
        .assign event_comment = "${event.Drv_Lbl}:'${event.Mning}'"
      .end if
#define ${te_evt.Enumerator} ${event_order}  /* ${event_comment} */
      .assign event_order = event_order + 1
    .end for
  .end if
  .if ( attr_no_events == true )
/* note:  no events defined in state model */
  .end if
.end function
.//
.//============================================================================
.// Create the State Event Matrix (SEM) for a state model.
.//
.// The SEM provides an exhaustive mapping of current state and received event
.// combinations to the next state (if any). Each class state has an entry
.// in the SEM for each possible event that the object can receive.
.// If a particular state does not deal with a particular event then the state
.// action is assigned as either a _dont care_ or _cant happen_ (as assigned
.// in the analysis xtUML).
.// The Row Index of the SEM corresponds to the architecturally enumerated
.// current state of the object.  Row 0 is the uninitialized state
.// of the object, which services creation event transitions.
.// The Column Index of the SEM corresponds to the architecturally enumerated
.// event numbers of events that may be received by the state machine.
.//============================================================================
.function CreateStateEventMatrixTable
  .param inst_ref sm_sm
  .select any te_file from instances of TE_FILE
  .select any te_typemap from instances of TE_TYPEMAP
  .select one te_sm related by sm_sm->TE_SM[R2043]
  .select one te_c related by te_sm->TE_CLASS[R2072]->TE_C[R2064]
  .// Watch out for incomplete xtUML models.
  .if ( (te_sm.num_states > 0) and (te_sm.num_events > 0) )
    .assign state_count = 0
    .select many te_evts related by sm_sm->SM_EVT[R502]->SM_SEVT[R525]->SM_EVT[R525]->TE_EVT[R2036] where ( selected.Used or te_c.OptDisabled )
    .assign num_events = cardinality te_evts
    .select many sm_states related by sm_sm->SM_STATE[R501]
    .select any sm_state related by sm_sm->SM_STATE[R501]
    .//
    .// Create a row for the initial state (0).
    .invoke r = CreateStateEventMatrixRow( sm_state, te_evts, state_count, num_events )
    .assign first_row = r.body
    .assign other_rows = ""
    .//
    .// Create a row for each real state in the SEM
    .assign state_count = state_count + 1
    .while ( state_count <= te_sm.num_states )
      .for each sm_state in sm_states
        .select one te_state related by sm_state->TE_STATE[R2037]
        .if ( te_state.number == state_count )
          .assign comment = "  /* row ${state_count}:  ${te_state.enumerator} (${te_state.Name}) */\n"
          .invoke r = CreateStateEventMatrixRow( sm_state, te_evts, state_count, num_events )
          .assign other_rows = ( other_rows + ",\n" ) + ( comment + r.body )
          .break for
        .end if
      .end for
      .assign state_count = state_count + 1
    .end while
    .include "${te_file.arc_path}/t.class.sem.matrix.c"
  .end if
.end function
.//
.//============================================================================
.// Create a row in the State Event Matrix (SEM) for a state model.
.//============================================================================
.function CreateStateEventMatrixRow
  .param inst_ref sm_state
  .param inst_ref_set te_evts
  .param integer order
  .param integer num_events
  .select any te_eq from instances of TE_EQ
  .assign event_number = 0
  .assign event_count = 0
  .assign row = ""
  .assign delimiter = ""
  .select any empty_sm_txn from instances of SM_TXN where ( false )
  .select any empty_sm_eign from instances of SM_EIGN where ( false )
  .// Here we use event_count and event_number, because we may skip events
  .// that are not used.  Soon there will be a reflexive on TE_EVT.
  .// Guard by limiting loop to 256 events.
  .while ( ( event_count < num_events ) and ( event_number < 256 ) )
    .assign cell = ""
    .assign found = false
    .for each te_evt in te_evts
      .if ( te_evt.Order == event_number )
        .assign found = true
        .assign sm_txn = empty_sm_txn
        .assign sm_eign = empty_sm_eign
        .if ( 0 == order )
          .// Deal with creation event transitions.
          .select one sm_txn related by te_evt->SM_EVT[R2036]->SM_SEVT[R525]->SM_LEVT[R526]->SM_CRTXN[R509]->SM_TXN[R507]
        .else
          .// Deal with normal transitions.
          .select any sm_seme related by te_evt->SM_EVT[R2036]->SM_SEVT[R525]->SM_SEME[R503] where ( selected.SMstt_ID == sm_state.SMstt_ID )
          .select one sm_nstxn related by sm_seme->SM_NSTXN[R504]
          .if ( not_empty sm_nstxn )
            .// NOTE:  To avoid problems with PE, we need the following to
            .// bypass metamodel issues when a PE and a local event both
            .// have transitions between the same state pairs.
            .select any sm_txn related by sm_state->SM_SM[R501]->SM_TXN[R505] where ( selected.Trans_ID == sm_nstxn.Trans_ID )
          .else
            .select one sm_eign related by sm_seme->SM_EIGN[R504]
          .end if
        .end if
        .if ( not_empty sm_txn )
          .select one next_te_state related by sm_txn->SM_STATE[R506]->TE_STATE[R2037]
          .select one txn_te_act related by sm_txn->SM_TAH[R530]->SM_AH[R513]->SM_ACT[R514]->TE_ACT[R2022]
          .if ( not_empty txn_te_act )
            .// We have a transition action.  Prepend number to cell.
            .assign cell = "(${txn_te_act.number}<<8) + "
          .end if
          .assign cell = ( delimiter + cell ) + next_te_state.enumerator
        .elif ( not_empty sm_eign )
          .assign cell = delimiter + te_eq.ignored
        .else
          .assign cell = delimiter + te_eq.cant_happen
        .end if
        .assign delimiter = ", "
        .break for
      .end if
    .end for
    .assign event_number = event_number + 1
    .if ( found )
      .assign event_count = event_count + 1
    .end if
    .assign row = row + cell
  .end while
  { ${row} }\
.end function
.//
.//============================================================================
.// Output the array of pointers that refer to the actions of the states.
.//============================================================================
.function CreateStateActionArray
  .param inst_ref te_c
  .param inst_ref sm_sm
  .select any te_file from instances of TE_FILE
  .select one te_sm related by sm_sm->TE_SM[R2043]
  .select many te_states related by sm_sm->SM_STATE[R501]->TE_STATE[R2037]
  .// Watch out for incomplete (or non-active) xtUML models.
  .assign state_space = te_sm.num_states + 1
  .assign state_names = ""
  .if ( te_sm.num_states > 0 )
    .assign delimiter = ","
    .assign state_action_rows = ""
    .assign state_count = 0
    .while ( state_count < te_sm.num_states )
      .if ( state_count == ( te_sm.num_states - 1 ) )
        .assign delimiter = ""
      .end if
      .for each te_state in te_states
        .if ( te_state.Order == state_count )
          .select one te_act related by te_state->SM_STATE[R2037]->SM_MOAH[R511]->SM_AH[R513]->SM_ACT[R514]->TE_ACT[R2022]
          .assign state_action_rows = state_action_rows + "    (${te_sm.action_type}) ${te_act.GeneratedName}${delimiter}  /* ${te_state.Name} */\n"
          .assign state_names = state_names + "    ""${te_state.Name}""${delimiter}\n"
          .break for
        .end if
      .end for
      .assign state_count = state_count + 1
    .end while
    .include "${te_file.arc_path}/t.class.sem.state_action_array.c"
  .end if
  .if ( te_c.StateTrace )
    .include "${te_file.arc_path}/t.class.sem.state_names.c"
  .end if
.end function
.//
.//============================================================================
.// Output the array of pointers that refer to the actions on the transitions.
.//============================================================================
.function CreateTransitionActionArray
  .param inst_ref sm_sm
  .select any te_file from instances of TE_FILE
  .select one te_sm related by sm_sm->TE_SM[R2043]
  .select many te_acts related by sm_sm->SM_TXN[R505]->SM_TAH[R530]->SM_AH[R513]->SM_ACT[R514]->TE_ACT[R2022]
  .assign num_te_acts = cardinality te_acts
  .if ( num_te_acts > 0 )
    .assign delimiter = ","
    .assign txn_action_rows = ""
    .for each te_act in te_acts
      .if ( last te_acts )
        .assign delimiter = ""
      .end if
      .assign txn_action_rows = txn_action_rows + "    (${te_sm.action_type}) ${te_act.GeneratedName}${delimiter}\n"
    .end for
    .include "${te_file.arc_path}/t.class.sem.txn_action_array.c"
  .end if
.end function
.//
.//===========================================================================
.// Output an event dispatcher for polymorphic event propagation.
.//===========================================================================
.function CreatePolymorphicEventDispatcher
  .param inst_ref o_obj
  .param inst_ref_set r_rels
  .//
  .select any te_eq from instances of TE_EQ
  .select any te_instance from instances of TE_INSTANCE
  .select any te_string from instances of TE_STRING
  .select any te_typemap from instances of TE_TYPEMAP
  .select one te_class related by o_obj->TE_CLASS[R2019]
  .if ( not_empty r_rels )
    .assign num_poly_rels = cardinality r_rels
    .if ( num_poly_rels == 1 )
  if ( 0 != GetIsPolymorphicEvent( event ) ) {
    .for each rel in r_rels
      .// for loop needed to get the one poly relationship.
      .invoke method_name = GetSuperTypePolymorphicEventMethodName( te_class, rel )
    ${method_name.result}( (${te_class.GeneratedName} *) instance, event );
    .end for
  }\
    .else
      .// Multidirectional subtyping
      .select one te_sm related by o_obj->SM_ISM[R518]->SM_SM[R517]->TE_SM[R2043]
  if ( 0 != GetIsPolymorphicEvent( event ) ) {
    /* Multidirectional subtyping hierarchy:  Pass PE down all active legs.  */
    ${te_eq.base_event_type} * copy;
      .for each rel in r_rels
        .invoke method_name = GetSuperTypePolymorphicEventMethodName( te_class, rel )
    /* Propagate event down R${rel.Numb}  */
    copy = Escher_AllocateOoaEvent();
    ${te_instance.module}${te_string.memmove}( copy, event, sizeof( ${te_sm.events_union} ) );
    ${method_name.result}( instance, copy );
    ${te_instance.module}${te_eq.delete}( copy );
      .end for
  }\
    .end if
  .end if
.end function
.//
.//===========================================================================
.// Ouput the routine that will dispatch events for a class.
.//===========================================================================
.function CreateInstanceStateModelEventDispatcher
  .param inst_ref te_c
  .param inst_ref o_obj
  .param boolean  gen_declaration
  .//
  .select any te_callout from instances of TE_CALLOUT
  .select any te_eq from instances of TE_EQ
  .select any te_file from instances of TE_FILE
  .select any te_instance from instances of TE_INSTANCE
  .select any te_prefix from instances of TE_PREFIX
  .select any te_trace from instances of TE_TRACE
  .select any te_target from instances of TE_TARGET
  .select any te_typemap from instances of TE_TYPEMAP
  .select one te_class related by o_obj->TE_CLASS[R2019]
  .select any polymorphic_event from instances of SM_PEVT
  .//
  .if ( gen_declaration )
    .include "${te_file.arc_path}/t.class.idispatch.h"
  .else
    .// Watch out for possibly incomplete models!
    .select one sm_sm related by o_obj->SM_ISM[R518]->SM_SM[R517]
    .select one te_sm related by sm_sm->TE_SM[R2043]
    .invoke poly_rels = GetPolymorphicRelationshipCollection( o_obj )
    .assign poly_rel_set = poly_rels.result
    .//
    .invoke r = AutoInitializeUniqueIDs( te_class, "i" )
    .assign init_uniques = r.body
    .invoke max_event = GetMaxEventInfo( o_obj, true )
    .invoke r = GetDomainTypeIDFromString( te_c.Name )
    .assign dom_id = r.result
    .invoke poly_dispatch = CreatePolymorphicEventDispatcher( o_obj, poly_rel_set )
    .assign poly_dispatcher = poly_dispatch.body
    .//
    .// Does this state model have any self-creation transitions?
    .assign can_self_create = false
    .select any sm_crtxn related by sm_sm->SM_EVT[R502]->SM_SEVT[R525]->SM_LEVT[R526]->SM_CRTXN[R509]
    .if ( not_empty sm_crtxn )
      .assign can_self_create = true
    .end if
    .//
    .// Does this state model have any self-deletion transitions?
    .assign can_self_delete = false
    .select many final_state_set related by sm_sm->SM_STATE[R501] where ( selected.Final != 0 )
    .select many te_states related by final_state_set->TE_STATE[R2037]
    .if ( not_empty te_states )
      .assign can_self_delete = true
    .end if
    .select any evt_cant_happen related by sm_sm->SM_STATE[R501]->SM_SEME[R503]->SM_CH[R504]
    .select any evt_ignored related by sm_sm->SM_STATE[R501]->SM_SEME[R503]->SM_EIGN[R504]
    .select any nlevt related by o_obj->SM_ISM[R518]->SM_SM[R517]->SM_EVT[R502]->SM_SEVT[R525]->SM_NLEVT[R526]
    .include "${te_file.arc_path}/t.class.idispatch.c"
  .end if
.end function
.//


Remove arc config

Remove arc config

@app
cojs

@json

# create a new session
post /session

# create/update/view a cell
post /cell
post /cell/:id
get /cell/:id

@tables

cells
  id *String
  ref **String