|
@@ -62,13 +62,10 @@ Element function get_possible_bindings(host_model : Element, LHS_model : Element
|
|
|
String typename
|
|
|
String original_typename
|
|
|
|
|
|
- log("FIND BINDING")
|
|
|
options = create_node()
|
|
|
|
|
|
typename = reverseKeyLookup(LHS_model["metamodel"]["model"], dict_read_node(LHS_model["type_mapping"], LHS_model["model"][current_element]))
|
|
|
original_typename = string_substr(typename, 4, string_len(typename))
|
|
|
- log("Found type: " + typename)
|
|
|
- log("Original type: " + original_typename)
|
|
|
|
|
|
if (is_edge(LHS_model["model"][current_element])):
|
|
|
// Is an edge, so check for already bound source/target
|
|
@@ -77,20 +74,15 @@ Element function get_possible_bindings(host_model : Element, LHS_model : Element
|
|
|
|
|
|
if (bool_and(set_in(dict_keys(map), src_label), set_in(dict_keys(map), dst_label))):
|
|
|
// Source and destination are bound
|
|
|
- log("MERGE")
|
|
|
options = allOutgoingAssociationInstances(host_model, map[src_label], original_typename)
|
|
|
- log("SRC: " + set_to_string(allOutgoingAssociationInstances(host_model, map[src_label], original_typename)))
|
|
|
- log("DST: " + set_to_string(allIncomingAssociationInstances(host_model, map[dst_label], original_typename)))
|
|
|
options = set_overlap(options, allIncomingAssociationInstances(host_model, map[dst_label], original_typename))
|
|
|
|
|
|
elif (set_in(dict_keys(map), src_label)):
|
|
|
// Source is bound
|
|
|
- log("SOURCE")
|
|
|
options = allOutgoingAssociationInstances(host_model, map[src_label], original_typename)
|
|
|
|
|
|
elif (set_in(dict_keys(map), dst_label)):
|
|
|
// Destination is bound
|
|
|
- log("DESTINATION")
|
|
|
options = allIncomingAssociationInstances(host_model, map[dst_label], original_typename)
|
|
|
|
|
|
else:
|
|
@@ -106,21 +98,17 @@ Element function get_possible_bindings(host_model : Element, LHS_model : Element
|
|
|
String option
|
|
|
|
|
|
filtered_options = create_node()
|
|
|
- log("Checking options")
|
|
|
while (read_nr_out(options) > 0):
|
|
|
option = set_pop(options)
|
|
|
// Check for detecting same element twice
|
|
|
- log("Option: " + cast_v2s(option))
|
|
|
if (bool_not(set_in(map, option))):
|
|
|
// Option is already present with another label, so skip this!
|
|
|
|
|
|
// Check for local constraints of element
|
|
|
if (element_eq(read_attribute(LHS_model, current_element, "constraint"), read_root())):
|
|
|
// No local constraints, so all is well
|
|
|
- log("No constraints, so ignore")
|
|
|
set_add(filtered_options, option)
|
|
|
else:
|
|
|
- log("Verify constraints first")
|
|
|
// Check local constraints and add only if positive
|
|
|
Element constraint_function
|
|
|
constraint_function = read_attribute(LHS_model, current_element, "constraint")
|
|
@@ -128,8 +116,6 @@ Element function get_possible_bindings(host_model : Element, LHS_model : Element
|
|
|
result = constraint_function(host_model, option)
|
|
|
if (result):
|
|
|
set_add(filtered_options, option)
|
|
|
- else:
|
|
|
- log("ERROR: already matched")
|
|
|
|
|
|
return filtered_options!
|
|
|
|
|
@@ -153,20 +139,16 @@ Element function match(host_model : Element, LHS_model : Element):
|
|
|
set_add(mappings, create_node())
|
|
|
while (bool_and(read_nr_out(schedule) > 0, read_nr_out(mappings) > 0)):
|
|
|
current_element = list_pop(schedule, 0)
|
|
|
- log("Finding options for " + cast_v2s(read_attribute(LHS_model, current_element, "label")))
|
|
|
new_mappings = create_node()
|
|
|
|
|
|
while (read_nr_out(mappings) > 0):
|
|
|
map = set_pop(mappings)
|
|
|
- log("In context " + dict_to_string(map))
|
|
|
options = get_possible_bindings(host_model, LHS_model, current_element, map)
|
|
|
- log("Found options " + set_to_string(options))
|
|
|
|
|
|
while (read_nr_out(options) > 0):
|
|
|
option = set_pop(options)
|
|
|
new_map = dict_copy(map)
|
|
|
dict_add(new_map, read_attribute(LHS_model, current_element, "label"), option)
|
|
|
- log(" --> adding mapping " + dict_to_string(new_map))
|
|
|
set_add(new_mappings, new_map)
|
|
|
|
|
|
mappings = new_mappings
|
|
@@ -174,7 +156,76 @@ Element function match(host_model : Element, LHS_model : Element):
|
|
|
return mappings!
|
|
|
|
|
|
Void function rewrite(host_model : Element, RHS_model : Element, mapping : Element):
|
|
|
- output("TODO: rewrite!")
|
|
|
+ // Rewrite the host model based on the mapping combined with the RHS
|
|
|
+ Element LHS_labels
|
|
|
+ Element RHS_labels
|
|
|
+ Element RHS_elements
|
|
|
+ Element remaining
|
|
|
+ String elem
|
|
|
+ String label
|
|
|
+ Element labels_to_remove
|
|
|
+ Element labels_to_add
|
|
|
+ String typename
|
|
|
+ String original_typename
|
|
|
+ String src
|
|
|
+ String dst
|
|
|
+ Element new_mapping
|
|
|
+ String new_name
|
|
|
+
|
|
|
+ LHS_labels = dict_keys(mapping)
|
|
|
+ RHS_labels = create_node()
|
|
|
+
|
|
|
+ RHS_elements = allInstances(RHS_model, "Post_Element")
|
|
|
+ while (read_nr_out(RHS_elements) > 0):
|
|
|
+ set_add(RHS_labels, read_attribute(RHS_model, set_pop(RHS_elements), "label"))
|
|
|
+
|
|
|
+ remaining = set_overlap(LHS_labels, RHS_labels)
|
|
|
+ while (read_nr_out(remaining) > 0):
|
|
|
+ elem = set_pop(remaining)
|
|
|
+ set_remove(LHS_labels, elem)
|
|
|
+ set_remove(RHS_labels, elem)
|
|
|
+ log("LHS labels: " + set_to_string(LHS_labels))
|
|
|
+ log("RHS labels: " + set_to_string(RHS_labels))
|
|
|
+
|
|
|
+ labels_to_remove = LHS_labels
|
|
|
+ labels_to_add = set_to_list(RHS_labels)
|
|
|
+ log("Labels to add: " + dict_to_string(labels_to_add))
|
|
|
+ log("Labels to remove: " + set_to_string(labels_to_remove))
|
|
|
+
|
|
|
+ new_mapping = dict_copy(mapping)
|
|
|
+ while (read_nr_out(labels_to_remove) > 0):
|
|
|
+ // Remove the elements linked to these labels
|
|
|
+ label = set_pop(labels_to_remove)
|
|
|
+ log("Remove element linked to label " + label)
|
|
|
+ log(" --> " + cast_v2s(mapping[label]))
|
|
|
+ model_delete_element(host_model, mapping[label])
|
|
|
+ dict_delete(new_mapping, label)
|
|
|
+
|
|
|
+ while (read_nr_out(labels_to_add) > 0):
|
|
|
+ // Add the elementsl inked to these labels
|
|
|
+ label = list_pop(labels_to_add, 0)
|
|
|
+ log("Add element linked to label " + label)
|
|
|
+ if (is_edge(RHS_model["model"][mapping[label]])):
|
|
|
+ // Edge
|
|
|
+ src = read_attribute(RHS_model, reverseKeyLookup(RHS_model["model"], read_edge_src(RHS_model["model"][mapping[label]])), "label")
|
|
|
+ dst = read_attribute(RHS_model, reverseKeyLookup(RHS_model["model"], read_edge_dst(RHS_model["model"][mapping[label]])), "label")
|
|
|
+ // First check whether both source and destination are already created
|
|
|
+ if (bool_and(dict_in(new_mapping, src), dict_in(new_mapping, dst))):
|
|
|
+ // Both are present, so we can make the link
|
|
|
+ typename = reverseKeyLookup(RHS_model["metamodel"]["model"], dict_read_node(RHS_model["type_mapping"], RHS_model["model"][mapping[label]]))
|
|
|
+ original_typename = string_substr(typename, 5, string_len(typename))
|
|
|
+ new_name = instantiate_link(host_model, original_typename, "", new_mapping[src], new_mapping[dst])
|
|
|
+ dict_add(new_mapping, label, new_name)
|
|
|
+ else:
|
|
|
+ // Delay this a bit, until all are bound
|
|
|
+ list_append(labels_to_add, label)
|
|
|
+ else:
|
|
|
+ // Node
|
|
|
+ // Create the node and add it
|
|
|
+ typename = reverseKeyLookup(RHS_model["metamodel"]["model"], dict_read_node(RHS_model["type_mapping"], RHS_model["model"][mapping[label]]))
|
|
|
+ original_typename = string_substr(typename, 5, string_len(typename))
|
|
|
+ new_name = instantiate_node(host_model, original_typename, "")
|
|
|
+ dict_add(new_mapping, label, new_name)
|
|
|
|
|
|
return!
|
|
|
|