include "primitives.alh" include "modelling.alh" include "object_operations.alh" include "random.alh" include "utils.alh" Boolean function main(model : Element): String result Element nodes String node Element edges String edge String new_node String source String destination String name Element to_explore Element rules String rule String value Element explored Element remainder_to_explore String attr explored = set_create() result = "root, = yield [('RR', [])]\n" nodes = allInstances(model, "Rules/Root") while (set_len(nodes) > 0): node = set_pop(nodes) source = string_replace(node, "/", "_") result = result + source + " = root\n" // Keep following outgoing edges to find matching nodes to_explore = set_create() remainder_to_explore = set_create() set_add(to_explore, node) while (set_len(to_explore) > 0): // Still explore more! node = set_pop(to_explore) source = string_replace(node, "/", "_") edges = allOutgoingAssociationInstances(model, node, "Rules/Edge") while (set_len(edges) > 0): edge = set_pop(edges) new_node = readAssociationDestination(model, edge) if (value_eq(read_attribute(model, new_node, "match"), True)): // Is a match node, so fetch the value on the edge name = read_attribute(model, edge, "value") destination = string_replace(new_node, "/", "_") if (element_eq(name, read_root())): String node_key node_key = string_replace(set_pop(allAssociationDestinations(model, edge, "")), "/", "_") if (set_in(explored, node_key)): result = result + destination + ", = yield [('RDN', [" + source + ", " + node_key + "])]\n" else: set_add(remainder_to_explore, node) else: if (set_in(explored, destination)): // Already visited this one in another way, so try to merge! String rand rand = random_string(10) result = result + rand + ", = yield [('RD', [" + source + ", " + name + "])]\n" result = result + "if " + rand + " != " + destination + ":\n" // If the values don't agree, this is not a correct match, and we say that this element remains unmatched (i.e., assign None) result = result + "\t" + destination + " = None\n" else: // First visit to this element, so just assign result = result + destination + ", = yield [('RD', [" + source + ", " + name + "])]\n" set_add(explored, destination) String value value = read_attribute(model, new_node, "value") if (element_neq(value, read_root())): // Match node has a value we should compare as well! // Read out the value from the Modelverse result = result + destination + "_V, = yield [('RV', [" + destination + "])]\n" set_add(to_explore, new_node) if (bool_and(set_len(to_explore) == 0, set_len(remainder_to_explore) > 0)): to_explore = remainder_to_explore remainder_to_explore = set_create() rules = allInstances(model, "Rules/Rule") while (set_len(rules) > 0): // Check if this rule is applicable rule = set_pop(rules) // Fetch all elements with a "match" label and check that they are not None (and possibly, that they have a value) result = result + "if (True " nodes = allAssociationDestinations(model, rule, "Rules/contains") while (set_len(nodes) > 0): node = set_pop(nodes) if (value_eq(read_attribute(model, node, "match"), True)): // We should match on this node: value = read_attribute(model, node, "value") if (bool_and(read_type(model, node) == "Rules/NAC", element_eq(value, read_root()))): result = result + " and " + string_replace(node, "/", "_") + " is None " else: result = result + " and " + string_replace(node, "/", "_") + " is not None " if (element_neq(value, read_root())): // Got a value, so match that as well // But check if it is an action element (first character == !) String sign if (read_type(model, node) == "Rules/NAC"): sign = "!=" else: sign = "==" if (string_get(value, 0) == "!"): result = result + " and " + string_replace(node, "/", "_") + "_V['value'] " + sign + " '" + string_replace(value, "!", "") + "'" else: result = result + " and " + string_replace(node, "/", "_") + "_V " + sign + " " + value result = result + "):\n" result = result + "\t# Execute rule " + rule + "\n" // We know all the nodes that we already have (in variable "explored") // Still have to match all "match" and "delete" elements // For "match", it is exactly the same as before // For "delete" edges, we match using "RD" and "RDE" nodes = allAssociationDestinations(model, rule, "Rules/contains") Element create_edges create_edges = set_create() explored = set_create() while (set_len(nodes) > 0): node = set_pop(nodes) if (read_type(model, node) == "Rules/Root"): // Found the root of this rule, so start exploring again // Keep following outgoing edges to find matching nodes to_explore = set_create() remainder_to_explore = set_create() set_add(to_explore, node) while (set_len(to_explore) > 0): // Still explore more! node = set_pop(to_explore) source = string_replace(node, "/", "_") edges = allOutgoingAssociationInstances(model, node, "Rules/MatchEdge") while (set_len(edges) > 0): edge = set_pop(edges) new_node = readAssociationDestination(model, edge) name = read_attribute(model, edge, "value") destination = string_replace(new_node, "/", "_") if (element_eq(name, read_root())): String node_key node_key = string_replace(set_pop(allAssociationDestinations(model, edge, "")), "/", "_") if (set_in(explored, node_key)): result = result + "\t" + destination + ", = yield [('RDN', [" + source + ", " + node_key + "])]\n" else: set_add(remainder_to_explore, node) continue! if (read_type(model, edge) == "Rules/DeleteEdge"): // Delete edge result = result + "\t" + destination + "_DEL, = yield [('RDNE', [" + source + ", " + node_key + "])]\n" result = result + "\tyield [('DE', [" + destination + "_DEL])]\n" else: if (set_in(explored, destination)): // Already visited this one in another way, so try to merge! String rand rand = random_string(10) result = result + "\t" + rand + ", = yield [('RD', [" + source + ", " + name + "])]\n" result = result + "\t" + "if " + rand + " != " + destination + ":\n" // If the values don't agree, this is not a correct match, and we say that this element remains unmatched (i.e., assign None) result = result + "\t" + "\t" + destination + " = None\n" else: // First visit to this element, so just assign result = result + "\t" + destination + ", = yield [('RD', [" + source + ", " + name + "])]\n" set_add(explored, destination) String value value = read_attribute(model, new_node, "value") if (element_neq(value, read_root())): // Match node has a value we should compare as well! // Read out the value from the Modelverse result = result + "\t" + destination + "_V, = yield [('RV', [" + destination + "])]\n" set_add(to_explore, new_node) if (read_type(model, edge) == "Rules/DeleteEdge"): // Delete edge result = result + "\t" + destination + "_DEL, = yield [('RDE', [" + source + ", " + name + "])]\n" result = result + "\tyield [('DE', [" + destination + "_DEL])]\n" if (bool_and(set_len(to_explore) == 0, set_len(remainder_to_explore) > 0)): to_explore = remainder_to_explore remainder_to_explore = set_create() elif (read_type(model, node) == "Rules/Create"): // A node that we should create: do that already, as otherwise we might have to sort String attr attr = read_attribute(model, node, "value") if (element_eq(attr, read_root())): // Create empty node result = result + "\t" + string_replace(node, "/", "_") + ", = yield [('CN', [])]\n" else: // Create value node result = result + "\t" + string_replace(node, "/", "_") + ", = yield [('CNV', [" + cast_string(attr) + "])]\n" elif (read_type(model, node) == "Rules/CreateEdge"): // Encounter a create edge, so alreade record this for later set_add(create_edges, node) // Now create all the new edges, given that we assume everything to be matched while (set_len(create_edges) > 0): edge = set_pop(create_edges) attr = read_attribute(model, edge, "value") if (element_neq(attr, read_root())): result = result + "\t" + string_replace(edge, "/", "_") + ", = yield [('CD', [" + string_replace(readAssociationSource(model, edge), "/", "_") + ", " + attr + ", " + string_replace(readAssociationDestination(model, edge), "/", "_") + "])]\n" else: result = result + "\t" + string_replace(edge, "/", "_") + ", = yield [('CE', [" + string_replace(readAssociationSource(model, edge), "/", "_") + ", " + string_replace(readAssociationDestination(model, edge), "/", "_") + "])]\n" log("Got result:") log(result) return True!