compile error fixes
git-svn-id: https://projects.brucker.ch/su4sml/svn/su4sml/trunk@7173 3260e6d1-4efc-4170-b0a7-36055960796d
This commit is contained in:
parent
093afd6030
commit
88ad63bd3f
|
@ -66,104 +66,36 @@ type modelTransformation = Rep_Core.transform_model * transformFlag list
|
|||
|
||||
|
||||
(* (JD) maybe not all of the following functions need to be exported.
|
||||
* e.g., generate_pairs, ...
|
||||
*)
|
||||
|
||||
val transformClassifiers_ext : Rep_Core.transform_model -> Rep.Model
|
||||
val transformClassifiersExt : Rep_Core.transform_model -> Rep.Model
|
||||
val transformClassifiers : Rep_Core.transform_model -> Rep.Classifier list
|
||||
val transformFile : string -> Rep.Model
|
||||
|
||||
(* transforms *)
|
||||
val transform_association_classes: Rep_Core.transform_model ->
|
||||
val transformAssociationClasses: Rep_Core.transform_model ->
|
||||
Rep_Core.transform_model (* split an association classe into a class and an association*)
|
||||
val transform_qualifiers : Rep_Core.transform_model -> Rep_Core.transform_model
|
||||
val transform_aggregation: Rep_Core.transform_model -> Rep_Core.transform_model
|
||||
val transform_n_ary_associations : Rep_Core.transform_model ->
|
||||
val transformQualifiers : Rep_Core.transform_model -> Rep_Core.transform_model
|
||||
val transformAggregation: Rep_Core.transform_model -> Rep_Core.transform_model
|
||||
val transformNAryAssociations : Rep_Core.transform_model ->
|
||||
Rep_Core.transform_model (* remove n-ary associations *)
|
||||
val transform_multiplicities : Rep_Core.transform_model ->
|
||||
val transformMultiplicities : Rep_Core.transform_model ->
|
||||
Rep_Core.transform_model (* remove multiplicities *)
|
||||
|
||||
(* helper functions *)
|
||||
(**
|
||||
* returns the path of an association end. The path of an association end
|
||||
* is <path_of_association>@[<name_of_aend>].
|
||||
* @params {aend}
|
||||
* @param aend association end
|
||||
* @return path of association end
|
||||
*)
|
||||
val path_of_aend : Rep_Core.associationend -> Rep_OclType.Path
|
||||
|
||||
val role_of_aend : Rep_Core.associationend -> string
|
||||
(**
|
||||
* returns the type of the classifier this association end belongs to.
|
||||
* @params {aend}
|
||||
* @param aend association end
|
||||
* @return type of the classifier at the association end
|
||||
*)
|
||||
val type_of_aend : Rep_Core.associationend -> Rep_OclType.OclType
|
||||
(**
|
||||
* returns the association this association end belongs to.
|
||||
* @params {aend}
|
||||
* @param aend association end
|
||||
* @return the path of the enclosing association
|
||||
*)
|
||||
val association_of_aend : Rep_Core.associationend -> Rep_OclType.Path
|
||||
(**
|
||||
* returns the name of the association end. The name of the association
|
||||
* end is the last part of the association end's path.
|
||||
* @params {aend}
|
||||
* @param aend association end
|
||||
* @return name of the association end as string.
|
||||
*)
|
||||
val name_of_aend : Rep_Core.associationend -> string
|
||||
(**
|
||||
* returns the list of specified multiplicities for this association end.
|
||||
* @params {aend}
|
||||
* @param aend association end
|
||||
* @return the list of multiplicities of this association end. If there are
|
||||
* no multiplicities, an empty list is returned.
|
||||
*)
|
||||
val multiplicities_of_aend : Rep_Core.associationend -> (int*int) list
|
||||
(**
|
||||
* returns the qualifying part of the (fully) qualified name.
|
||||
* @params {qualifiedName}
|
||||
* @param qualifiedName path denoting a name
|
||||
* @return all but the last part of qualifiedName
|
||||
*)
|
||||
val get_qualifier : Rep_OclType.Path -> Rep_OclType.Path
|
||||
|
||||
(**
|
||||
* Remove all multiplicities from the association
|
||||
* @params {assoc}
|
||||
* @param assoc association
|
||||
* @return assoc with all multiplicities removed
|
||||
*)
|
||||
val stripMultiplicities : Rep_Core.association -> Rep_Core.association
|
||||
val generate_pairs : 'a list -> ('a * 'a) list (* including symmetry *)
|
||||
val update_classifier_with_constraint : Rep_Core.constraint ->
|
||||
Rep_Core.Classifier -> Rep_Core.Classifier
|
||||
(* single: exactly 1 match *)
|
||||
val update_classifiers_single : Rep_Core.Classifier list -> Rep_OclType.OclType -> (Rep_Core.Classifier -> Rep_Core.Classifier) -> Rep_Core.Classifier list
|
||||
val updateClassifiersWithConstraints: Rep_Core.Classifier list ->
|
||||
Rep_OclType.OclType ->
|
||||
Rep_Core.constraint list ->
|
||||
Rep_Core.Classifier list
|
||||
val get_association : Rep_Core.association list -> Rep_OclType.Path ->
|
||||
Rep_Core.association
|
||||
val split_on_association: Rep_Core.association list -> Rep_OclType.Path ->
|
||||
Rep_Core.association * Rep_Core.association list
|
||||
(* only one of the below will remain *)
|
||||
val get_other_associationends: Rep_Core.association list -> Rep_OclType.Path -> Rep_OclType.OclType -> Rep_Core.associationend list
|
||||
val get_other_associationends_alt : Rep_Core.association list -> Rep_OclType.OclType -> Rep_OclType.Path -> Rep_Core.associationend list
|
||||
val get_associationends : Rep_Core.association list -> Rep_OclType.Path -> Rep_Core.associationend list
|
||||
val associationends_of : Rep_Core.association -> Rep_Core.associationend list
|
||||
|
||||
(* result: (Variable list , OCL expression for set intersection)*)
|
||||
val reachable_set : Rep_Core.associationend -> Rep_Core.associationend list -> (Rep_OclTerm.OclTerm list * Rep_OclTerm.OclTerm)
|
||||
val within_bounds : Rep_OclTerm.OclTerm -> (int*int) -> Rep_OclTerm.OclTerm
|
||||
val within_aend_multiplicities : Rep_Core.associationend -> Rep_Core.associationend list -> string -> Rep_Core.constraint
|
||||
val injective_constraint : Rep_OclType.Path -> Rep_OclType.OclType -> Rep_Core.associationend list -> string -> Rep_Core.constraint
|
||||
|
||||
exception NotYetImplemented of string
|
||||
exception InvalidArguments of string
|
||||
|
||||
|
@ -175,6 +107,9 @@ struct
|
|||
datatype transformFlag = BinaryAssociationsOnly
|
||||
type modelTransformation = Rep_Core.transform_model * transformFlag list
|
||||
-> Rep_Core.transform_model * transformFlag list
|
||||
|
||||
open List
|
||||
open ListPair
|
||||
open library
|
||||
open Transform_Library
|
||||
open Rep_OclTerm
|
||||
|
@ -182,6 +117,7 @@ open Rep_OclType
|
|||
open Rep_OclHelper
|
||||
open Rep_Core
|
||||
|
||||
|
||||
infix |>>
|
||||
fun (x |>> f) = (f x)
|
||||
|
||||
|
@ -194,130 +130,6 @@ exception InvalidArguments of string
|
|||
§ ***********************************)
|
||||
val triv_expr = Rep_OclTerm.Literal ("true",Rep_OclType.Boolean)
|
||||
|
||||
(* (JD) -> Rep_OclType? *)
|
||||
fun get_short_name (path:Path):string =
|
||||
List.last path
|
||||
|
||||
fun stripMultiplicities ({name,aends,aclass}:association):association =
|
||||
let
|
||||
fun handleAend {name,aend_type,multiplicity,visibility,
|
||||
ordered,init} =
|
||||
{name=name,
|
||||
aend_type=aend_type,
|
||||
multiplicity=[],
|
||||
visibility=visibility,
|
||||
ordered=ordered,
|
||||
init=init}
|
||||
in
|
||||
{name = name,
|
||||
aends = map handleAend aends,
|
||||
aclass = aclass}
|
||||
end
|
||||
|
||||
fun generate_pairs [] =
|
||||
error "in generate_pairs: argument list is empty" (* or simply return []? *)
|
||||
| generate_pairs [a] =
|
||||
[(a,a)]
|
||||
| generate_pairs [a,b] =
|
||||
(* not necessary *)
|
||||
[(a,b),(b,a)]
|
||||
| generate_pairs (x::xs) =
|
||||
let
|
||||
val pairs = map (fn a => (x,a)) xs
|
||||
val rev_pairs = map (fn a => (a,x)) xs
|
||||
in
|
||||
pairs@rev_pairs@(generate_pairs xs)
|
||||
end
|
||||
|
||||
fun update_classifier_with_constraint constraint (Class{name,parent,attributes,
|
||||
operations,associations,invariant,stereotypes,interfaces,thyname,
|
||||
activity_graphs}) =
|
||||
Class {name = name,
|
||||
parent = parent,
|
||||
attributes = attributes,
|
||||
operations = operations,
|
||||
associations = associations,
|
||||
invariant = constraint::invariant,
|
||||
stereotypes = stereotypes,
|
||||
interfaces = interfaces,
|
||||
thyname = thyname,
|
||||
activity_graphs = activity_graphs}
|
||||
| update_classifier_with_constraint constraint (AssociationClass {name,parent,
|
||||
attributes,operations,associations,association,invariant,stereotypes,
|
||||
interfaces,thyname,activity_graphs}) =
|
||||
AssociationClass {name = name,
|
||||
parent = parent,
|
||||
attributes = attributes,
|
||||
operations = operations,
|
||||
associations = associations,
|
||||
association = association,
|
||||
invariant = constraint::invariant,
|
||||
stereotypes = stereotypes,
|
||||
interfaces = interfaces,
|
||||
thyname = thyname,
|
||||
activity_graphs = activity_graphs}
|
||||
| update_classifier_with_constraint constraint (Interface {name,parents,
|
||||
operations,stereotypes,invariant,thyname}) =
|
||||
Interface {name=name,
|
||||
parents=parents,
|
||||
operations=operations,
|
||||
stereotypes=stereotypes,
|
||||
invariant=constraint::invariant,
|
||||
thyname=thyname}
|
||||
| update_classifier_with_constraint constraint (Enumeration {name,parent,
|
||||
operations,literals,invariant,stereotypes,interfaces,thyname}) =
|
||||
Enumeration {name = name,
|
||||
parent = parent,
|
||||
operations = operations,
|
||||
literals=literals,
|
||||
invariant = constraint::invariant,
|
||||
stereotypes = stereotypes,
|
||||
interfaces = interfaces,
|
||||
thyname = thyname}
|
||||
| update_classifier_with_constraint constraint (Primitive {name,parent,
|
||||
operations,associations,invariant,stereotypes,interfaces,thyname}) =
|
||||
Primitive{name = name,
|
||||
parent = parent,
|
||||
operations = operations,
|
||||
associations = associations,
|
||||
invariant = constraint::invariant,
|
||||
stereotypes = stereotypes,
|
||||
interfaces = interfaces,
|
||||
thyname = thyname}
|
||||
| update_classifier_with_constraint constraint (Template {parameter,
|
||||
classifier}) =
|
||||
Template{parameter=parameter,
|
||||
classifier = update_classifier_with_constraint
|
||||
constraint classifier} (* sensible? *)
|
||||
|
||||
fun update_classifiers_single (all_classifiers:Classifier list)
|
||||
(classifier:OclType) (update:Classifier -> Classifier) :Classifier list=
|
||||
let
|
||||
val (match,rest) = List.partition
|
||||
(fn (Class {name,...}) => name=classifier
|
||||
| (AssociationClass {name,...}) => name=classifier
|
||||
| (Interface {name,...}) => name=classifier
|
||||
| (Enumeration {name,...}) => name=classifier
|
||||
| (Primitive {name,...}) => name=classifier
|
||||
| _ => false ) all_classifiers
|
||||
in
|
||||
case match of
|
||||
[x] => (update x)::rest
|
||||
| [] => error "in update_classifiers_single: no match found"
|
||||
| _ => error "in update_classifiers_single: more than 1 match found"
|
||||
end
|
||||
|
||||
fun update_classifiers_with_constraints (all_classifiers:Classifier list)
|
||||
(classifier:OclType) (con::constraints:constraint list) :Classifier list =
|
||||
let
|
||||
val modified_clsses = update_classifiers_single all_classifiers classifier
|
||||
(update_classifier_with_constraint con)
|
||||
in
|
||||
update_classifiers_with_constraints modified_clsses classifier
|
||||
constraints
|
||||
end
|
||||
| update_classifiers_with_constraints all_classifiers _ [] = all_classifiers
|
||||
|
||||
fun get_association (all_assocs: Rep_Core.association list) (assoc_path:Path):
|
||||
association =
|
||||
let
|
||||
|
@ -362,100 +174,6 @@ fun associationends_of (assoc:association):associationend list =
|
|||
#aends assoc
|
||||
end
|
||||
|
||||
fun reachable_set (_:associationend) ([]:associationend list) = error "rep_transform.get_reachable_set: empty source list"
|
||||
| reachable_set (target:associationend) ([source]:associationend list) =
|
||||
let
|
||||
val src_var = Variable(name_of_aend source ,type_of_aend source)
|
||||
in
|
||||
([src_var], ocl_aendcall src_var (path_of_aend target) (type_of_aend target))
|
||||
end
|
||||
| reachable_set (target:associationend) ((source::rest):associationend list) =
|
||||
let
|
||||
val (old_vars,intermediate) = reachable_set target rest
|
||||
val src_var = Variable(name_of_aend source ,type_of_aend source)
|
||||
val new_set = ocl_aendcall src_var (path_of_aend target) (type_of_aend target)
|
||||
in
|
||||
(src_var::old_vars ,ocl_intersection_set new_set intermediate)
|
||||
end
|
||||
|
||||
|
||||
fun within_bounds (set:Rep_OclTerm.OclTerm) ((lower,upper):int*int):Rep_OclTerm.OclTerm =
|
||||
let
|
||||
val size = ocl_size set
|
||||
val lower_lit = Literal (Int.toString lower,Integer)
|
||||
val upper_lit = Literal (Int.toString upper,Integer)
|
||||
val lower_bound = ocl_geq size lower_lit
|
||||
val upper_bound = ocl_leq size upper_lit
|
||||
in
|
||||
ocl_and lower_bound upper_bound
|
||||
end
|
||||
|
||||
fun withinAendMultiplicities targetAend sourceAends name =
|
||||
let
|
||||
val _ = trace function_calls "withinAendMultiplicities\n"
|
||||
val tgt_multiplicities = multiplicities_of_aend target
|
||||
val tgt_name = name_of_aend target
|
||||
val tgt_type = type_of_aend target
|
||||
val (variables,set) = reachable_set target sources
|
||||
val constr_body = ocl_or_all (map (within_bounds set) tgt_multiplicities)
|
||||
val tgt_variable = Variable(tgt_name,tgt_type)
|
||||
val allInstances = ocl_allInstances tgt_variable
|
||||
val constr_complete = ocl_forAll allInstances variables constr_body
|
||||
val constraint = (SOME name,constr_complete)
|
||||
in
|
||||
constraint
|
||||
end
|
||||
|
||||
fun injective_constraint (source_path:Path) (source_type:OclType) (targets:associationend list) (name:string):constraint =
|
||||
let
|
||||
val source_name = get_short_name source_path
|
||||
val src_var = Variable(source_name,source_type)
|
||||
fun role_bounds src_var aend =
|
||||
let
|
||||
val name = path_of_aend aend
|
||||
val aend_type = type_of_aend aend
|
||||
val set = ocl_aendcall src_var name aend_type
|
||||
val size = ocl_size set
|
||||
val bounds = ocl_eq size (Literal("1",Integer))
|
||||
in
|
||||
bounds
|
||||
end
|
||||
fun role_equals src_var src2_var aend =
|
||||
let
|
||||
val name = path_of_aend aend
|
||||
val aend_type = type_of_aend aend
|
||||
val set = ocl_aendcall src_var name aend_type
|
||||
val size = ocl_size set
|
||||
val match = ocl_eq size (Literal("1",Integer))
|
||||
in
|
||||
match
|
||||
end
|
||||
val roles = map (role_bounds src_var) targets
|
||||
val roles_part = ocl_and_all roles
|
||||
val allInstances = ocl_allInstances src_var
|
||||
val src_var2 = Variable(source_name^"2",source_type)
|
||||
val matches = map (role_equals src_var src_var2) targets
|
||||
val matches_anded = ocl_and_all roles
|
||||
val matches_equal = ocl_eq src_var src_var2
|
||||
val matches_imp = ocl_implies matches_anded matches_equal
|
||||
val allInstances2 = ocl_allInstances src_var2
|
||||
val matches_part = ocl_forAll allInstances2 [src_var2] matches_imp
|
||||
val constr_body = ocl_and roles_part matches_part
|
||||
val constr_complete = ocl_forAll allInstances [src_var] constr_body
|
||||
in
|
||||
(SOME name,constr_complete)
|
||||
end
|
||||
|
||||
fun split_on_association (associations:association list) (path:Path): (association * association list) =
|
||||
let
|
||||
fun belonging_association tgt {name,aends,aclass} = tgt = name
|
||||
val ([assoc],others) = List.partition (belonging_association path)
|
||||
associations
|
||||
in
|
||||
(assoc, others)
|
||||
end
|
||||
|
||||
|
||||
(****************************
|
||||
******** Transforms ********
|
||||
****************************)
|
||||
|
@ -467,7 +185,7 @@ fun split_on_association (associations:association list) (path:Path): (associati
|
|||
* generates: constraint, AssociationClass
|
||||
* removes: qualifier
|
||||
*)
|
||||
fun transform_qualifiers ((all_classifiers,all_associations):transform_model):
|
||||
fun transformQualifiers ((all_classifiers,all_associations):transform_model):
|
||||
transform_model =
|
||||
(all_classifiers,all_associations) (*dummy*)
|
||||
|
||||
|
@ -476,8 +194,8 @@ fun transform_qualifiers ((all_classifiers,all_associations):transform_model):
|
|||
* generates: constraint
|
||||
* removes: aggregation
|
||||
*)
|
||||
fun transform_aggregation ((all_classifiers,all_associations):transform_model):transform_model =
|
||||
(all_classifiers,all_associations) (*dummy*)
|
||||
fun transformAggregation (allClassifiers,allAssociations) =
|
||||
(allClassifiers,allAssociations) (*dummy*)
|
||||
|
||||
|
||||
(*****************************************************************************)
|
||||
|
@ -499,20 +217,85 @@ fun transform_aggregation ((all_classifiers,all_associations):transform_model):t
|
|||
*)
|
||||
fun transformAssociationClassIntoClass (AssociationClass
|
||||
{name,parent,attributes,operations,
|
||||
associations,association,
|
||||
associations,association,
|
||||
invariant,stereotypes,interfaces,
|
||||
thyname,activity_graphs}) =
|
||||
(trace function_calls "transformAssociationClassIntoClass\n",
|
||||
Class { name = name,
|
||||
parent = parent,
|
||||
attributes = attributes,
|
||||
operations = operations,
|
||||
associations = associations,
|
||||
invariant = constraint::invariant,
|
||||
stereotypes = stereotypes,
|
||||
interfaces = interfaces,
|
||||
thyname = thyname,
|
||||
activity_graphs = activity_graphs})
|
||||
parent = parent,
|
||||
attributes = attributes,
|
||||
operations = operations,
|
||||
associations = associations,
|
||||
invariant = invariant,
|
||||
stereotypes = stereotypes,
|
||||
interfaces = interfaces,
|
||||
thyname = thyname,
|
||||
activity_graphs = activity_graphs})
|
||||
|
||||
(**
|
||||
* Process an association: add the dummy class, generate the matching-
|
||||
* constraint and update the classifiers with that constraint.
|
||||
*)
|
||||
fun generalTransfromNAryAssociation dummy (association as {name,aends,
|
||||
aclass=NONE},
|
||||
(classifiers,processedAssocs)) =
|
||||
let
|
||||
val _ = trace function_calls "transformNAryAssociation\n"
|
||||
fun modifyClassifier ((assocs,classifier),classifiers) =
|
||||
let
|
||||
val ([cls],rem) = partition (fn x => name_of x = name_of
|
||||
classifier)
|
||||
classifiers
|
||||
in
|
||||
modifyAssociationsOfClassifier assocs [association] cls ::rem
|
||||
end
|
||||
|
||||
fun consistency [] refer [] [] [] = []
|
||||
| consistency (source::xs) refer (selfAend::ys) (roles::zs)
|
||||
(refRoles::us) =
|
||||
consistencyOclConstraint source refer selfAend roles refRoles ::
|
||||
(consistency xs refer ys zs us)
|
||||
|
||||
fun addOcl ((classifier,ocls), classifiers) =
|
||||
let
|
||||
val ([cls],rem) = partition (fn x => classifier = x) classifiers
|
||||
in
|
||||
addInvariants ocls cls :: rem
|
||||
end
|
||||
|
||||
(* extract participants/members and form associations *)
|
||||
val (assocMembers,rem) = matchClassifiersAtAend aends classifiers
|
||||
val (binaryAssocs,oppRefAends) = binaryAssociations dummy assocMembers
|
||||
aends
|
||||
val (clsses,roleNames, oppAends, splitAssocs) = splitNAryAssociation
|
||||
association
|
||||
assocMembers
|
||||
val assocMemberPairs = zip (map (fn x => [x]) binaryAssocs,assocMembers)
|
||||
val splitMemberPairs = zip (splitAssocs,assocMembers)
|
||||
|
||||
(* update association membership info in classifiers *)
|
||||
val modifiedClassifiers = foldl modifyClassifier classifiers
|
||||
(assocMemberPairs @ splitMemberPairs)
|
||||
val dummy = modifyAssociationsOfClassifier binaryAssocs [] dummy
|
||||
|
||||
(* generate and add OCL constraints *)
|
||||
val uniquenessOCL = uniquenessOclConstraint dummy binaryAssocs
|
||||
val selfAends = matchAends oppRefAends (zip (clsses,roleNames))
|
||||
val refRoles = map (matchAends oppRefAends) oppAends
|
||||
val namedConsistencyOCLs = consistency clsses dummy selfAends oppAends
|
||||
refRoles
|
||||
val multiplicitiesOCL =
|
||||
multiplicityOclConstraint dummy (map multiplicity_of_aend aends)
|
||||
oppRefAends
|
||||
val dummy = addInvariants (uniquenessOCL::multiplicitiesOCL) dummy
|
||||
val modifiedClassifiers = foldl addOcl modifiedClassifiers
|
||||
namedConsistencyOCLs
|
||||
|
||||
(* update references to removed associations *)
|
||||
(*val modifiedClassifiers = TODO *)
|
||||
in
|
||||
(dummy::modifiedClassifiers, binaryAssocs@splitAssocs@processedAssocs)
|
||||
end
|
||||
|
||||
(**
|
||||
* Transform an AssociationClass into a Class and an Association
|
||||
|
@ -529,13 +312,15 @@ fun transformAssociationClasses (allClassifiers,allAssociations) =
|
|||
val ([dummy],rem) = List.partition (fn x => name_of x = aClass)
|
||||
classifiers
|
||||
in
|
||||
generalTransfromNAryAssociation dummy ({name=name,aends=aends,aclass=NONE},
|
||||
generalTransfromNAryAssociation dummy ({name=name,aends=aends,
|
||||
aclass=NONE},
|
||||
(rem,procAssocs))
|
||||
end
|
||||
|
||||
fun stripAcAssoc ({name,aends,aclass=SOME aClass},classifiers) =
|
||||
let
|
||||
val (ac,rem) = List.partition (fn x => name_of x = aClass) classifiers
|
||||
val (ac,rem) = List.partition (fn x => name_of x = aClass)
|
||||
classifiers
|
||||
in
|
||||
transformAssociationClassIntoClass ac ::rem
|
||||
end
|
||||
|
@ -548,77 +333,6 @@ fun transformAssociationClasses (allClassifiers,allAssociations) =
|
|||
(modifiedClassifiers,modifiedAssociations@rem)
|
||||
end
|
||||
|
||||
fun transformNAryAssociation (association,(classifiers,procAssocs)) =
|
||||
generalTransfromNAryAssociation (newDummyClass o package_of_association
|
||||
association)
|
||||
(association,(classifiers,procAssocs))
|
||||
|
||||
(**
|
||||
* Process an association: add the dummy class, generate the matching-
|
||||
* constraint and update the classifiers with that constraint.
|
||||
*)
|
||||
fun generalTransfromNAryAssociation dummy (association as {name,aends,NONE},
|
||||
(classifiers,processedAssocs)) =
|
||||
let
|
||||
val _ = trace function_calls "transformNAryAssociation\n"
|
||||
fun modifyClassifiers ((assoc,classifier),classifiers) =
|
||||
let
|
||||
val ([cls],rem) = partition (fn x => name_of x = name_of
|
||||
classifier)
|
||||
classifiers
|
||||
in
|
||||
modifyAssociationsOfClassifier [assoc] [association] cls ::rem
|
||||
end
|
||||
|
||||
fun consistency [] ref [] [] [] = []
|
||||
| consistency (source::xs) ref (selfAend::ys) (roles::zs)
|
||||
(refRoles::us) =
|
||||
consistencyOclConstraint source ref selfAend roles refRoles ::
|
||||
(consistency xs ref ys zs us)
|
||||
|
||||
fun addOcl ((classifier,ocls), classifiers) =
|
||||
let
|
||||
val ([cls],rem) = partition (fn x => classifier = x) classifiers
|
||||
in
|
||||
addInvariants ocls cls :: rem
|
||||
end
|
||||
|
||||
fun matchClassifiers oppRefAends (cls,role) =
|
||||
matchClassifier oppRefAends cls role
|
||||
|
||||
(* extract participants/members and form associations *)
|
||||
val (assocMembers,rem) = matchClassifierAtAend classifiers aends
|
||||
val (binaryAssocs,oppRefAends) = binaryAssociations dummy assocMembers
|
||||
aends
|
||||
val (clsses,roleNames, oppAends, splitAssocs) = splitNAryAssociation
|
||||
association
|
||||
assocMembers
|
||||
val assocMemberPairs = zip binaryAssocs assocMembers
|
||||
val splitMemberPairs = zip splitAssocs assocMembers
|
||||
|
||||
(* update association membership info in classifiers *)
|
||||
val modifiedClassifiers = foldl modifyClassifiers classifiers
|
||||
(assocMemberPairs@splitMemeberPairs)
|
||||
val dummy = modifyAssociationsOfClassifier binaryAssocs [] dummy
|
||||
|
||||
(* generate and add OCL constraints *)
|
||||
val uniquenessOCL = uniquenessOclConstraint dummy binaryAssocs
|
||||
val selfAends = matchClassifiers oppRefAends (zip clsses roleNames)
|
||||
val refRoles = map (matchAends oppRefAends) oppAends
|
||||
val namedConsistencyOCLs = consistency clsses dummy selfAends oppAends
|
||||
refRoles
|
||||
val multiplicitiesOCL =
|
||||
multiplicityOclConstraint dummy (map multiplicity_of_aend aends)
|
||||
binaryAssocs
|
||||
val dummy = addInvariants (uniquenessOCL::multiplicitiesOCL) dummy
|
||||
val modifiedClassifiers = foldl addOcl modifiedClassifiers
|
||||
namedConsistencyOCLs
|
||||
|
||||
(* update references to removed associations *)
|
||||
(*val modifiedClassifiers = TODO *)
|
||||
in
|
||||
(dummy::modifiedClassifiers, binaryAssocs@splitAssocs@processedAssocs)
|
||||
end
|
||||
|
||||
(**
|
||||
* We need OCL constraints and an additional dummy class to handle the broken
|
||||
|
@ -634,6 +348,11 @@ fun generalTransfromNAryAssociation dummy (association as {name,aends,NONE},
|
|||
fun transformNAryAssociations (allClassifiers,allAssociations) =
|
||||
let
|
||||
val _ = trace function_calls "transform_n_ary_associations\n"
|
||||
fun transformNAryAssociation (association,(classifiers,procAssocs)) =
|
||||
generalTransfromNAryAssociation
|
||||
(newDummyClass (package_of_association association))
|
||||
(association,(classifiers,procAssocs))
|
||||
|
||||
val (nAryAssocs,rem) = partition isPureNAryAssoc allAssociations
|
||||
val (modifiedClassifiers,modifiedAssociations) =
|
||||
foldl transformNAryAssociation (allClassifiers,[]) nAryAssocs
|
||||
|
@ -672,47 +391,48 @@ fun transformMultiplicities (allClassifiers,allAssociations) =
|
|||
(SOME name, term)
|
||||
end
|
||||
|
||||
fun addMultiplicityConstraints (assoc as {name,aends=[a,b],NONE},
|
||||
fun addMultiplicityConstraints (assoc as {name,aends=[a,b],aclass=NONE},
|
||||
localClassifiers) =
|
||||
let
|
||||
val _ = trace function_calls "addMultiplicityConstraints\n"
|
||||
val aType = type_of_aend a
|
||||
val bType = type_of_aend b
|
||||
val _ = trace function_calls "addMultiplicityConstraints\n"
|
||||
val aType = type_of_aend a
|
||||
val bType = type_of_aend b
|
||||
val aPath = path_of_aend a
|
||||
val bPath = path_of_aend b
|
||||
val aName = name_of_aend a
|
||||
val bName = name_of_aend b
|
||||
val aConstrName = "BinaryMultiplicity"^a_name
|
||||
val bConstrName = "BinaryMultiplicity"^b_name
|
||||
val modifiedTmp =
|
||||
val aName = name_of_aend a
|
||||
val bName = name_of_aend b
|
||||
val aConstrName = "BinaryMultiplicity"^aName
|
||||
val bConstrName = "BinaryMultiplicity"^bName
|
||||
val modifiedTmp =
|
||||
(case (multiplicities_of_aend a) of
|
||||
[] => localClassifiers
|
||||
| multis =>
|
||||
let
|
||||
val aConstraint = binaryConstraint aType bType bPath
|
||||
val aConstraint = binaryConstraint aType bType bPath
|
||||
multis aConstrName
|
||||
in
|
||||
updateClassifiersWithConstraints classifiers aType
|
||||
in
|
||||
updateClassifiersWithConstraints localClassifiers aType
|
||||
[aConstraint]
|
||||
end)
|
||||
val modifiedClassifiers =
|
||||
end)
|
||||
val modifiedClassifiers =
|
||||
(case (multiplicities_of_aend b) of
|
||||
[] => modifiedTmp
|
||||
| multis =>
|
||||
let
|
||||
val bConstraint = binaryConstraint bType aType aPath
|
||||
let
|
||||
val bConstraint = binaryConstraint bType aType aPath
|
||||
multis bConstrName
|
||||
in
|
||||
updateClassifiersWithConstraints modifiedTmp bType
|
||||
in
|
||||
updateClassifiersWithConstraints modifiedTmp bType
|
||||
[bConstraint]
|
||||
end)
|
||||
in
|
||||
modifiedClassifiers
|
||||
end
|
||||
|
||||
end)
|
||||
in
|
||||
modifiedClassifiers
|
||||
end
|
||||
|
||||
(* filter the valid associations *)
|
||||
val (binaryAssociations,rem) = partition isPureBinAssoc allAssociations
|
||||
|
||||
val (binaryAssociations,rem) = List.partition isPureBinAssoc
|
||||
allAssociations
|
||||
|
||||
(* add the constraints to the classifiers *)
|
||||
val modifiedClassifiers = foldl addMultiplicityConstraints
|
||||
allClassifiers binaryAssociations
|
||||
|
@ -745,7 +465,7 @@ fun transformClassifiersExt (model:Rep_Core.transform_model):Rep_Core.transform_
|
|||
transformNAryAssociations
|
||||
|
||||
fun transformClassifiers (model:transform_model):Rep.Classifier list =
|
||||
fst (transformClassifiers_ext model) (* return classifiers *)
|
||||
fst (transformClassifiersExt model) (* return classifiers *)
|
||||
|
||||
|
||||
(**
|
||||
|
@ -753,7 +473,8 @@ fun transformClassifiers (model:transform_model):Rep.Classifier list =
|
|||
* @return a list of rep classifiers, or nil in case of problems
|
||||
*)
|
||||
fun transformFile f:transform_model = (info ("opening "^f);
|
||||
(normalize_ext o transformClassifiers_ext o RepParser.transformXMI_ext o XmiParser.readFile) f)
|
||||
(normalize_ext o transformClassifiersExt o
|
||||
RepParser.transformXMI_ext o XmiParser.readFile) f)
|
||||
(* handle ex as (IllFormed msg) => raise ex *)
|
||||
|
||||
exception FileNotFound of string
|
||||
|
|
|
@ -18,8 +18,14 @@ val uniquenessOclConstraint : Rep_Core.Classifier ->
|
|||
* @params {source,multis,binaryAssocs}
|
||||
*)
|
||||
val multiplicityOclConstraint: Rep_Core.Classifier -> (int*int) list list ->
|
||||
Rep_Core.association list ->
|
||||
Rep_Core.associationend list ->
|
||||
Rep_Core.constraint list
|
||||
val consistencyOclConstraint: Rep_Core.Classifier ->
|
||||
Rep_Core.Classifier ->
|
||||
Rep_Core.associationend ->
|
||||
Rep_Core.associationend list ->
|
||||
Rep_Core.associationend list ->
|
||||
(Rep_Core.Classifier * Rep_Core.constraint list)
|
||||
|
||||
(**
|
||||
* @params {association,assocMembers}
|
||||
|
@ -60,9 +66,14 @@ val matchAends: Rep_Core.associationend list ->
|
|||
(**
|
||||
*
|
||||
*)
|
||||
val matchClassifiers: Rep_Core.associationend list ->
|
||||
(Rep_Core.Classifier * string) list
|
||||
-> Rep_Core.associationend list
|
||||
val matchAendsAtClassifier: Rep_Core.associationend list ->
|
||||
(Rep_Core.Classifier * string) list
|
||||
-> Rep_Core.associationend list
|
||||
|
||||
val matchClassifiersAtAend: Rep_Core.associationend list ->
|
||||
Rep_Core.Classifier list ->
|
||||
(Rep_Core.Classifier list *
|
||||
Rep_Core.Classifier list )
|
||||
|
||||
(**
|
||||
* Form binary associations between
|
||||
|
@ -102,12 +113,77 @@ val isPureNAryAssoc: Rep_Core.association -> bool
|
|||
*)
|
||||
val isPureBinAssoc : Rep_Core.association -> bool
|
||||
|
||||
(**
|
||||
* returns the path of an association end. The path of an association end
|
||||
* is <path_of_association>@[<name_of_aend>].
|
||||
* @params {aend}
|
||||
* @param aend association end
|
||||
* @return path of association end
|
||||
*)
|
||||
val path_of_aend : Rep_Core.associationend -> Rep_OclType.Path
|
||||
|
||||
val role_of_aend : Rep_Core.associationend -> string
|
||||
(**
|
||||
* returns the type of the classifier this association end belongs to.
|
||||
* @params {aend}
|
||||
* @param aend association end
|
||||
* @return type of the classifier at the association end
|
||||
*)
|
||||
val type_of_aend : Rep_Core.associationend -> Rep_OclType.OclType
|
||||
(**
|
||||
* returns the association this association end belongs to.
|
||||
* @params {aend}
|
||||
* @param aend association end
|
||||
* @return the path of the enclosing association
|
||||
*)
|
||||
val association_of_aend : Rep_Core.associationend -> Rep_OclType.Path
|
||||
(**
|
||||
* returns the name of the association end. The name of the association
|
||||
* end is the last part of the association end's path.
|
||||
* @params {aend}
|
||||
* @param aend association end
|
||||
* @return name of the association end as string.
|
||||
*)
|
||||
val name_of_aend : Rep_Core.associationend -> string
|
||||
(**
|
||||
* returns the list of specified multiplicities for this association end.
|
||||
* @params {aend}
|
||||
* @param aend association end
|
||||
* @return the list of multiplicities of this association end. If there are
|
||||
* no multiplicities, an empty list is returned.
|
||||
*)
|
||||
val multiplicities_of_aend : Rep_Core.associationend -> (int*int) list
|
||||
|
||||
(**
|
||||
* Remove all multiplicities from the association
|
||||
* @params {assoc}
|
||||
* @param assoc association
|
||||
* @return assoc with all multiplicities removed
|
||||
*)
|
||||
val stripMultiplicities : Rep_Core.association -> Rep_Core.association
|
||||
(* result: (Variable list , OCL expression for set intersection)*)
|
||||
val reachableSet : Rep_Core.associationend -> Rep_Core.associationend list -> (Rep_OclTerm.OclTerm list * Rep_OclTerm.OclTerm)
|
||||
|
||||
|
||||
|
||||
val modifyAssociationsOfClassifier: Rep_Core.association list ->
|
||||
Rep_Core.association list ->
|
||||
Rep_Core.Classifier -> Rep_Core.Classifier
|
||||
|
||||
|
||||
val withinBounds : Rep_OclTerm.OclTerm -> (int*int) -> Rep_OclTerm.OclTerm
|
||||
val withinAendMultiplicities : Rep_Core.associationend -> Rep_Core.associationend list -> string -> Rep_Core.constraint
|
||||
val injectiveConstraint : Rep_OclType.Path -> Rep_OclType.OclType -> Rep_Core.associationend list -> string -> Rep_Core.constraint
|
||||
val updateClassifiersWithConstraints: Rep_Core.Classifier list ->
|
||||
Rep_OclType.OclType ->
|
||||
Rep_Core.constraint list ->
|
||||
Rep_Core.Classifier list
|
||||
|
||||
|
||||
|
||||
val uid: int ref
|
||||
|
||||
val path_of_aend: Rep_Core.associationend -> Rep_OclType.Path
|
||||
val role_of_aend: Rep_Core.associationend -> string
|
||||
val type_of_aend: Rep_Core.associationend -> Rep_OclType.OclType
|
||||
val association_of_aend: Rep_Core.associationend -> Rep_OclType.Path
|
||||
val multiplicity_of_aend: Rep_Core.associationend -> (int * int) list
|
||||
val package_of_aend: Rep_Core.associationend -> Rep_OclType.Path
|
||||
val name_of_association: Rep_Core.association -> Rep_OclType.Path
|
||||
val package_of_association: Rep_Core.association -> Rep_OclType.Path
|
||||
|
@ -124,11 +200,8 @@ structure Transform_Library:TRANSFORM_LIBRARY =
|
|||
struct
|
||||
|
||||
open library
|
||||
open ListPair
|
||||
open List
|
||||
open StringHandling
|
||||
open Rep_OclTerm
|
||||
open Rep_OclType
|
||||
open Rep_OclHelper
|
||||
open Rep_Core
|
||||
|
||||
|
@ -138,31 +211,56 @@ val uid = ref 0
|
|||
|
||||
fun nextUid () = (uid := !uid + 1; "_S"^(Int.toString (!uid)))
|
||||
|
||||
fun get_short_name (path:Path):string =
|
||||
List.last path
|
||||
|
||||
fun stripMultiplicities ({name,aends,aclass}:association):association =
|
||||
let
|
||||
fun handleAend {name,aend_type,multiplicity,visibility,
|
||||
ordered,init} =
|
||||
{name=name,
|
||||
aend_type=aend_type,
|
||||
multiplicity=[],
|
||||
visibility=visibility,
|
||||
ordered=ordered,
|
||||
init=init}
|
||||
in
|
||||
{name = name,
|
||||
aends = map handleAend aends,
|
||||
aclass = aclass}
|
||||
end
|
||||
|
||||
fun multiplicity_of_aend ({aend_type,multiplicity,...}:associationend) =
|
||||
multiplicity
|
||||
|
||||
(* (JD) -> Rep_Core? *)
|
||||
fun path_of_aend {name,aend_type,...} = name
|
||||
fun path_of_aend ({name,aend_type,...}:associationend) = name
|
||||
fun name_of_aend ({name,aend_type,...}:associationend) =
|
||||
short_name_of_path name
|
||||
|
||||
fun role_of_aend {name,aend_type,...} = List.last name
|
||||
fun role_of_aend ({name,aend_type,...}:associationend) = List.last name
|
||||
|
||||
(* (JD) -> Rep_Core? *)
|
||||
fun type_of_aend {name,aend_type,...} = aend_type
|
||||
fun type_of_aend ({name,aend_type,...}:associationend) = aend_type
|
||||
|
||||
(* (JD) -> Rep_Core? *)
|
||||
fun association_of_aend {name,aend_type,...} =
|
||||
fun association_of_aend ({name,aend_type,...}:associationend) =
|
||||
List.take(name, (List.length name)-1)
|
||||
|
||||
fun package_of_aend {name,aend_type,...} =
|
||||
fun package_of_aend ({name,aend_type,...}:associationend) =
|
||||
List.take(name, List.length name - 2)
|
||||
|
||||
fun name_of_association {name,aends,aclass} = name
|
||||
fun name_of_association ({name,aends,aclass}:association) = name
|
||||
|
||||
fun package_of_association {name,aends,aclass} =
|
||||
fun package_of_association ({name,aends,aclass}:association) =
|
||||
List.take(name, List.length name - 1)
|
||||
|
||||
(* (JD) -> Rep_Core? *)
|
||||
fun multiplicities_of_aend {aend_type,multiplicity,...} = multiplicity
|
||||
fun multiplicities_of_aend ({aend_type,multiplicity,...}:associationend) =
|
||||
multiplicity
|
||||
|
||||
fun short_name_of_aend {name,aend_type,...} = List.last name
|
||||
fun short_name_of_aend ({name,aend_type,...}:associationend) =
|
||||
short_name_of_path name
|
||||
|
||||
|
||||
fun quantifyForAll variables body =
|
||||
|
@ -213,7 +311,103 @@ fun removeAssociations oldAssocs associations =
|
|||
associations (* FIXME *)
|
||||
end
|
||||
|
||||
fun modifyAssociationsOfClassifier newAssociations oldAssociations
|
||||
fun updateClassifiersWithConstraints classifiers oclType constraints =
|
||||
let
|
||||
val (match,rem) = List.partition (fn cls => type_of cls = oclType)
|
||||
classifiers
|
||||
in
|
||||
map (addInvariants constraints) match @ rem
|
||||
end
|
||||
|
||||
fun reachableSet (_:associationend) ([]:associationend list) =
|
||||
error "rep_transform.get_reachableSet: empty source list"
|
||||
| reachableSet (target:associationend) ([source]:associationend list) =
|
||||
let
|
||||
val src_var = Variable(name_of_aend source ,type_of_aend source)
|
||||
in
|
||||
([src_var], ocl_aendcall src_var (path_of_aend target)
|
||||
(type_of_aend target))
|
||||
end
|
||||
| reachableSet (target:associationend) (source::rest) =
|
||||
let
|
||||
val (old_vars,intermediate) = reachableSet target rest
|
||||
val src_var = Variable(name_of_aend source ,type_of_aend source)
|
||||
val new_set = ocl_aendcall src_var (path_of_aend target)
|
||||
(type_of_aend target)
|
||||
in
|
||||
(src_var::old_vars ,ocl_intersection_set new_set intermediate)
|
||||
end
|
||||
|
||||
|
||||
fun withinBounds (set:Rep_OclTerm.OclTerm) ((lower,upper):int*int):Rep_OclTerm.OclTerm =
|
||||
let
|
||||
val size = ocl_size set
|
||||
val lower_lit = Literal (Int.toString lower,Integer)
|
||||
val upper_lit = Literal (Int.toString upper,Integer)
|
||||
val lower_bound = ocl_geq size lower_lit
|
||||
val upper_bound = ocl_leq size upper_lit
|
||||
in
|
||||
ocl_and lower_bound upper_bound
|
||||
end
|
||||
|
||||
fun withinAendMultiplicities targetAend sourceAends name =
|
||||
let
|
||||
val _ = trace function_calls "withinAendMultiplicities\n"
|
||||
val tgtMultiplicities = multiplicities_of_aend targetAend
|
||||
val tgtName = name_of_aend targetAend
|
||||
val tgtType = type_of_aend targetAend
|
||||
val (variables,set) = reachableSet targetAend sourceAends
|
||||
val constrBody = ocl_or_all (map (withinBounds set) tgtMultiplicities)
|
||||
val tgtVariable = Variable(tgtName^nextUid (),tgtType)
|
||||
val allInstances = ocl_allInstances tgtVariable
|
||||
val constrComplete = ocl_forAll allInstances variables constrBody
|
||||
val constraint = (SOME name,constrComplete)
|
||||
in
|
||||
constraint
|
||||
end
|
||||
|
||||
fun injectiveConstraint (source_path:Path) (source_type:OclType) (targets:associationend list) (name:string):constraint =
|
||||
let
|
||||
val source_name = get_short_name source_path
|
||||
val src_var = Variable(source_name,source_type)
|
||||
fun role_bounds src_var aend =
|
||||
let
|
||||
val name = path_of_aend aend
|
||||
val aend_type = type_of_aend aend
|
||||
val set = ocl_aendcall src_var name aend_type
|
||||
val size = ocl_size set
|
||||
val bounds = ocl_eq size (Literal("1",Integer))
|
||||
in
|
||||
bounds
|
||||
end
|
||||
fun role_equals src_var src2_var aend =
|
||||
let
|
||||
val name = path_of_aend aend
|
||||
val aend_type = type_of_aend aend
|
||||
val set = ocl_aendcall src_var name aend_type
|
||||
val size = ocl_size set
|
||||
val match = ocl_eq size (Literal("1",Integer))
|
||||
in
|
||||
match
|
||||
end
|
||||
val roles = map (role_bounds src_var) targets
|
||||
val roles_part = ocl_and_all roles
|
||||
val allInstances = ocl_allInstances src_var
|
||||
val src_var2 = Variable(source_name^"2",source_type)
|
||||
val matches = map (role_equals src_var src_var2) targets
|
||||
val matches_anded = ocl_and_all roles
|
||||
val matches_equal = ocl_eq src_var src_var2
|
||||
val matches_imp = ocl_implies matches_anded matches_equal
|
||||
val allInstances2 = ocl_allInstances src_var2
|
||||
val matches_part = ocl_forAll allInstances2 [src_var2] matches_imp
|
||||
val constr_body = ocl_and roles_part matches_part
|
||||
val constr_complete = ocl_forAll allInstances [src_var] constr_body
|
||||
in
|
||||
(SOME name,constr_complete)
|
||||
end
|
||||
|
||||
fun modifyAssociationsOfClassifier (newAssociations:association list)
|
||||
(oldAssociations:association list)
|
||||
(Class{name,parent,attributes,
|
||||
operations,associations,invariant,
|
||||
stereotypes,interfaces,thyname,
|
||||
|
@ -266,12 +460,13 @@ fun modifyAssociationsOfClassifier newAssociations oldAssociations
|
|||
interfaces=interfaces,
|
||||
thyname=thyname}
|
||||
|
||||
fun uniquenessOclConstraint source associations =
|
||||
fun uniquenessOclConstraint (source:Classifier) (associations:association list) =
|
||||
let
|
||||
fun assocAendCalls (self:OclTerm) iter {name,aends,aclass} =
|
||||
fun assocAendCalls (self:OclTerm) (iter:OclTerm) {name,aends,aclass} =
|
||||
let
|
||||
val [{name,aend_type,...}] = filter (fn {aend_type,...} =>
|
||||
aend_type <> Rep_OclHelper.type_of self)
|
||||
val [{name,aend_type,...}] = filter (fn {aend_type,name,multiplicity,ordered,visibility,init} =>
|
||||
Rep_OclHelper.type_of self
|
||||
<> aend_type)
|
||||
aends
|
||||
val selfCall = ocl_aendcall self name (Collection aend_type)
|
||||
val iterCall = ocl_aendcall iter name (Collection aend_type)
|
||||
|
@ -291,12 +486,12 @@ fun uniquenessOclConstraint source associations =
|
|||
end
|
||||
|
||||
|
||||
fun binaryAssociations source targets aends=
|
||||
fun binaryAssociations (source:Classifier) (targets:Classifier list) aends=
|
||||
let
|
||||
val _ = trace function_calls "binaryAssociations\n"
|
||||
fun generateAssociation target =
|
||||
let
|
||||
val assocName = package_of_aend source @
|
||||
val assocName = package_of source @
|
||||
["BinaryAssoc"^nextUid ()]
|
||||
val oppAend = {name=assocName@[short_name_of target],
|
||||
aend_type=type_of target,
|
||||
|
@ -323,11 +518,12 @@ fun binaryAssociations source targets aends=
|
|||
| order (x::xs) [] =
|
||||
raise InvalidArguments ("binaryAssociations.order:"^
|
||||
"arguments don't agree\n")
|
||||
| order pairs ({name=refName,aend_type,...}::aends) =
|
||||
| order pairs ({name=refName,aend_type,multiplicity,ordered,init,visibility}::aends) =
|
||||
let
|
||||
val ([oppAend],rem) = List.partition (fn (_,{name=oppAendName,
|
||||
aend_type,...}:Rep_Core.associationend) =>
|
||||
oppAendName = refName) pairs
|
||||
aend_type,multiplicity,ordered,visibility,init}) =>
|
||||
oppAendName = refName)
|
||||
pairs
|
||||
in
|
||||
oppAend :: (order rem aends)
|
||||
end
|
||||
|
@ -335,25 +531,25 @@ fun binaryAssociations source targets aends=
|
|||
|
||||
val pairs = map generateAssociation targets
|
||||
in
|
||||
unzip (order pairs aends)
|
||||
ListPair.unzip (order pairs aends)
|
||||
end
|
||||
|
||||
fun variableFromAend {name,aend_type,...} =
|
||||
fun variableFromAend ({name,aend_type,...}:associationend) =
|
||||
Variable (toLower (short_name_of_path name)^nextUid (),aend_type)
|
||||
|
||||
fun variableFromClassifier cls =
|
||||
fun variableFromClassifier (cls:Classifier) =
|
||||
Variable (toLower (short_name_of cls)^nextUid () ,type_of cls)
|
||||
|
||||
fun roleToAend source {name,aend_type,...} =
|
||||
fun roleToAend source ({name,aend_type,...}:associationend) =
|
||||
ocl_aendcall source name (Collection aend_type)
|
||||
|
||||
fun fixAends source aends =
|
||||
fun fixAends source (aends:associationend list) =
|
||||
let
|
||||
fun equal (a,b) = ocl_eq a b
|
||||
|
||||
val vars = map variableFromAend aends
|
||||
val roles = map (roleToAend source) aends
|
||||
val body = ocl_and_all (map equal (zip (roles,vars)))
|
||||
val body = ocl_and_all (map equal (ListPair.zip (roles,vars)))
|
||||
val sourceType = Rep_OclHelper.type_of source
|
||||
val ocl = ocl_select (ocl_allInstances
|
||||
(Literal (short_name_of_OclType sourceType,
|
||||
|
@ -363,7 +559,7 @@ fun fixAends source aends =
|
|||
(ocl,vars)
|
||||
end
|
||||
|
||||
fun multiplicityOclConstraint source multis binaryAssocs =
|
||||
fun multiplicityOclConstraint source multis oppAends =
|
||||
let
|
||||
val _ = trace function_calls "multiplicityOclConstraint\n"
|
||||
fun bound set (low,high) =
|
||||
|
@ -382,15 +578,18 @@ fun multiplicityOclConstraint source multis binaryAssocs =
|
|||
|
||||
val selfVar = self (type_of source)
|
||||
in
|
||||
iterate selfVar multis [] binaryAssocs
|
||||
iterate selfVar multis [] oppAends
|
||||
end
|
||||
|
||||
fun consistencyOclConstraint source reference selfAend roles refRoles =
|
||||
let
|
||||
val _ = trace function_calls "consistencyOclConstraint\n"
|
||||
fun implies selfVar refVar {name=selfPath,aend_type=selfType,...}
|
||||
((role as {name=newPath,aend_type=newType,...}),
|
||||
{name=refPath,aend_type=refType,...}) =
|
||||
fun implies selfVar refVar {name=selfPath,aend_type=selfType,
|
||||
multiplicity,init,visibility,ordered}
|
||||
((role as {name=newPath,aend_type=newType,ordered=ord2,
|
||||
init=init2,multiplicity=mult2,visibility=vis2}),
|
||||
{name=refPath,aend_type=refType,multiplicity=multi3,
|
||||
init=init3,visibility=vis3,ordered=ord3}) =
|
||||
let
|
||||
val var = variableFromAend role
|
||||
val refVarType = Rep_OclHelper.type_of refVar
|
||||
|
@ -413,30 +612,33 @@ fun consistencyOclConstraint source reference selfAend roles refRoles =
|
|||
val refVar = variableFromClassifier reference
|
||||
|
||||
in
|
||||
(source, map (implies selfVar refVar selfAend ) (zip (roles,refRoles)))
|
||||
(source, map (implies selfVar refVar selfAend )
|
||||
(ListPair.zip (roles,refRoles)))
|
||||
end
|
||||
|
||||
fun splitNAryAssociation (association as {name as (qualifier::assocName),
|
||||
fun splitNAryAssociation (association as {name=qualifier::assocName,
|
||||
aends,aclass}) classifiers =
|
||||
let
|
||||
val _ = trace function_calls "splitNAryAssociation\n"
|
||||
fun updateClassifier ((clsType,newPaths),classifiers) =
|
||||
fun updateClassifier ((clsType,newAssocs),classifiers) =
|
||||
let
|
||||
val ([cls],rem) = List.partition (fn x => type_of x = clsType )
|
||||
classifiers
|
||||
val modifiedCls = modifyAssociationsOfClassifier newPaths
|
||||
val ([cls],rem) = List.partition (fn x => type_of x = clsType )
|
||||
classifiers
|
||||
val modifiedCls = modifyAssociationsOfClassifier newAssocs
|
||||
[association]
|
||||
cls
|
||||
in
|
||||
modifiedCls::rem
|
||||
modifiedCls::rem
|
||||
end
|
||||
|
||||
|
||||
fun iterate done [] = []
|
||||
| iterate done ((aend as {name,aend_type,multiplicity,ordered,
|
||||
visibility,init})::xs) =
|
||||
visibility,init})::xs) =
|
||||
let
|
||||
fun makeAssoc (sourceAend as {name,aend_type,...})
|
||||
{name=targetName,aend_type=targetType,...} =
|
||||
fun makeAssoc (sourceAend as {name,aend_type,multiplicity,init,
|
||||
ordered,visibility})
|
||||
{name=targetName,aend_type=targetType,init=init2,
|
||||
ordered=ord2,multiplicity=mult2,visibility=vis2} =
|
||||
let
|
||||
val assocPath = package_of_aend sourceAend
|
||||
val assocName = short_name_of_path (association_of_aend
|
||||
|
@ -462,9 +664,9 @@ fun splitNAryAssociation (association as {name as (qualifier::assocName),
|
|||
(oppAend,binaryAssoc)
|
||||
end
|
||||
|
||||
val (oppAends,binaryAssocs) = unzip (map (makeAssoc aend)
|
||||
(done@xs))
|
||||
val role = short_name_of name
|
||||
val (oppAends,binaryAssocs) = ListPair.unzip (map (makeAssoc aend)
|
||||
(done@xs))
|
||||
val role = short_name_of_path name
|
||||
in
|
||||
(aend_type,role,oppAends,binaryAssocs)::
|
||||
(iterate (aend::done) xs)
|
||||
|
@ -478,9 +680,8 @@ fun splitNAryAssociation (association as {name as (qualifier::assocName),
|
|||
"arguments don't agree\n")
|
||||
| order pairs (cls::clsses) =
|
||||
let
|
||||
val ([oppAend],rem) = List.partition (fn (oppCls,_,_,_) =>
|
||||
name_of oppCls =
|
||||
name_of cls)
|
||||
val ([oppAend],rem) = List.partition (fn (oppType,_,_,_) =>
|
||||
type_of cls = oppType)
|
||||
pairs
|
||||
in
|
||||
oppAend :: (order rem clsses)
|
||||
|
@ -498,39 +699,55 @@ fun splitNAryAssociation (association as {name as (qualifier::assocName),
|
|||
|
||||
(* generate new associations *)
|
||||
val pairs = iterate [] aends
|
||||
val (clsses,roleNames,oppAends,splitAssocs) = unzip4 (order pairs
|
||||
val (types,roleNames,oppAends,splitAssocs) = unzip4 (order pairs
|
||||
classifiers)
|
||||
|
||||
(* update associations in classifiers to the new names *)
|
||||
val modifiedClassifiers = foldl updateClassifier classifiers
|
||||
(zip (map type_of clsses,
|
||||
map getPaths splitAssocs))
|
||||
(ListPair.zip (types,splitAssocs))
|
||||
in
|
||||
(modifiedClassifiers, roleNames, oppAends, splitAssocs)
|
||||
end
|
||||
|
||||
(* target type and role name is unqiue, even with reflexive links *)
|
||||
fun matchAends oppRefAends oppAends =
|
||||
fun matchAends (oppRefAends:associationend list) oppAends =
|
||||
let
|
||||
fun findMatch {aend_type=oppAendType,name=oppName,...} =
|
||||
hd (List.filter (fn {aend_type=refAendType,name=refName,
|
||||
...} => oppAendType = refAendType andalso
|
||||
List.last oppName = List.last refName)
|
||||
fun findMatch {aend_type=oppAendType,name=oppName,multiplicity,init,
|
||||
ordered,visibility} =
|
||||
hd (List.filter (fn {aend_type=refAendType,name=refName,ordered,
|
||||
visibility,init,multiplicity} =>
|
||||
oppAendType = refAendType andalso
|
||||
List.last oppName = List.last refName)
|
||||
oppRefAends)
|
||||
in
|
||||
map findMatch oppAends
|
||||
map findMatch oppAends
|
||||
end
|
||||
|
||||
|
||||
(* target type and role name is still unqiue for classifiers and role *)
|
||||
fun matchClassifiers oppRefAends pairs =
|
||||
fun matchClassifiersAtAend aends classifiers =
|
||||
let
|
||||
fun matchClassifier (cls,role) =
|
||||
hd (filter (fn {aend_type,name,...} =>
|
||||
fun match {name,aend_type,ordered,init,multiplicity,visibility} =
|
||||
hd (List.filter (fn cls => type_of cls = aend_type)
|
||||
classifiers)
|
||||
|
||||
fun remove (cls,classifiers) =
|
||||
#2 (List.partition (fn x => type_of x = type_of cls) classifiers)
|
||||
|
||||
val matched = map match aends
|
||||
val rem = foldl remove classifiers matched
|
||||
in
|
||||
(matched,rem)
|
||||
end
|
||||
|
||||
(* target type and role name is still unqiue for classifiers and role *)
|
||||
fun matchAendsAtClassifier oppRefAends pairs =
|
||||
let
|
||||
fun matchAend (cls,role) =
|
||||
hd (filter (fn {aend_type,name,multiplicity,init,
|
||||
ordered,visibility} =>
|
||||
type_of cls = aend_type andalso
|
||||
role = short_name_of_path name) oppRefAends)
|
||||
in
|
||||
map matchClassifier pairs
|
||||
map matchAend pairs
|
||||
end
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue