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 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 + "): pass # Execute rule " + string_replace(rule, "/", "_") + "\n" log("Got result:") log(result) return True!