diff --git a/src/xmi2rep.sml b/src/xmi2rep.sml index 2c9bd92..dfdb4c1 100644 --- a/src/xmi2rep.sml +++ b/src/xmi2rep.sml @@ -202,9 +202,16 @@ fun transform_attribute t ({xmiid,name,type_id,changeability,visibility,ordering } end +fun lowercase s = let val sl = String.explode s + in + String.implode ((Char.toLower (hd sl))::(tl sl)) + end + fun transform_aend t ({xmiid,name,ordering,multiplicity,participant_id, isNavigable,aggregation,changeability,visibility,targetScope}) - = {name = valOf name, + = {name = Option.getOpt(name, + (lowercase o XMI.classifier_name_of o + find_classifier t) participant_id), aend_type = find_classifier_type t participant_id, multiplicity = multiplicity, ordered = if ordering = XMI.Ordered then true else false, @@ -309,7 +316,7 @@ fun transform_classifier t (XMI.Class {xmiid,name,isActive,visibility,isLeaf, invariant = map ((transform_constraint t) o (find_constraint t)) checked_invariants, associationends = map (transform_aend t) - ((filter_named_aends (find_aends t xmiid))), + (find_aends t xmiid), stereotypes = map (find_stereotype t) stereotype, interfaces = nil, (* FIX *) activity_graphs = List.concat [map (transform_activitygraph t) activity_graphs, @@ -335,7 +342,7 @@ fun transform_classifier t (XMI.Class {xmiid,name,isActive,visibility,isLeaf, invariant = map ((transform_constraint t) o (find_constraint t)) checked_invariants, associationends = map (transform_aend t) - ((filter_named_aends (find_aends t xmiid))), + (find_aends t xmiid), stereotypes = map (find_stereotype t) stereotype, interfaces = nil, (* FIX *) activity_graphs = nil, @@ -350,7 +357,7 @@ fun transform_classifier t (XMI.Class {xmiid,name,isActive,visibility,isLeaf, parent = NONE, (* FIX *) operations = map (transform_operation t) operations, associationends = map (transform_aend t) - (filter_named_aends (find_aends t xmiid)), + (find_aends t xmiid), invariant = map ((transform_constraint t) o (find_constraint t)) checked_invariants, stereotypes = nil, (*FIX *) @@ -418,9 +425,9 @@ fun transformXMI ({classifiers,constraints,packages, (* "hd packages" is supposed to be the first model in the xmi-file *) val model = hd packages in - insert_model xmiid_table model; (* fill xmi.id table *) - transform_associations xmiid_table model; (* handle associations *) - map Rep.normalize (transform_package xmiid_table model) (* transform classes *) + insert_model xmiid_table model; (* fill xmi.id table *) + transform_associations xmiid_table model; (* handle associations *) + map Rep.normalize (transform_package xmiid_table model) (* transform classes *) end handle Empty => raise Option diff --git a/src/xmi_idtable.sml b/src/xmi_idtable.sml index 7be2476..08ff484 100644 --- a/src/xmi_idtable.sml +++ b/src/xmi_idtable.sml @@ -426,17 +426,19 @@ fun classifier_has_stereotype t st c = List.exists (fn x => (find_stereotype t x) = st) (XMI.classifier_stereotype_of c) -(* split an association into association ends, and put the association ends *) -(* ends into the xmi.id table under the corresponding (i.e., opposite) *) -(* classifier. *) -(* 1. split the association into a list of two (or more) association ends *) -(* 2. pair each association end with the participant_id's of all other *) -(* association ends: when a class is a participant in an association, *) -(* this association end is a feature of all _other_ participants in the *) -(* association *) -(* 3. insert the mapping xmi.id of class to association end into the *) -(* hashtable *) -(* 4. insert mapping xmi.id of association end to path into the hashtable *) +(** + * split an association into association ends, and put the association ends + * ends into the xmi.id table under the corresponding (i.e., opposite) + * classifier. + * 1. split the association into a list of two (or more) association ends + * 2. pair each association end with the participant_id's of all other + * association ends: when a class is a participant in an association, + * this association end is a feature of all _other_ participants in the + * association + * 3. insert the mapping xmi.id of class to association end into the + * hashtable + * 4. insert mapping xmi.id of association end to path into the hashtable + *) fun transform_assocation t (assoc:XMI.Association) = let val aends = #connection assoc fun all_others x xs = List.filter @@ -461,9 +463,38 @@ fun transform_assocation t (assoc:XMI.Association) = List.app add_aend_to_type mappings end +(** + * insert the association from assocation class to the connected classifiers. + * the other direction (from connected classifiers to the association class + * is more difficult (and not implemented) because the association class does + * not specify (syntactically) an association end. + *) +fun transform_associationclass_as_association t (XMI.AssociationClass assoc) = + let val aends = #connection assoc + fun add_aend_to_type (id,ae) = + if not (Option.isSome (HashTable.find t id)) then () else + let val type_of_id = find_classifier_type t id + val cls_of_id = find_classifier t id + val aends_of_id = ae::(find_aends t id) + val ags_of_id = find_activity_graph_of t id + val path_of_id = path_of_classifier type_of_id + val path_of_ae = path_of_id @ [case #name ae of SOME x => x + | NONE => ""] + in + (HashTable.insert t (id,Type (type_of_id,aends_of_id,cls_of_id,ags_of_id)); + HashTable.insert t (#xmiid ae, AssociationEnd path_of_ae)) + end + in + List.app (fn x => add_aend_to_type (#xmiid assoc, x)) aends + end + + (* recursively transforms all associations in the package p, *) fun transform_associations t (XMI.Package p) = (List.app (transform_associations t) (#packages p); - List.app (transform_assocation t) (#associations p)) - + List.app (transform_assocation t) (#associations p); + List.app (transform_associationclass_as_association t) + (List.filter (fn (XMI.AssociationClass x) => true + | _ => false) + (#classifiers p))) end