include "modelling.alh" include "library.alh" include "primitives.alh" include "constructors.alh" include "object_operations.alh" include "mini_modify.alh" include "model_management.alh" include "ramify.alh" include "conformance_scd.alh" include "transform.alh" include "metamodels.alh" include "utils.alh" include "conformance_finding.alh" include "typing.alh" include "compiler.alh" include "random.alh" include "io.alh" String core_model_location = "models/core" Element core = ? String current_user_id Element caches Element pm_tasks = ? String function get_foldername(name : String): Element result result = string_split(name, "/") list_pop_final(result) if (list_len(result) == 0): return ""! // 'result' now contains a list of entries which we have to join with the seperator String str str = list_pop_final(result) while (list_len(result) > 0): str = cast_string(list_pop_final(result)) + "/" + str return str! String function get_filename(name : String): return list_pop_final(string_split(name, "/"))! String function full_name(model_id : String): return read_attribute(core, model_id, "name")! Void function initialize_core(): // TODO make this more flexible by putting it in the bootstrap in a similar way as other models add_code_model(import_node("models/ActionLanguage"), "models/Conformance_MV", wrap_conformance) return ! Boolean function is_typed_by(model_id : String, metamodel_id : String): return (set_len(get_instanceOf_links(model_id, metamodel_id)) > 0)! Element function get_instanceOf_links(model_id : String, metamodel_id : String): Element result Element options String elem result = set_create() options = allOutgoingAssociationInstances(core, model_id, "instanceOf") while (set_len(options) > 0): elem = set_pop(options) if (value_eq(readAssociationDestination(core, elem), metamodel_id)): set_add(result, elem) return result! String function get_instanceOf_link(model_id : String, metamodel_id : String): Element all_links String choice all_links = get_instanceOf_links(model_id, metamodel_id) if (set_len(all_links) > 1): log("WARNING: multiple instanceOf relations were detected for this model; picking one at random!") elif (set_len(all_links) == 0): log("No types found!") log("Source model: " + cast_value(read_attribute(core, model_id, "name"))) log("Target meta-model: " + cast_value(read_attribute(core, metamodel_id, "name"))) return read_root()! choice = set_pop(all_links) return choice! Element function get_full_model(model_id : String, metamodel_id : String): // TODO we are restricted to using formalisms/SimpleClassDiagrams as M3 level, through this code! Element m Element all_links String choice choice = get_instanceOf_link(model_id, metamodel_id) m = dict_create() dict_add(m, "model", import_node(read_attribute(core, model_id, "location"))) // TODO for now this is restricted to the fixed semantics // dict_add(m, "semantics", set_pop(allAssociationDestinations(core, choice, "semantics"))) dict_add(m, "semantics", get_entry_id("models/conformance_mv")) if (metamodel_id == model_id): // Found the meta-circular level, so we can stop! dict_add(m, "metamodel", m) else: Element mm mm = get_full_model(metamodel_id, get_entry_id("formalisms/SimpleClassDiagrams")) if (element_eq(mm, read_root())): return read_root()! else: dict_add(m, "metamodel", mm) if (element_neq(choice, read_root())): Element types types = allAssociationDestinations(core, choice, "typing") if (set_len(types) == 1): // Add the preferred original type mapping set_type_mapping(m, import_node(read_attribute(core, set_pop(types), "location"))) else: // Start from scratch new_type_mapping(m) else: // Start from scratch new_type_mapping(m) if (find_type_mapping(m)): // TODO store the found type model somewhere return m! else: log("No type mapping could be deduced!") log("Error for " + cast_value(read_attribute(core, model_id, "name"))) log(" and type " + cast_value(read_attribute(core, metamodel_id, "name"))) return read_root()! Integer function get_relation_to_model(user_id : String, model_id : String): if (set_in(allAssociationDestinations(core, model_id, "owner"), user_id)): // We are the owner return 0! else: String group_id group_id = set_pop(allAssociationDestinations(core, model_id, "group")) if (set_in(allAssociationDestinations(core, user_id, "belongsTo"), group_id)): // We are in the owning group return 1! else: // We are not related whatsoever return 2! Boolean function is_admin(user_id : String): if (read_attribute(core, user_id, "admin")): return True! else: return False! Boolean function allow_read(user_id : String, model_id : String): if (is_admin(user_id)): // Is admin, so always allow return True! else: // Check permissions String permission permission = string_get(read_attribute(core, model_id, "permissions"), get_relation_to_model(user_id, model_id)) if (bool_or(permission == "1", permission == "2")): return True! else: return False! Boolean function allow_write(user_id : String, model_id : String): if (is_admin(user_id)): // Is admin, so always allow return True! else: // Check permissions String permission permission = string_get(read_attribute(core, model_id, "permissions"), get_relation_to_model(user_id, model_id)) if (permission == "2"): return True! else: return False! Boolean function allow_change_metadata(user_id : String, model_id : String): if (is_admin(user_id)): // Is admin, so always allow return True! else: if (get_relation_to_model(user_id, model_id) == 0): // Only owner can chmod return True! else: return False! Boolean function allow_group_modify(user_id : String, group_id : String): if (is_admin(user_id)): // Is admin, so always allow return True! else: if (set_in(allAssociationDestinations(core, group_id, "owner"), user_id)): // We are an owner return True! else: return False! Boolean function check_login(user_id : String): String password String stored_password stored_password = read_attribute(core, user_id, "password") output("Password for existing user?") password = hash(input()) return password == stored_password! Void function new_task(): String username String user_id String password // Load in a hard-reference to the previously created model core = import_node(core_model_location) while (True): output("Log on as which user?") username = input() user_id = get_user_id(username) if (user_id == ""): // New user // Add user to Core Formalism user_id = instantiate_node(core, "User", "") instantiate_attribute(core, user_id, "name", username) instantiate_attribute(core, user_id, "admin", False) output("This is a new user: please give password!") password = hash(input()) output("Please repeat the password") if (password == hash(input())): output("Passwords match!") instantiate_attribute(core, user_id, "password", password) break! else: output("Not the same password!") else: if (check_login(user_id)): break! else: output("Wrong password!") user_function_skip_init(user_id) // User destroyed already, so just stop execution return! String function get_entry_id(name : String): Element hierarchy_split String current Integer i Element elems String elem Boolean found String folder_name if (name == ""): return caches["root"]! if (dict_in(caches["models"], name)): if (dict_in(core, caches["models"])): if (full_name(caches["models"][name]) == name): return caches["models"][name]! folder_name = get_foldername(name) current = get_entry_id(folder_name) if (current == ""): return ""! elems = allAssociationDestinations(core, current, "contains") while (set_len(elems) > 0): elem = set_pop(elems) dict_overwrite(caches["models"], read_attribute(core, elem, "name"), elem) if (value_eq(name, read_attribute(core, elem, "name"))): return elem! return ""! String function get_service_id(name : String): core = import_node(core_model_location) Element services String service services = allInstances(core, "Service") while (set_len(services) > 0): service = set_pop(services) if (value_eq(read_attribute(core, service, "name"), name)): return service! return ""! String function get_user_id(name : String): Element users String user users = allInstances(core, "User") while (set_len(users) > 0): user = set_pop(users) if (value_eq(read_attribute(core, user, "name"), name)): return user! return ""! String function get_group_id(name : String): Element groups String group groups = allInstances(core, "Group") while (set_len(groups) > 0): group = set_pop(groups) if (value_eq(read_attribute(core, group, "name"), name)): return group! return ""! String function create_folders(user_id : String, folder_name : String): Element hierarchy Integer i String prev String elem String new_entry String cummul if (get_entry_id(folder_name) != ""): // Folders already exist, so don't iterate return get_entry_id(folder_name)! i = 0 hierarchy = string_split(folder_name, "/") prev = get_entry_id("") cummul = "" // Go through folders first while (i < list_len(hierarchy)): elem = list_read(hierarchy, i) if (cummul == ""): cummul = elem else: cummul = string_join(cummul + "/", elem) if (get_entry_id(cummul) == ""): if (allow_write(user_id, prev)): // Element does not exist yet! new_entry = instantiate_node(core, "Folder", "") instantiate_attribute(core, new_entry, "name", cummul) instantiate_attribute(core, new_entry, "permissions", "200") instantiate_link(core, "contains", "", prev, new_entry) instantiate_link(core, "group", "", new_entry, get_group_id("nobody")) instantiate_link(core, "owner", "", new_entry, user_id) else: return read_root()! prev = get_entry_id(cummul) i = i + 1 return prev! String function store_entry(model_id : String, full_name : String, user_id : String): String prev if (get_entry_id(full_name) != ""): // Delete any old models model_delete(get_entry_id(full_name)) prev = create_folders(user_id, get_foldername(full_name)) instantiate_link(core, "contains", "", prev, model_id) return full_name! String function export_typing(model : Element, name : String): String result result = instantiate_node(core, "TypeMapping", "") name = "type mappings/" + name // Create type mapping model String location location = "type mappings/" + cast_id(get_type_mapping(model)) export_node(location, get_type_mapping(model)) String instance_of name = store_entry(result, name, get_user_id("admin")) instantiate_attribute(core, result, "name", name) instantiate_attribute(core, result, "location", location) instantiate_attribute(core, result, "permissions", "200") instantiate_link(core, "owner", "", result, current_user_id) instantiate_link(core, "group", "", result, get_group_id("nobody")) instance_of = instantiate_link(core, "instanceOf", "", result, get_entry_id("formalisms/TypeMapping")) instantiate_link(core, "semantics", "", instance_of, get_entry_id("models/conformance_mv")) return result! Void function model_create(model : Element, name : String, type_id : String, kind : String): String location String model_id String instance_of // Create model itself location = "models/" + cast_id(model) export_node(location, model["model"]) model_id = instantiate_node(core, kind, "") instantiate_attribute(core, model_id, "name", store_entry(model_id, name, current_user_id)) instantiate_attribute(core, model_id, "location", location) instantiate_attribute(core, model_id, "permissions", "200") instantiate_link(core, "owner", "", model_id, current_user_id) instantiate_link(core, "group", "", model_id, get_group_id("nobody")) instance_of = instantiate_link(core, "instanceOf", "", model_id, type_id) instantiate_link(core, "semantics", "", instance_of, get_entry_id("models/conformance_mv")) // Create type mapping model instantiate_link(core, "typing", "", instance_of, export_typing(model, name)) return! Void function model_overwrite(model : Element, model_id : String, metamodel_id : String): // TODO this should be more elegant than just hiding the old elements String location String instanceOf_link location = "models/" + cast_id(model) export_node(location, model["model"]) // Change location in meta-data unset_attribute(core, model_id, "location") instantiate_attribute(core, model_id, "location", location) // Update the instanceOf relation of the context in which we are working String choice choice = get_instanceOf_link(model_id, metamodel_id) if (element_neq(choice, read_root())): // There was a link, so we remove it // First remove the type mapping it referred to Element tl tl = allAssociationDestinations(core, choice, "typing") while (set_len(tl) > 0): model_delete_element(core, set_pop(tl)) // Now delete the element itself model_delete_element(core, choice) // Create a new instanceOf relation now String instance_of instance_of = instantiate_link(core, "instanceOf", "", model_id, metamodel_id) instantiate_link(core, "semantics", "", instance_of, get_entry_id("models/conformance_mv")) instantiate_link(core, "typing", "", instance_of, export_typing(model, full_name(model_id))) return! Boolean function check_conformance(model_id : String): // TODO check if it actually conforms, considering that instanceOf link // --> in-depth check return True! Element function merge_models(models_dict : Element, operation_name : String): core = import_node(core_model_location) // 0) Find operation signature Element input_metamodels Element iter String edge String operation_id operation_id = get_entry_id(operation_name) input_metamodels = dict_create() iter = allOutgoingAssociationInstances(core, operation_id, "transformInput") while (set_len(iter) > 0): edge = set_pop(iter) dict_add(input_metamodels, read_attribute(core, edge, "name"), read_attribute(core, readAssociationDestination(core, edge), "name")) String merged_metamodel_id String trace_link_id Element trace_links // 1) Find merged metamodel trace_links = allOutgoingAssociationInstances(core, operation_id, "tracability") merged_metamodel_id = "" while (set_len(trace_links) > 0): trace_link_id = set_pop(trace_links) if (value_eq(read_attribute(core, trace_link_id, "type"), "operatesOn")): merged_metamodel_id = readAssociationDestination(core, trace_link_id) // 2) Merge source models if (merged_metamodel_id != ""): Element model_tuples Element keys String key Element mm model_tuples = set_create() keys = dict_keys(models_dict) while (set_len(keys) > 0): key = set_pop(keys) mm = get_full_model(get_entry_id(models_dict[key]), get_entry_id(input_metamodels[key])) if (element_eq(mm, read_root())): log("Signature mismatch in operation for tag " + key) output("Signature mismatch in operation for tag " + key) return read_root()! set_add_node(model_tuples, create_tuple(key, mm)) Element merged_metamodel merged_metamodel = get_full_model(merged_metamodel_id, get_entry_id("SimpleClassDiagrams")) if (element_eq(merged_metamodel, read_root())): log("Merged metamodel in operation is not of type SimpleClassDiagrams") output("Merged metamodel in operation is not of type SimpleClassDiagrams") return read_root()! return model_join(model_tuples, merged_metamodel, read_root())! else: return read_root()! Element function split_model(model : Element, metamodels_dict : Element): core = import_node(core_model_location) Element model_tuples Element keys String key Element mm model_tuples = set_create() keys = dict_keys(metamodels_dict) while (set_len(keys) > 0): key = set_pop(keys) mm = get_full_model(get_entry_id(metamodels_dict[key]), get_entry_id("SimpleClassDiagrams")) if (element_eq(mm, read_root())): log("Output metamodel cannot be interpreted using SimpleClassDiagrams: " + key) output("Output metamodel cannot be interpreted using SimpleClassDiagrams: " + key) return read_root()! set_add_node(model_tuples, create_tuple(key, mm)) return model_split(model, model_tuples, read_root())! Element function get_model(model_name : String, metamodel_name : String): core = import_node(core_model_location) return get_full_model(get_entry_id(model_name), get_entry_id(metamodel_name))! Void function store_model(model_name : String, metamodel_name : String, model : Element): core = import_node(core_model_location) if (get_entry_id(model_name) == ""): // New model model_create(model, model_name, get_entry_id(metamodel_name), "Model") else: model_overwrite(model, get_entry_id(model_name), get_entry_id(metamodel_name)) return! String function get_ramified_metamodel(model_name : String): core = import_node(core_model_location) String operation_id Element trace_links String merged_metamodel_id String trace_link_id String ramified_metamodel_id operation_id = get_entry_id(model_name) trace_links = allOutgoingAssociationInstances(core, operation_id, "tracability") merged_metamodel_id = "" while (set_len(trace_links) > 0): trace_link_id = set_pop(trace_links) if (value_eq(read_attribute(core, trace_link_id, "type"), "operatesOn")): merged_metamodel_id = readAssociationDestination(core, trace_link_id) trace_links = allOutgoingAssociationInstances(core, merged_metamodel_id, "tracability") ramified_metamodel_id = "" while (set_len(trace_links) > 0): trace_link_id = set_pop(trace_links) if (value_eq(read_attribute(core, trace_link_id, "type"), "RAMified")): ramified_metamodel_id = readAssociationDestination(core, trace_link_id) return read_attribute(core, ramified_metamodel_id, "name")! return read_root()! Element function execute_operation(operation_id : String, input_models : Element, tracability_model : Element): // Operations are always in-place and uses only a single metamodel // Therefore, we must: // 1) Find merged metamodel // 2) Merge the different source models and retype // 3) Perform the operation on the merged model // 4) Split the resulting model based on the target formalisms; if operation successful Element input_model String trace_link_id Element merged_model String merged_metamodel_id String ramified_metamodel_id Boolean result String exact_type Element trace_links String model_ID String key Element keys Element input_keys Element output_keys Element model_tuples String metamodel_name Element metamodel String metamodel_ID Boolean tracability // 0) Find the signature of the operation Element input_metamodels Element output_metamodels Element iter String edge input_metamodels = dict_create() iter = allOutgoingAssociationInstances(core, operation_id, "transformInput") while (set_len(iter) > 0): edge = set_pop(iter) dict_add(input_metamodels, read_attribute(core, edge, "name"), full_name(readAssociationDestination(core, edge))) output_metamodels = dict_create() iter = allOutgoingAssociationInstances(core, operation_id, "transformOutput") while (set_len(iter) > 0): edge = set_pop(iter) dict_add(output_metamodels, read_attribute(core, edge, "name"), full_name(readAssociationDestination(core, edge))) // 1) Find merged metamodel exact_type = read_type(core, operation_id) trace_links = allOutgoingAssociationInstances(core, operation_id, "tracability") merged_metamodel_id = "" while (set_len(trace_links) > 0): trace_link_id = set_pop(trace_links) if (value_eq(read_attribute(core, trace_link_id, "type"), "operatesOn")): merged_metamodel_id = readAssociationDestination(core, trace_link_id) // 2) Merge source models if (merged_metamodel_id != ""): model_tuples = set_create() keys = dict_keys(input_models) while (set_len(keys) > 0): key = set_pop(keys) Element mm if (get_entry_id(input_models[key]) == ""): // Input model doesn't exist yet, so create cmd_model_add(input_metamodels[key], input_models[key], "") mm = get_full_model(get_entry_id(input_models[key]), get_entry_id(input_metamodels[key])) if (element_eq(mm, read_root())): log("Signature mismatch in operation for tag " + key) output("Signature mismatch in operation for tag " + key) return read_root()! set_add_node(model_tuples, create_tuple(key, mm)) Element merged_metamodel merged_metamodel = get_full_model(merged_metamodel_id, get_entry_id("formalisms/SimpleClassDiagrams")) if (element_eq(merged_metamodel, read_root())): log("Merged metamodel in operation is not of type formalisms/SimpleClassDiagrams") output("Merged metamodel in operation is not of type formalisms/SimpleClassDiagrams") return read_root()! merged_model = model_join(model_tuples, merged_metamodel, tracability_model) else: if (bool_and(dict_len(input_models) == 1, dict_len(output_metamodels) == 0)): // Just skip the merge... Element m m = get_full_model(get_entry_id(input_models[set_pop(dict_keys(input_models))]), get_entry_id(input_metamodels[set_pop(dict_keys(input_metamodels))])) if (element_eq(m, read_root())): log("Signature mismatch in operation for tag " + cast_value(set_pop(dict_keys(input_models)))) output("Signature mismatch in operation for tag " + cast_value(set_pop(dict_keys(input_models)))) return read_root()! merged_model = model_copy(m) elif (bool_and(dict_len(input_models) == 0, dict_len(output_metamodels) == 0)): merged_model = read_root() else: log("Could not resolve intermediate merged metamodel") output("Could not resolve intermediate merged metamodel") return read_root()! // 3) Transform if (exact_type == "ModelTransformation"): trace_links = allOutgoingAssociationInstances(core, merged_metamodel_id, "tracability") ramified_metamodel_id = "" while (set_len(trace_links) > 0): trace_link_id = set_pop(trace_links) if (value_eq(read_attribute(core, trace_link_id, "type"), "RAMified")): ramified_metamodel_id = readAssociationDestination(core, trace_link_id) Element operation operation = get_full_model(operation_id, ramified_metamodel_id) if (element_eq(operation, read_root())): log("Operation could not be typed by specified RAMified metamodel!") output("Operation could not be typed by specified RAMified metamodel!") return read_root()! result = transform(merged_model, operation) elif (exact_type == "ManualOperation"): output("Please perform manual operation " + cast_value(full_name(operation_id))) String model_name model_name = "" while (get_entry_id(model_name) != ""): model_name = ".tmp/" + random_string(20) model_create(merged_model, model_name, merged_metamodel_id, "Model") // We want to modify, so modify do_spawn_modify(model_name, True) merged_model = get_full_model(get_entry_id(model_name), merged_metamodel_id) //model_delete(get_entry_id(model_name)) result = True elif (exact_type == "ActionLanguage"): Element func Element al al = get_full_model(operation_id, get_entry_id("formalisms/ActionLanguage")) if (element_eq(al, read_root())): log("Action Language operation not typed by ActionLanguage metamodel!") output("Action Language operation not typed by ActionLanguage metamodel!") return read_root()! func = get_func_AL_model(al) result = func(merged_model) else: log("Unknown type of operation: " + exact_type) output("Unknown type of operation: " + exact_type) return read_root()! // 4) Split in different models depending on type if (element_neq(tracability_model, read_root())): tracability = True else: tracability = False if (result): model_tuples = set_create() keys = dict_keys(output_metamodels) while (set_len(keys) > 0): key = set_pop(keys) Element mm mm = get_full_model(get_entry_id(output_metamodels[key]), get_entry_id("formalisms/SimpleClassDiagrams")) if (element_eq(mm, read_root())): log("Output metamodel cannot be interpreted using formalisms/SimpleClassDiagrams: " + key) output("Output metamodel cannot be interpreted using formalisms/SimpleClassDiagrams: " + key) return read_root()! set_add_node(model_tuples, create_tuple(key, mm)) result = model_split(merged_model, model_tuples, tracability) if (tracability): Element new_tracability_model new_tracability_model = result["__tracability"] dict_overwrite(tracability_model, "model", new_tracability_model["model"]) set_type_mapping(tracability_model, get_type_mapping(new_tracability_model)) dict_overwrite(tracability_model, "metamodel", new_tracability_model["metamodel"]) dict_delete(result, "__tracability") return result! else: log("Negative result of execution") return read_root()! Boolean function enact_action(pm : Element, element : String, mapping : Element): Boolean result String transformation_id Element lst String elem Element inputs Element outputs String type_name String exact_type Element trace_links Element output_mms Element consumes_link String name String elem_name Element keys String key String consume String produce Element input_traceability_model String output_traceability_name String output_traceability_type Element output_map inputs = dict_create() outputs = dict_create() output_map = dict_create() input_traceability_model = read_root() output_traceability_name = read_root() output_traceability_type = read_root() // Read out the referenced element from the MvC transformation_id = get_entry_id(read_attribute(pm, element, "name")) // Find all input model names lst = allOutgoingAssociationInstances(pm, element, "Consumes") while (set_len(lst) > 0): consume = set_pop(lst) elem = readAssociationDestination(pm, consume) type_name = read_attribute(pm, elem, "type") elem_name = read_attribute(pm, elem, "name") if (cast_string(read_attribute(pm, consume, "name")) == "__traceability"): input_traceability_model = model_copy(get_full_model(get_entry_id(mapping[elem_name]), get_entry_id(type_name))) output_traceability_type = type_name else: dict_add(inputs, read_attribute(pm, consume, "name"), mapping[elem_name]) // Find all output model names and their metamodel lst = allOutgoingAssociationInstances(pm, element, "Produces") while (set_len(lst) > 0): produce = set_pop(lst) elem = readAssociationDestination(pm, produce) type_name = read_attribute(pm, elem, "type") elem_name = read_attribute(pm, elem, "name") if (cast_string(read_attribute(pm, produce, "name")) == "__traceability"): output_traceability_name = mapping[elem_name] else: dict_add(outputs, read_attribute(pm, produce, "name"), type_name) dict_add(output_map, read_attribute(pm, produce, "name"), mapping[elem_name]) if read_type(core, transformation_id) == "ActionLanguage": log(string_join("Enacting ActionLanguage: ", read_attribute(pm, element, "name"))) output("Success: ready for AL execution") elif read_type(core, transformation_id) == "ManualOperation": log(string_join("Enacting ManualOperation: ", read_attribute(pm, element, "name"))) output("Success: ready for MANUAL execution") else: log(string_join("Enacting ModelTransformation: ", read_attribute(pm, element, "name"))) output("Success: ready for MT execution") result = execute_operation(transformation_id, inputs, input_traceability_model) if (element_eq(result, read_root())): // Something went wrong! output("Failure") return False! else: // Check if we have to store traceability information if (element_neq(output_traceability_name, read_root())): // Yes, so store it // Note that we have overwritten the previous input traceability model, which is why it was a copy model_overwrite(input_traceability_model, get_entry_id(output_traceability_name), get_entry_id(output_traceability_type)) keys = dict_keys(outputs) while (set_len(keys) > 0): key = set_pop(keys) if (get_entry_id(output_map[key]) == ""): // New model model_create(result[key], output_map[key], get_entry_id(outputs[key]), "Model") else: model_overwrite(result[key], get_entry_id(output_map[key]), get_entry_id(outputs[key])) output("Success") return True! Element function PM_signature(pm : Element): Element all_data Element result String entry result = dict_create() all_data = allInstances(pm, "Data") while (set_len(all_data) > 0): entry = set_pop(all_data) dict_add(result, cast_string(read_attribute(pm, entry, "name")), cast_string(read_attribute(pm, entry, "type"))) return result! Void function enact_PM_activity(activity_to_task : Element, task_to_result : Element, pm : Element, element : String, mapping : Element): Boolean result pm_tasks = activity_to_task set_add(activity_to_task[element], get_taskname()) result = enact_action(pm, element, mapping) dict_add_fast(task_to_result, get_taskname(), result) while (other_has_output(get_taskname())): sleep(1) return! Void function enact_PM(pm : Element, mapping : Element): Element worklist String element String type Boolean result Element tuple Element counters Element join_nodes Element exec_nodes Element keys String key output("Success") // For all entries in the signature, not in the mapping, we add a mock location Element signature String mock_location Element mock_locations mock_locations = set_create() signature = PM_signature(pm) keys = dict_keys(signature) while (set_len(keys) > 0): key = set_pop(keys) if (bool_not(dict_in(mapping, key))): // Add mock location mock_location = "" while (get_entry_id(mock_location) != ""): mock_location = ".tmp/" + random_string(10) dict_add(mapping, key, mock_location) cmd_model_add(signature[key], mapping[key], "") set_add(mock_locations, mock_location) // Initialize Join counters counters = dict_create() join_nodes = allInstances(pm, "Join") while (set_len(join_nodes) > 0): dict_add(counters, set_pop(join_nodes), 0) // Initialize activity to task dictionary with empty sets Element activity_to_task Element task_to_activity Element task_to_result activity_to_task = dict_create() task_to_activity = dict_create() task_to_result = dict_create() exec_nodes = allInstances(pm, "Exec") while (set_len(exec_nodes) > 0): dict_add(activity_to_task, set_pop(exec_nodes), set_create()) // Create the worklist with the Start instance as first element worklist = set_create() set_add(worklist, set_pop(allInstances(pm, "Start"))) // Keep on iterating until we reach finish while (True): // Check if there are PM elements to expand if (set_len(worklist) > 0): // There is something we can do, so do it! element = set_pop(worklist) // Find the type (to see what to do with it) // this does not yet yield the type of transformation, if it is an Execution type = read_type(pm, element) // Some types have nothing to do, such as start and fork // Therefore, they are not mentioned in the following conditional if (type == "Finish"): // We have finished, so terminate break! elif (type == "Join"): // Only do this if all dependencies are fullfilled // So add to the counter of this Join dict_overwrite(counters, element, integer_addition(counters[element], 1)) // Now check whether we have enough tokens to execute the Join itself Integer required Integer got required = set_len(allIncomingAssociationInstances(pm, element, "Next")) + set_len(allIncomingAssociationInstances(pm, element, "Else")) got = counters[element] if (got == required): // Reset counter to 0 dict_overwrite(counters, element, 0) // And continue else: // We haven't gotten all yet, so we wait (i.e., continue without adding Next link to worklist) continue! elif (type == "Exec"): // Execute a transformation // This the difficult part! Element args String taskname args = list_create() list_append(args, activity_to_task) list_append(args, task_to_result) list_append(args, pm) list_append(args, element) list_append(args, mapping) taskname = spawn(enact_PM_activity, args) output(taskname + " : " + cast_string(read_attribute(pm, element, "name"))) dict_add(task_to_activity, taskname, element) continue! // We have finished the execution, so add all outgoing edges to the worklist Element all_next all_next = allAssociationDestinations(pm, element, "Next") String next while (set_len(all_next) > 0): next = set_pop(all_next) set_add(worklist, next) else: // No new tasks to spawn, so go and check on all running activities if (dict_len(task_to_result) > 0): // There are outputs! Element keys String task keys = dict_keys(task_to_result) while (set_len(keys) > 0): task = set_pop(keys) result = task_to_result[task] Element all_next all_next = allAssociationDestinations(pm, task_to_activity[task], "Next") String next while (set_len(all_next) > 0): next = set_pop(all_next) if (read_type(pm, next) == "Decision"): // Got decision node, so expand immediately if (result): set_add(worklist, set_pop(allAssociationDestinations(pm, next, "Then"))) else: set_add(worklist, set_pop(allAssociationDestinations(pm, next, "Else"))) else: // Other node, so just append for further processing set_add(worklist, next) set_remove(activity_to_task[task_to_activity[task]], task) dict_delete(task_to_result, task) dict_delete(task_to_activity, task) else: // No finished activities either, so we sleep for some time sleep(0.1) // Remove all mock locations again while (set_len(mock_locations) > 0): model_delete(get_entry_id(set_pop(mock_locations))) return ! String function cmd_help(): String result result = "" result = result + ("Model operations\n") result = result + (" model_add -- Add a new model\n") result = result + (" model_modify -- Modify an existing model\n") result = result + (" model_list -- List all models\n") result = result + (" model_list_full -- List all models with full info\n") result = result + (" model_overwrite -- Overwrites a model with an uploaded model, leaving all metadata\n") result = result + (" model_render -- Render a given model with a specified mapper\n") result = result + (" verify -- Check whether a model conforms to its metamodel\n") result = result + ("\n") result = result + ("Transformation-specific operations\n") result = result + (" transformation_add_MT -- Initialize a new model transformation\n") result = result + (" transformation_add_AL -- Initialize a new action language transformation\n") result = result + (" transformation_add_MANUAL -- Initialize a new manual transformation\n") result = result + (" transformation_execute -- Execute a transformation on a set of input models\n") result = result + (" transformation_list -- List all model transformations\n") result = result + (" transformation_list_full -- List all model transformations with permissions\n") result = result + (" transformation_detail -- List transformation details\n") result = result + (" transformation_between -- List all transformations between two metamodels\n") result = result + ("\n") result = result + ("Process operations\n") result = result + (" process_execute -- Execute a process model\n") result = result + ("\n") result = result + ("Model permission operations\n") result = result + (" permission_modify -- Change model permissions\n") result = result + (" permission_owner -- Change model owner\n") result = result + (" permission_group -- Change model group\n") result = result + ("\n") result = result + ("Group operations\n") result = result + (" group_create -- Create a group\n") result = result + (" group_delete -- Delete a group\n") result = result + (" group_owner_add -- Add group owner\n") result = result + (" group_owner_delete -- Remove group owner\n") result = result + (" group_join -- Add someone to your group\n") result = result + (" group_kick -- Kick someone from your group\n") result = result + (" group_list -- List all groups you are a member of\n") result = result + ("\n") if (is_admin(current_user_id)): result = result + ("Admin operations\n") result = result + (" admin_promote -- Promote a user to admin status\n") result = result + (" admin_demote -- Demote a user to normal status\n") result = result + ("\n") result = result + ("General operations\n") result = result + (" self-destruct -- Remove current user and revoke all permissions \n") result = result + (" exit -- Kill the current task, while retaining user\n") return result! String function cmd_model_add(type : String, name : String, code : String): // Model addition operation, which uses model upload commands of the compiler String location String type_id Element new_model String new_model_id type_id = get_entry_id(type) if (type_id != ""): // Type exists if (allow_read(current_user_id, type_id)): // And is readable create_folders(current_user_id, get_foldername(name)) //TODO check if bottommost existing model was writable by us if (get_entry_id(name) == ""): // Model doesn't exist yet Element mm mm = get_full_model(type_id, get_entry_id("formalisms/SimpleClassDiagrams")) if (element_eq(mm, read_root())): return "Type is not typed by formalisms/SimpleClassDiagrams: " + type! new_model = compile_model(code, mm) if (element_eq(new_model, read_root())): return "Compilation error"! model_create(new_model, name, type_id, "Model") return "Success"! else: return "Model exists: " + name! else: return "Permission denied to model: " + type! else: return "Model not found: " + type! String function cmd_process_execute(process : String, mapping : Element): // Execute a process model until it reaches termination String process_id process_id = get_entry_id(process) if (process_id != ""): if (allow_read(current_user_id, process_id)): Element pm pm = get_full_model(process_id, get_entry_id("formalisms/ProcessModel")) if (element_eq(pm, read_root())): return "Specified model cannot be interpreted as a ProcessModel: " + process! enact_PM(pm, mapping) return "Success"! else: return "Permission denied to model: " + process! else: return "Model not found: " + process! String function cmd_process_signature(process : String): // Execute a process model until it reaches termination String process_id String result Element signature Element keys String key process_id = get_entry_id(process) if (process_id != ""): if (allow_read(current_user_id, process_id)): Element pm pm = get_full_model(process_id, get_entry_id("formalisms/ProcessModel")) if (element_eq(pm, read_root())): return "Specified model cannot be interpreted as a ProcessModel: " + process! result = "Success: " signature = PM_signature(pm) keys = dict_keys(signature) while (set_len(keys) > 0): key = set_pop(keys) result = result + key + " : " + cast_string(signature[key]) + "\n" return result! else: return "Permission denied to model: " + process! else: return "Model not found: " + process! String function cmd_transformation_between(source_dict : String, target_dict : String): Element result Element subresult String tag String mm String mm_id Element links String link Element keys result = allInstances(core, "Transformation") // Iterate over all inputs keys = dict_keys(source_dict) while (set_len(keys) > 0): subresult = set_create() tag = set_pop(keys) mm = source_dict[tag] mm_id = get_entry_id(mm) if (mm_id != ""): links = allIncomingAssociationInstances(core, mm_id, "transformInput") while (set_len(links) > 0): link = set_pop(links) if (value_eq(read_attribute(core, link, "name"), tag)): // Correct tag, so make transformation a possibility set_add(subresult, readAssociationSource(core, link)) else: return "Model not found: " + mm! // Got a set of subresults now, which we use to find the overlap result = set_overlap(result, subresult) keys = dict_keys(target_dict) while (set_len(keys) > 0): subresult = set_create() tag = set_pop(keys) mm = target_dict[tag] mm_id = get_entry_id(mm) if (mm_id != ""): links = allIncomingAssociationInstances(core, mm_id, "transformOutput") while (set_len(links) > 0): link = set_pop(links) if (value_eq(read_attribute(core, link, "name"), tag)): // Correct tag, so make transformation a possibility set_add(subresult, readAssociationSource(core, link)) else: return "Model not found: " + mm! // Got a set of subresults now, which we use to find the overlap result = set_overlap(result, subresult) String r String transformation r = "Success: " while (set_len(result) > 0): transformation = set_pop(result) if (allow_read(current_user_id, transformation)): r = r + string_join(full_name(transformation), "\n") return r! String function cmd_model_rendered(model_name : String, mapper_name : String): Element trace_links String rendered String trace_link_id String allowed_rendered Element trace_links_2 String trace_link_2_id allowed_rendered = "Success: " trace_links = allOutgoingAssociationInstances(core, get_entry_id(model_name), "tracability") while (set_len(trace_links) > 0): trace_link_id = set_pop(trace_links) if (value_eq(read_attribute(core, trace_link_id, "type"), "CS_perceptualized")): rendered = readAssociationDestination(core, trace_link_id) trace_links_2 = allOutgoingAssociationInstances(core, rendered, "tracability") while (set_len(trace_links_2) > 0): trace_link_2_id = set_pop(trace_links_2) if (value_eq(read_attribute(core, readAssociationDestination(core, trace_link_2_id), "name"), mapper_name)): if (value_eq(read_attribute(core, trace_link_2_id, "type"), "CS_mapper")): allowed_rendered = string_join(allowed_rendered, read_attribute(core, rendered, "name")) + "\n" return allowed_rendered! String function cmd_model_render(model_name : String, mapper_name : String, rendered_name : String): String model_ID String mapper_ID String tracability_name Element inputs Element output_map Element rendered_model Element tracability_model Element result Element out_links String link String ID_rendered_M String ID_rendered_MM String ID_SCD String ID_tracability_MM String ID_tracability_M model_ID = get_entry_id(model_name) if (model_ID != ""): mapper_ID = get_entry_id(mapper_name) if (allow_read(current_user_id, model_ID)): if (mapper_ID != ""): if (allow_read(current_user_id, mapper_ID)): // Everything is fine; start the actual operation // Find metamodel to render to tracability_name = "tracability/" + rendered_name // Take the abstract syntax model and the previously rendered model inputs = dict_create() dict_add(inputs, "abstract", model_name) dict_add(inputs, "rendered", rendered_name) // Fetch the output types output_map = dict_create() out_links = allOutgoingAssociationInstances(core, mapper_ID, "transformOutput") while(set_len(out_links) > 0): link = set_pop(out_links) dict_add(output_map, read_attribute(core, link, "name"), full_name(readAssociationDestination(core, link))) ID_rendered_MM = get_entry_id(output_map["rendered"]) ID_SCD = get_entry_id("formalisms/SimpleClassDiagrams") ID_tracability_MM = get_entry_id("formalisms/Tracability") ID_tracability_M = get_entry_id(tracability_name) ID_rendered_M = get_entry_id(rendered_name) if (ID_rendered_M == ""): // Instantiate Element rendered rendered = get_full_model(ID_rendered_MM, ID_SCD) if (element_eq(rendered, read_root())): return "Rendered metamodel doesn't conform to formalisms/SimpleClassDiagrams"! rendered_model = instantiate_model(rendered) model_create(rendered_model, rendered_name, ID_rendered_MM, "Model") // Tracability model won't exist either tracability_model = instantiate_model(get_full_model(ID_tracability_MM, ID_SCD)) model_create(tracability_model, tracability_name, ID_tracability_MM, "Model") ID_rendered_M = get_entry_id(rendered_name) ID_tracability_M = get_entry_id(tracability_name) else: // Read out tracability model tracability_model = get_full_model(ID_tracability_M, ID_tracability_MM) if (element_eq(tracability_model, read_root())): return "Tracability model not typed by Tracability metamodel: " + tracability_name! // Do the operation itself! result = execute_operation(mapper_ID, inputs, tracability_model) // Overwrite the previous rendered model model_overwrite(result["rendered"], ID_rendered_M, ID_rendered_MM) // Tracability updated in-place model_overwrite(tracability_model, ID_tracability_M, ID_tracability_MM) if (element_eq(tracability_model, read_root())): return "Tracability model not typed by Tracability metamodel: " + tracability_name! // Link all information in the megamodel String tr_link tr_link = instantiate_link(core, "tracability", "", get_entry_id(model_name), ID_rendered_M) instantiate_attribute(core, tr_link, "type", "CS_perceptualized") tr_link = instantiate_link(core, "tracability", "", ID_rendered_M, get_entry_id(mapper_name)) instantiate_attribute(core, tr_link, "type", "CS_mapper") // Output the resulting model String value value = JSON_print(result["rendered"]) return ("Success: " + value) ! else: return "Permission denied to model: " + mapper_name! else: return "Model not found: " + mapper_name! else: return "Permission denied to model: " + model_name! else: return "Model not found: " + model_name! Boolean function do_spawn_modify(model_name : String, write : Boolean): output("Please edit this model before sending next input: " + model_name) input() return False! Boolean function do_spawn_activity(transformation_id : String, tracability_name : String, inputs : Element, outputs : Element, output_map : Element): Element lst Element returnvalue String taskname lst = list_create() returnvalue = set_create() list_append(lst, returnvalue) list_append(lst, transformation_id) list_append(lst, tracability_name) list_append(lst, inputs) list_append(lst, outputs) list_append(lst, output_map) taskname = spawn(spawn_activity, lst) output("Spawned activity on task: " + taskname) while (set_len(returnvalue) == 0): sleep(0.1) output("Finished task: " + taskname) return cast_boolean(set_pop(returnvalue))! Void function spawn_activity(returnvalue : Element, transformation_id : String, tracability_name : String, inputs : Element, outputs : Element, output_map : Element): Element result Element keys String key if (read_type(core, transformation_id) == "ActionLanguage"): output("Success: ready for AL execution") elif (read_type(core, transformation_id) == "ManualOperation"): output("Success: ready for MANUAL execution") else: output("Success: ready for MT execution") // Do tracability Element tracability_model if (tracability_name != ""): // Check if exists if (get_entry_id(tracability_name) == ""): // No, so create tracability_model = instantiate_model(get_full_model(get_entry_id("formalisms/Tracability"), get_entry_id("formalisms/SimpleClassDiagrams"))) model_create(tracability_model, tracability_name, get_entry_id("formalisms/Tracability"), "Model") else: // Yes, so read out tracability_model = get_full_model(get_entry_id(tracability_name), get_entry_id("formalisms/Tracability")) else: tracability_model = read_root() result = execute_operation(transformation_id, inputs, tracability_model) // Flush tracability again, just to be sure if (tracability_name != ""): model_overwrite(tracability_model, get_entry_id(tracability_name), get_entry_id("formalisms/Tracability")) // Now write out the models again if (element_eq(result, read_root())): // Something went wrong! set_add(returnvalue, False) output("Failure") else: keys = dict_keys(outputs) while (set_len(keys) > 0): key = set_pop(keys) if (get_entry_id(outputs[key]) == ""): // New model model_create(result[key], outputs[key], get_entry_id(output_map[key]), "Model") else: model_overwrite(result[key], get_entry_id(outputs[key]), get_entry_id(output_map[key])) set_add(returnvalue, True) output("Success") while (other_has_output(get_taskname())): sleep(1) return! String function cmd_transformation_execute(transformation_name : String, source_models : Element, target_models : Element, tracability_name : String): // Execute a transformation, whatever type it is // First we detect the type, so we know how to prepare for invocation String transformation_id String exact_type Element sources Element targets String source String target Element inputs Element outputs Element output_map Element trace_links String target_model_name String source_model_name String source_model_ID String assoc_name transformation_id = get_entry_id(transformation_name) if (transformation_id != ""): if (allow_read(current_user_id, transformation_id)): if (is_nominal_instance(core, transformation_id, "Transformation")): // Read out source and target links inputs = dict_create() sources = allOutgoingAssociationInstances(core, transformation_id, "transformInput") while (set_len(sources) > 0): source = set_pop(sources) assoc_name = read_attribute(core, source, "name") if (dict_in(source_models, assoc_name)): source_model_name = source_models[assoc_name] else: return "Source model not bound: " + assoc_name! source_model_ID = get_entry_id(source_model_name) if (source_model_ID != ""): if (allow_read(current_user_id, source_model_ID)): // Check for conformance to the requested metamodel dict_add(inputs, assoc_name, source_model_name) continue! else: return "Permission denied to model: " + source_model_name! else: return "Model not found: " + source_model_name! targets = allOutgoingAssociationInstances(core, transformation_id, "transformOutput") outputs = dict_create() output_map = dict_create() while (set_len(targets) > 0): target = set_pop(targets) assoc_name = read_attribute(core, target, "name") if (dict_in(target_models, assoc_name)): target_model_name = target_models[assoc_name] if (get_entry_id(target_model_name) == ""): // Doesn't exist yet, so we can easily create if (get_entry_id(get_foldername(target_model_name)) == ""): return "Folder not found: " + get_foldername(target_model_name)! else: if (allow_write(current_user_id, get_entry_id(get_foldername(target_model_name)))): dict_add(output_map, assoc_name, full_name(readAssociationDestination(core, target))) dict_add(outputs, assoc_name, target_model_name) else: return "Permission denied to folder: " + get_foldername(target_model_name)! else: // Already exists, so we need to check for write access if (allow_write(current_user_id, get_entry_id(target_model_name))): dict_add(output_map, assoc_name, read_attribute(core, readAssociationDestination(core, target), "name")) dict_add(outputs, assoc_name, target_model_name) else: return "Permission denied to model: " + target_model_name! if (do_spawn_activity(transformation_id, tracability_name, inputs, outputs, output_map)): return "Success"! else: return "Failure"! else: return "Model is not executable: " + transformation_name! else: return "Permission denied to model: " + transformation_name! else: return "Model not found: " + transformation_name! String function cmd_verify(model_name : String, metamodel_name : String): // Check whether a model conforms to its specification (with the selected type mapping) String model_id String result Element inputs model_id = get_entry_id(model_name) if (model_id != ""): if (allow_read(current_user_id, model_id)): if (get_entry_id(metamodel_name) != ""): if (allow_read(current_user_id, get_entry_id(metamodel_name))): Element m m = get_full_model(get_entry_id(model_name), get_entry_id(metamodel_name)) if (element_eq(m, read_root())): return "No conformance relation can be found between these models"! return string_join("Success: ", conformance_scd(m))! else: return "Permission denied to model: " + metamodel_name! else: return "Model not found: " + metamodel_name! else: return "Permission denied to model: " + model_name! else: return "Model not found: " + model_name! String function cmd_model_overwrite(model_name : String, metamodel_name : String): // Overwrites an existing model without changing any metadata String model_id String type_id Element new_model model_id = get_entry_id(model_name) if (model_id != ""): if (allow_write(current_user_id, model_id)): type_id = set_pop(allAssociationDestinations(core, model_id, "instanceOf")) if (allow_read(current_user_id, type_id)): Element mm mm = get_full_model(get_entry_id(metamodel_name), get_entry_id("formalisms/SimpleClassDiagrams")) if (element_eq(mm, read_root())): return "Metamodel does not conform to formalisms/SimpleClassDiagrams: " + metamodel_name! output("Waiting for model constructors...") new_model = compile_model(input(), mm) if (element_eq(new_model, read_root())): return "Compilation error"! model_overwrite(new_model, model_id, get_entry_id(metamodel_name)) return "Success"! else: return string_join("Permission denied to model: ", full_name(type_id))! else: return "Permission denied to model: " + model_name! else: return "Model not found: " + model_name! String function cmd_model_modify(model_name : String, metamodel_name : String): // Model modify operation, which uses the mini_modify.alc operations, though with extensions for access control String model_id String type_id model_id = get_entry_id(model_name) if (model_id != ""): if (allow_read(current_user_id, model_id)): type_id = set_pop(allAssociationDestinations(core, model_id, "instanceOf")) if (allow_read(current_user_id, type_id)): Element new_model new_model = get_full_model(model_id, get_entry_id(metamodel_name)) if (element_eq(new_model, read_root())): return "No conformance relation can be found between these models"! modify(new_model, allow_write(current_user_id, model_id)) if (allow_write(current_user_id, model_id)): // Overwrite the modified model model_overwrite(new_model, model_id, get_entry_id(metamodel_name)) return "Success"! else: return string_join("Permission denied to model: ", full_name(type_id))! else: return "Permission denied to model: " + model_name! else: return "Model not found: " + model_name! Void function model_delete(model_id : String): if (read_type(core, model_id) == "Folder"): // Folder, so delete all containing elements as well! Element elems elems = allAssociationDestinations(core, model_id, "contains") while (set_len(elems) > 0): model_delete(set_pop(elems)) // Delete self model_delete_element(core, model_id) else: // Only delete this element model_delete_element(core, model_id) return! String function cmd_model_delete(model_name : String): String model_id model_id = get_entry_id(model_name) if (model_id != ""): if (allow_write(current_user_id, model_id)): model_delete(model_id) return "Success"! else: return "Permission denied to model: " + model_name! else: return "Model not found: " + model_name! String function cmd_model_list(location : String): // List all models if (get_entry_id(location) != ""): if (allow_read(current_user_id, get_entry_id(location))): Element models String result String m result = "Success: " models = allAssociationDestinations(core, get_entry_id(location), "contains") while (set_len(models) > 0): m = set_pop(models) if (is_nominal_instance(core, m, "Folder")): result = result + (get_filename(read_attribute(core, m, "name")) + "/\n") else: result = result + (get_filename(read_attribute(core, m, "name")) + "\n") return result! else: return "Permission denied to folder: " + location! else: return "Location not found: " + location! String function cmd_model_list_full(location : String): // List all models with full info if (get_entry_id(location) != ""): if (allow_read(current_user_id, get_entry_id(location))): Element models String m String permissions String owner String group String name String type String result result = "Success: " models = allAssociationDestinations(core, get_entry_id(location), "contains") while (set_len(models) > 0): m = set_pop(models) permissions = read_attribute(core, m, "permissions") owner = read_attribute(core, set_pop(allAssociationDestinations(core, m, "owner")), "name") group = read_attribute(core, set_pop(allAssociationDestinations(core, m, "group")), "name") if (is_nominal_instance(core, m, "Folder")): name = get_filename(read_attribute(core, m, "name")) + "/" else: name = get_filename(read_attribute(core, m, "name")) result = result + permissions + " " + owner + " " + group + " " + name + "\n" return result! else: return "Permission denied to folder: " + location! else: return "Location not found: " + location! String function cmd_transformation_add_MANUAL(source_models : Element, target_models : Element, operation_name : String): return transformation_add(source_models, target_models, operation_name, "manual")! String function cmd_transformation_add_AL(source_models : Element, target_models : Element, operation_name : String): return transformation_add(source_models, target_models, operation_name, "actionlanguage")! String function transformation_add(source_models : Element, target_models : Element, operation_name : String, operation_type : String): // Add a manual transformation model String model_id Element models Element source Element target String name Element all_formalisms Element formalism_map Element merged_formalism String merged_formalism_id String source_formalism_id String tracability_link Element fused Element keys String key Element mm source = dict_create() target = dict_create() all_formalisms = set_create() formalism_map = set_create() fused = set_create() keys = dict_keys(source_models) while (set_len(keys) > 0): key = set_pop(keys) name = source_models[key] model_id = get_entry_id(name) if (model_id != ""): if (allow_read(current_user_id, model_id)): if (bool_not(dict_in(source, key))): dict_add(source, key, model_id) mm = get_full_model(model_id, get_entry_id("formalisms/SimpleClassDiagrams")) if (element_eq(mm, read_root())): return "Transformation source type not in formalisms/SimpleClassDiagrams hierarchy: " + key! if (bool_not(set_in(fused, key))): set_add_node(formalism_map, create_tuple(key, mm)) set_add(fused, key) if (bool_not(set_in(all_formalisms, model_id))): set_add(all_formalisms, model_id) else: return "Name already selected for source: " + key! else: return "Permission denied to model: " + name! else: return "Model not found: " + name! keys = dict_keys(target_models) while (set_len(keys) > 0): key = set_pop(keys) name = target_models[key] model_id = get_entry_id(name) if (model_id != ""): if (allow_read(current_user_id, model_id)): if (bool_not(dict_in(target, key))): dict_add(target, key, model_id) mm = get_full_model(model_id, get_entry_id("formalisms/SimpleClassDiagrams")) if (element_eq(mm, read_root())): return "Transformation target type not in formalisms/SimpleClassDiagrams hierarchy: " + key! if (bool_not(set_in(fused, key))): set_add_node(formalism_map, create_tuple(key, mm)) set_add(fused, key) if (bool_not(set_in(all_formalisms, model_id))): set_add(all_formalisms, model_id) else: return "Name already selected for target: " + key! else: return "Permission denied to model: " + name! else: return "Model not found: " + name! if (get_entry_id(operation_name) == ""): // Write out a merged metamodel containing all these models: this is the MM for the manual operation // New location is available, so write if (dict_len(source_models) + dict_len(target_models) > 0): merged_formalism = model_fuse(formalism_map) model_create(merged_formalism, "merged/" + operation_name, get_entry_id("formalisms/SimpleClassDiagrams"), "Model") do_spawn_modify("merged/" + operation_name, True) merged_formalism = get_full_model(get_entry_id("merged/" + operation_name), get_entry_id("formalisms/SimpleClassDiagrams")) if (operation_type == "manual"): if (dict_len(source_models) + dict_len(target_models) == 0): return "Manual activity needs at least one formalism in its input or output signature!"! // Finished with all information, now create the model itself! Element m m = get_full_model(get_entry_id("formalisms/ManualOperation"), get_entry_id("formalisms/SimpleClassDiagrams")) if (element_eq(m, read_root())): log("Error when opening ManualOperation: no conformance relation found") return "Error when opening ManualOperation: no conformance relation found"! model_create(instantiate_model(m), operation_name, get_entry_id("formalisms/ManualOperation"), "ManualOperation") model_id = get_entry_id(operation_name) elif (operation_type == "actionlanguage"): // Finished with all information, now create the model itself! output("Waiting for code constructors...") Element compiled compiled = compile_code(input()) if (element_eq(compiled, read_root())): return "Compilation error"! add_code_model(get_full_model(get_entry_id("formalisms/ActionLanguage"), get_entry_id("formalisms/SimpleClassDiagrams")), "AL/" + operation_name, compiled) model_create(import_node("AL/" + operation_name), operation_name, get_entry_id("formalisms/ActionLanguage"), "ActionLanguage") model_id = get_entry_id(operation_name) if (dict_len(source_models) + dict_len(target_models) > 0): merged_formalism_id = get_entry_id("merged/" + operation_name) // Add tracability links at this level while (set_len(all_formalisms) > 0): source_formalism_id = set_pop(all_formalisms) tracability_link = instantiate_link(core, "tracability", "", merged_formalism_id, source_formalism_id) instantiate_attribute(core, tracability_link, "type", "merged") tracability_link = instantiate_link(core, "tracability", "", model_id, merged_formalism_id) instantiate_attribute(core, tracability_link, "type", "operatesOn") // Extend metadata with info on source and target String link String dst keys = dict_keys(source) while (set_len(keys) > 0): key = set_pop(keys) link = instantiate_link(core, "transformInput", "", model_id, source[key]) instantiate_attribute(core, link, "name", key) keys = dict_keys(target) while (set_len(keys) > 0): key = set_pop(keys) link = instantiate_link(core, "transformOutput", "", model_id, target[key]) instantiate_attribute(core, link, "name", key) return "Success"! else: return "Model exists: " + operation_name! String function cmd_transformation_add_MT(source_models : Element, target_models : Element, operation_name : String): // Add a model transformation model // Just a usual model instantiation, but need to add the source and target links based on user info String ramified_metamodel_id Element ramified_metamodel String model_id Element models Element links String link_id Element supported Element source Element target String name String new_model_id String merged_link_id Element links_merged String merged_formalism Element keys String key Element mm Element to_ramify String source_formalism_id String merged_formalism_id String tracability_link source = dict_create() target = dict_create() to_ramify = set_create() if (dict_len(source_models) + dict_len(target_models) == 0): return "Model transformation needs at least one formalism in its input or output signature!"! keys = dict_keys(source_models) while (set_len(keys) > 0): key = set_pop(keys) name = source_models[key] model_id = get_entry_id(name) if (model_id != ""): if (allow_read(current_user_id, name)): // Check whether or not it is formalisms/SimpleClassDiagrams if (is_typed_by(model_id, get_entry_id("formalisms/SimpleClassDiagrams"))): if (bool_not(dict_in(source, key))): dict_add(source, key, model_id) mm = get_full_model(model_id, get_entry_id("formalisms/SimpleClassDiagrams")) if (element_eq(mm, read_root())): return "ModelTransformation source type not in formalisms/SimpleClassDiagrams hierarchy: " + name! set_add_node(to_ramify, create_tuple(key, mm)) else: return "Name was already assigned a metamodel: " + key! else: return "Model not supported for RAMification: " + name! else: return "Permission denied: " + name! else: return "Model not found: " + name! keys = dict_keys(target_models) while (set_len(keys) > 0): key = set_pop(keys) name = target_models[key] model_id = get_entry_id(name) if (model_id != ""): if (allow_read(current_user_id, name)): if (is_typed_by(model_id, get_entry_id("formalisms/SimpleClassDiagrams"))): if (bool_not(dict_in(target, key))): if (dict_in(source, key)): if (value_eq(model_id, source[key])): dict_add(target, key, model_id) // Don't add to to_ramify, as it is already in there! else: return "Name in output cannot have different type than input: " + key! else: dict_add(target, key, model_id) mm = get_full_model(model_id, get_entry_id("formalisms/SimpleClassDiagrams")) if (element_eq(mm, read_root())): return "ModelTransformation target type not in formalisms/SimpleClassDiagrams hierarchy: " + name! set_add_node(to_ramify, create_tuple(key, mm)) else: return "Name was already assigned a metamodel: " + key! else: return "Model not supported for RAMification: " + name! else: return "Permission denied: " + name! else: return "Model not found: " + name! merged_formalism = model_fuse(to_ramify) model_create(merged_formalism, "merged/" + operation_name, get_entry_id("formalisms/SimpleClassDiagrams"), "Model") do_spawn_modify("merged/" + operation_name, True) merged_formalism = get_full_model(get_entry_id("merged/" + operation_name), get_entry_id("formalisms/SimpleClassDiagrams")) model_overwrite(merged_formalism, get_entry_id("merged/" + operation_name), get_entry_id("formalisms/SimpleClassDiagrams")) ramified_metamodel = ramify(merged_formalism) model_create(ramified_metamodel, "RAMified/" + operation_name, get_entry_id("formalisms/SimpleClassDiagrams"), "Model") ramified_metamodel_id = get_entry_id("RAMified/" + operation_name) // Now use the RAMified model to create the instance if (get_entry_id(operation_name) == ""): String new_model // Finished with all information, now create the model itself! output("Waiting for model constructors...") new_model = compile_model(input(), get_full_model(ramified_metamodel_id, get_entry_id("formalisms/SimpleClassDiagrams"))) if (element_eq(new_model, read_root())): return "Compilation error"! model_create(new_model, operation_name, ramified_metamodel_id, "ModelTransformation") model_id = get_entry_id(operation_name) // Write out a merged metamodel containing all these models: this is the MM for the manual operation // New location is available, so write model_create(merged_formalism, "merged/" + operation_name, get_entry_id("formalisms/SimpleClassDiagrams"), "Model") merged_formalism_id = get_entry_id("merged/" + operation_name) // Add tracability links at this level tracability_link = instantiate_link(core, "tracability", "", model_id, merged_formalism_id) instantiate_attribute(core, tracability_link, "type", "operatesOn") // Add tracability links at this level tracability_link = instantiate_link(core, "tracability", "", merged_formalism_id, ramified_metamodel_id) instantiate_attribute(core, tracability_link, "type", "RAMified") // Extend metadata with info on source and target String link String dst keys = dict_keys(source) while (set_len(keys) > 0): key = set_pop(keys) dst = source[key] link = instantiate_link(core, "transformInput", "", model_id, dst) instantiate_attribute(core, link, "name", key) keys = dict_keys(target) while (set_len(keys) > 0): key = set_pop(keys) dst = target[key] link = instantiate_link(core, "transformOutput", "", model_id, dst) instantiate_attribute(core, link, "name", key) return "Success"! else: return "Model exists: " + operation_name! String function cmd_permission_modify(model_name : String, permissions : String): Integer permission String model_id model_id = get_entry_id(model_name) if (model_id != ""): if (get_relation_to_model(current_user_id, model_id) == 0): Boolean fail Integer i i = 0 if (string_len(permissions) != 3): fail = True while (i < 3): permission = cast_integer(string_get(permissions, i)) if (bool_or(permission < 0, permission > 2)): fail = True break! i = i + 1 if (bool_not(fail)): unset_attribute(core, model_id, "permissions") instantiate_attribute(core, model_id, "permissions", permissions) return "Success"! else: return "Permission has incorrect format: must be a string of three characters, with each character being a digit between 0 and 2"! else: return "Permission denied to model: " + model_name! else: return "Model not found: " + model_name! String function cmd_permission_owner(model_name : String, new_user_name : String): String model_id String new_user_id model_id = get_entry_id(model_name) if (model_id != ""): if (bool_or(get_relation_to_model(current_user_id, model_id) == 0, is_admin(current_user_id))): new_user_id = get_user_id(new_user_name) if (new_user_id != ""): model_delete_element(core, set_pop(allOutgoingAssociationInstances(core, model_id, "owner"))) instantiate_link(core, "owner", "", model_id, new_user_id) return "Success"! else: return "No such user: " + new_user_name! else: return "Permission denied to model: " + model_name! else: return "Model not found: " + model_name! String function cmd_permission_group(model_name : String, new_group_name : String): String model_id String group_id model_id = get_entry_id(model_name) if (model_id != ""): if (bool_or(get_relation_to_model(current_user_id, model_id) == 0, is_admin(current_user_id))): group_id = get_group_id(new_group_name) if (group_id != ""): model_delete_element(core, set_pop(allOutgoingAssociationInstances(core, model_id, "group"))) instantiate_link(core, "group", "", model_id, group_id) return "Success"! else: return "No such group: " + new_group_name! else: return "Permission denied to model: " + model_name! else: return "Model not found: " + model_name! String function cmd_group_create(group_name : String): // Create a new group and become its owner String group_id String name group_id = get_group_id(group_name) if (group_id == ""): group_id = instantiate_node(core, "Group", "") instantiate_attribute(core, group_id, "name", group_name) instantiate_link(core, "belongsTo", "", current_user_id, group_id) instantiate_link(core, "owner", "", group_id, current_user_id) return "Success"! else: return "Group exists: " + group_name! String function cmd_group_delete(group_name : String): // Delete an existing group String group_id group_id = get_group_id(group_name) if (group_id != ""): if (allow_group_modify(current_user_id, group_id)): model_delete_element(core, group_id) return "Success"! else: return "Permission denied to group: " + group_name! else: return "Group not found: " + group_name! String function cmd_group_owner_add(group_name : String, other_user_name : String): // Add an owner to your group String group_id String other_user_id group_id = get_group_id(group_name) if (group_id != ""): if (allow_group_modify(current_user_id, group_id)): other_user_id = get_user_id(other_user_name) if (other_user_id != ""): if (set_in(allAssociationDestinations(core, group_id, "owner"), other_user_id)): instantiate_link(core, "owner", "", group_id, other_user_id) if (set_in(allAssociationDestinations(core, other_user_id, "belongsTo"), group_id)): instantiate_link(core, "belongsTo", "", other_user_id, group_id) return "Success"! else: return "User is already the owner!"! else: return "User not found: " + other_user_name! else: return "Permission denied to group: " + group_name! else: return "Group not found: " + group_name! String function cmd_group_owner_delete(group_name : String, other_user_name : String): // Remove an owner from your group String group_id String other_user_id group_id = get_group_id(group_name) if (group_id != ""): if (allow_group_modify(current_user_id, group_id)): other_user_id = get_user_id(other_user_name) if (other_user_id != ""): if (set_in(allAssociationDestinations(core, other_user_id, "belongsTo"), group_id)): if (set_in(allAssociationDestinations(core, group_id, "owner"), other_user_id)): Element overlap overlap = set_overlap(allIncomingAssociationInstances(core, group_id, "owner"), allOutgoingAssociationInstances(core, other_user_id, "owner")) model_delete_element(core, set_pop(overlap)) return "Success"! else: return "User is not an owner of the group!"! else: return "User is not a member of the group!"! else: return "User not found: " + other_user_name! else: return "Permission denied to group: " + group_name! else: return "Group not found: " + group_name! String function cmd_group_join(group_name : String, other_user_name : String): // Add someone to your group String group_id String other_user_id group_id = get_group_id(group_name) if (group_id != ""): if (allow_group_modify(current_user_id, group_id)): other_user_id = get_user_id(other_user_name) if (other_user_id != ""): if (set_in(allOutgoingAssociationInstances(core, other_user_id, "belongsTo"), group_id)): instantiate_link(core, "belongsTo", "", other_user_id, group_id) return "Success"! else: return "User is already a member of the group!"! else: return "User not found: " + other_user_name! else: return "Permission denied to group: " + group_name! else: return "Group not found: " + group_name! String function cmd_group_kick(group_name : String, other_user_name : String): // Remove someone from your group String group_id String other_user_id group_id = get_group_id(group_name) if (group_id != ""): if (allow_group_modify(current_user_id, group_id)): other_user_id = get_user_id(other_user_name) if (other_user_id != ""): Element overlap if (set_in(allAssociationDestinations(core, other_user_id, "belongsTo"), group_id)): overlap = set_overlap(allIncomingAssociationInstances(core, group_id, "belongsTo"), allOutgoingAssociationInstances(core, other_user_id, "belongsTo")) model_delete_element(core,set_pop(overlap)) // Check if user was an owner as well if (set_in(allAssociationDestinations(core, group_id, "owner"), other_user_id)): overlap = set_overlap(allIncomingAssociationInstances(core, other_user_id, "owner"), allOutgoingAssociationInstances(core, group_id, "owner")) model_delete_element(core, set_pop(overlap)) return "Success"! else: return "User is not a member of the group!"! else: return "User not found: " + other_user_name! else: return "Permission denied to group: " + group_name! else: return "Group not found: " + group_name! String function cmd_group_list(): // List all groups you are a member of (and whether you are admin or not!) Element groups String group_id String admin String result result = "" groups = allAssociationDestinations(core, current_user_id, "belongsTo") while (set_len(groups) > 0): group_id = set_pop(groups) if (set_in(allAssociationDestinations(core, group_id, "owner"), current_user_id)): admin = " A " else: admin = " " result = result + (string_join(admin, read_attribute(core, group_id, "name")) + "\n") return result! String function cmd_admin_promote(other_user_name : String): // Promote a user to admin status if (is_admin(current_user_id)): String other_user_id other_user_id = get_user_id(other_user_name) if (other_user_id != ""): unset_attribute(core, other_user_id, "admin") instantiate_attribute(core, other_user_id, "admin", True) return "Success"! else: return "User not found: " + other_user_name! else: return "Permission denied to administrate: " + other_user_name! String function cmd_admin_demote(other_user_name : String): // Demote a user to normal status if (is_admin(current_user_id)): String other_user_id other_user_id = get_user_id(other_user_name) if (other_user_id != ""): unset_attribute(core, other_user_id, "admin") instantiate_attribute(core, other_user_id, "admin", False) return "Success"! else: return "User not found: " + other_user_name! else: return "Permission denied to administrate: " + other_user_name! String function cmd_service_register(service_name : String): // Active a service for this specific user if (get_service_id(service_name) == ""): String service service = instantiate_node(core, "Service", "") instantiate_attribute(core, service, "name", service_name) instantiate_attribute(core, service, "port", get_taskname()) output("Success: " + get_taskname()) // Wait until we can stop the service while (cast_value(input()) != "\"service_stop\""): output("Service is running on this task: stop it by sending 'service_stop'") model_delete_element(core, service) // Service terminated return "Success"! else: return "Service already exists: " + service_name! String function cmd_user_password(user_name : String, new_password : String): if (bool_or(current_user_id == get_user_id(user_name), is_admin(current_user_id))): if (get_user_id(user_name) != ""): instantiate_attribute(core, get_user_id(user_name), "password", hash(new_password)) return "Success"! else: return "No such user: " + user_name! else: return "Permission denied to user: " + user_name! String function cmd_transformation_signature(transformation_name : String): String model_id model_id = get_entry_id(transformation_name) if (model_id != ""): if (is_nominal_instance(core, model_id, "Transformation")): if (allow_read(current_user_id, transformation_name)): String result String elem Element inputs Element outputs result = "Success: " inputs = allOutgoingAssociationInstances(core, model_id, "transformInput") while (set_len(inputs) > 0): elem = set_pop(inputs) result = string_join(string_join(string_join(string_join(result + "I ", read_attribute(core, elem, "name")), " "), full_name(readAssociationDestination(core, elem))), "\n") outputs = allOutgoingAssociationInstances(core, model_id, "transformOutput") while (set_len(outputs) > 0): elem = set_pop(outputs) result = string_join(string_join(string_join(string_join(result + "O ", read_attribute(core, elem, "name")), " "), full_name(readAssociationDestination(core, elem))), "\n") return result! else: return "Permission denied to operation: " + transformation_name! else: return "Model is not an operation: " + transformation_name! else: return "No such operation: " + transformation_name! String function cmd_model_types(model_name : String): if (get_entry_id(model_name) != ""): String model_id model_id = get_entry_id(model_name) Element types String type String result result = "Success: " types = allAssociationDestinations(core, model_id, "instanceOf") while (set_len(types) > 0): type = set_pop(types) result = string_join(result, full_name(type) + "\n") return result! else: return "No such model: " + model_name! String function cmd_folder_create(folder_name : String): if (get_entry_id(folder_name) == ""): if (element_neq(create_folders(current_user_id, folder_name), read_root())): return "Success"! else: return "Permission denied to folder: " + folder_name! else: return "Folder alreay exists: " + folder_name! String function cmd_conformance_add(model_name : String, metamodel_name : String): // Create a new instanceOf relation now String instance_of instance_of = instantiate_link(core, "instanceOf", "", get_entry_id(model_name), get_entry_id(metamodel_name)) return "Success"! Void function user_function_skip_init(user_id : String): String cmd String result current_user_id = user_id caches = dict_create() dict_add_fast(caches, "models", dict_create()) dict_add_fast(caches, "users", dict_create()) dict_add_fast(caches, "full_name", dict_create()) // Find root element Element elems String elem elems = allInstances(core, "Folder") while (set_len(elems) > 0): elem = set_pop(elems) if (value_eq(read_attribute(core, elem, "name"), "")): if (set_len(allIncomingAssociationInstances(core, elem, "contains")) == 0): dict_add_fast(caches, "root", elem) break! output("Welcome to the Model Management Interface v2.0!") output("Use the 'help' command for a list of possible commands") while (True): cmd = input() if (cmd == "help"): output(cmd_help()) elif (cmd == "model_add"): output(cmd_model_add(single_input("Model type?"), single_input("Model name?"), single_input("Model textual representation?"))) elif (cmd == "process_execute"): output(cmd_process_execute(single_input("Process to execute?"), dict_input("Model bindings to use?"))) elif (cmd == "process_signature"): output(cmd_process_signature(single_input("Process to execute?"))) elif (cmd == "transformation_between"): output(cmd_transformation_between(dict_input("Source signature?"), dict_input("Target signature?"))) elif (cmd == "model_render"): output(cmd_model_render(single_input("Model name?"), single_input("Mapper name?"), single_input("Rendered name?"))) elif (cmd == "model_rendered"): output(cmd_model_rendered(single_input("Model name?"), single_input("Mapper name?"))) elif (cmd == "transformation_execute"): output(cmd_transformation_execute(single_input("Transformation name?"), dict_input("Source models?"), dict_input("Target models?"), single_input("Tracability model?"))) elif (cmd == "verify"): result = cmd_verify(single_input("Model name?"), single_input("Metamodel name?")) if (result != ""): output(result) elif (cmd == "model_overwrite"): output(cmd_model_overwrite(single_input("Model name?"), single_input("Metamodel name?"))) elif (cmd == "model_modify"): output(cmd_model_modify(single_input("Model name?"), single_input("Metamodel name?"))) elif (cmd == "model_delete"): output(cmd_model_delete(single_input("Model name?"))) elif (cmd == "model_list"): output(cmd_model_list(single_input("Location?"))) elif (cmd == "model_list_full"): output(cmd_model_list_full(single_input("Location?"))) elif (cmd == "transformation_add_MANUAL"): output(cmd_transformation_add_MANUAL(dict_input("Source models?"), dict_input("Target models?"), single_input("Operation name?"))) elif (cmd == "transformation_add_AL"): output(cmd_transformation_add_AL(dict_input("Source models?"), dict_input("Target models?"), single_input("Operation name?"))) elif (cmd == "transformation_add_MT"): output(cmd_transformation_add_MT(dict_input("Source models?"), dict_input("Target models?"), single_input("Operation name?"))) elif (cmd == "permission_modify"): output(cmd_permission_modify(single_input("Model name?"), single_input("Permissions?"))) elif (cmd == "permission_owner"): output(cmd_permission_owner(single_input("Model name?"), single_input("New owning user?"))) elif (cmd == "permission_group"): output(cmd_permission_group(single_input("Model name?"), single_input("New owning group?"))) elif (cmd == "group_create"): output(cmd_group_create(single_input("New group name?"))) elif (cmd == "group_delete"): output(cmd_group_delete(single_input("Group name?"))) elif (cmd == "group_owner_add"): output(cmd_group_owner_add(single_input("Group name?"), single_input("User name?"))) elif (cmd == "group_owner_delete"): output(cmd_group_owner_delete(single_input("Group name?"), single_input("User name?"))) elif (cmd == "group_join"): output(cmd_group_join(single_input("Group name?"), single_input("User name?"))) elif (cmd == "group_kick"): output(cmd_group_kick(single_input("Group name?"), single_input("User name?"))) elif (cmd == "group_list"): output(cmd_group_list()) elif (cmd == "admin_promote"): output(cmd_admin_promote(single_input("User name?"))) elif (cmd == "admin_demote"): output(cmd_admin_demote(single_input("User name?"))) elif (cmd == "service_register"): output(cmd_service_register(single_input("Service name?"))) elif (cmd == "user_password"): output(cmd_user_password(single_input("User name?"), single_input("New password?"))) elif (cmd == "transformation_read_signature"): output(cmd_transformation_signature(single_input("Transformation name?"))) elif (cmd == "verbose"): set_verbose(True) elif (cmd == "quiet"): set_verbose(False) elif (cmd == "self-destruct"): // Delete user from Core Formalism model_delete_element(core, user_id) return ! elif (cmd == "user_logout"): // TODO cmd = "FAIL" elif (cmd == "exit"): // Exit by actually removing the user and decoupling it from all of its models // Restarting with the same user name will NOT grant you access to anything of the previous user with that same name // as the current user will have been deleted return ! elif (cmd == "folder_create"): output(cmd_folder_create(single_input("Folder name?"))) elif (cmd == "add_conformance"): output(cmd_conformance_add(single_input("Model name?"), single_input("Metamodel name?"))) elif (cmd == "remove_conformance"): // TODO cmd = "FAIL" elif (cmd == "user_name"): // TODO cmd = "FAIL" elif (cmd == "service_poll"): // TODO cmd = "FAIL" elif (cmd == "model_types"): output(cmd_model_types(single_input("Model name?"))) else: output("Unknown command: " + cmd) // We never get here! return !