|
|
@@ -13,12 +13,15 @@ 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
|
|
|
@@ -30,10 +33,10 @@ String function get_foldername(name : String):
|
|
|
|
|
|
// 'result' now contains a list of entries which we have to join with the seperator
|
|
|
String str
|
|
|
- str = list_pop(result, 0)
|
|
|
+ str = list_pop_final(result)
|
|
|
|
|
|
while (list_len(result) > 0):
|
|
|
- str = string_join(str + "/", list_pop(result, 0))
|
|
|
+ str = cast_string(list_pop_final(result)) + "/" + str
|
|
|
|
|
|
return str!
|
|
|
|
|
|
@@ -75,8 +78,8 @@ String function get_instanceOf_link(model_id : String, metamodel_id : String):
|
|
|
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_v2s(read_attribute(core, model_id, "name")))
|
|
|
- log("Target meta-model: " + cast_v2s(read_attribute(core, metamodel_id, "name")))
|
|
|
+ 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)
|
|
|
@@ -127,8 +130,8 @@ Element function get_full_model(model_id : String, metamodel_id : String):
|
|
|
return m!
|
|
|
else:
|
|
|
log("No type mapping could be deduced!")
|
|
|
- log("Error for " + cast_v2s(read_attribute(core, model_id, "name")))
|
|
|
- log(" and type " + cast_v2s(read_attribute(core, metamodel_id, "name")))
|
|
|
+ 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):
|
|
|
@@ -256,9 +259,9 @@ String function get_entry_id(name : String):
|
|
|
String current
|
|
|
Integer i
|
|
|
Element elems
|
|
|
- String current_part
|
|
|
String elem
|
|
|
Boolean found
|
|
|
+ String folder_name
|
|
|
|
|
|
if (name == ""):
|
|
|
return caches["root"]!
|
|
|
@@ -268,20 +271,18 @@ String function get_entry_id(name : String):
|
|
|
if (full_name(caches["models"][name]) == name):
|
|
|
return caches["models"][name]!
|
|
|
|
|
|
- current = get_entry_id(get_foldername(name))
|
|
|
+ folder_name = get_foldername(name)
|
|
|
+ current = get_entry_id(folder_name)
|
|
|
|
|
|
if (current == ""):
|
|
|
return ""!
|
|
|
|
|
|
- if (current_part != ""):
|
|
|
- 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!
|
|
|
- else:
|
|
|
- return current!
|
|
|
+ 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 ""!
|
|
|
|
|
|
@@ -384,7 +385,7 @@ String function export_typing(model : Element, name : String):
|
|
|
|
|
|
// Create type mapping model
|
|
|
String location
|
|
|
- location = "type mappings/" + cast_id2s(get_type_mapping(model))
|
|
|
+ location = "type mappings/" + cast_id(get_type_mapping(model))
|
|
|
export_node(location, get_type_mapping(model))
|
|
|
|
|
|
String instance_of
|
|
|
@@ -405,7 +406,7 @@ Void function model_create(model : Element, name : String, type_id : String, kin
|
|
|
String instance_of
|
|
|
|
|
|
// Create model itself
|
|
|
- location = "models/" + cast_id2s(model)
|
|
|
+ location = "models/" + cast_id(model)
|
|
|
export_node(location, model["model"])
|
|
|
|
|
|
model_id = instantiate_node(core, kind, "")
|
|
|
@@ -428,7 +429,7 @@ Void function model_overwrite(model : Element, model_id : String, metamodel_id :
|
|
|
String location
|
|
|
String instanceOf_link
|
|
|
|
|
|
- location = "models/" + cast_id2s(model)
|
|
|
+ location = "models/" + cast_id(model)
|
|
|
export_node(location, model["model"])
|
|
|
|
|
|
// Change location in meta-data
|
|
|
@@ -464,20 +465,6 @@ Boolean function check_conformance(model_id : String):
|
|
|
|
|
|
return True!
|
|
|
|
|
|
-Boolean function pm_finished(worklist : Element, pm : String):
|
|
|
- Element finished
|
|
|
- Integer cnt
|
|
|
- Integer i
|
|
|
- // Check if any of the "finish" elements are in the worklist
|
|
|
- // If so, we can already finish, and therefore will stop immediately
|
|
|
- finished = allInstances(pm, "Finish")
|
|
|
- worklist = set_copy(worklist)
|
|
|
- while (set_len(worklist) > 0):
|
|
|
- // Check each finished element individually
|
|
|
- if (set_in(finished, list_read(set_pop(worklist), 0))):
|
|
|
- return True!
|
|
|
- return False!
|
|
|
-
|
|
|
Element function merge_models(models_dict : Element, operation_name : String):
|
|
|
core = import_node(core_model_location)
|
|
|
// 0) Find operation signature
|
|
|
@@ -641,7 +628,7 @@ Element function execute_operation(operation_id : String, input_models : Element
|
|
|
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)
|
|
|
@@ -660,6 +647,9 @@ Element function execute_operation(operation_id : String, input_models : Element
|
|
|
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)
|
|
|
@@ -681,8 +671,8 @@ Element function execute_operation(operation_id : String, input_models : Element
|
|
|
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_v2s(set_pop(dict_keys(input_models))))
|
|
|
- output("Signature mismatch in operation for tag " + cast_v2s(set_pop(dict_keys(input_models))))
|
|
|
+ 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)):
|
|
|
@@ -710,8 +700,16 @@ Element function execute_operation(operation_id : String, input_models : Element
|
|
|
return read_root()!
|
|
|
result = transform(merged_model, operation)
|
|
|
elif (exact_type == "ManualOperation"):
|
|
|
- output("Please perform manual operation " + cast_v2s(full_name(operation_id)))
|
|
|
- modify(merged_model, True)
|
|
|
+ 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
|
|
|
@@ -763,7 +761,7 @@ Element function execute_operation(operation_id : String, input_models : Element
|
|
|
log("Negative result of execution")
|
|
|
return read_root()!
|
|
|
|
|
|
-Boolean function enact_action(pm : Element, element : String, prefix : String):
|
|
|
+Boolean function enact_action(pm : Element, element : String, mapping : Element):
|
|
|
Boolean result
|
|
|
String transformation_id
|
|
|
Element lst
|
|
|
@@ -776,17 +774,22 @@ Boolean function enact_action(pm : Element, element : String, prefix : String):
|
|
|
Element output_mms
|
|
|
Element consumes_link
|
|
|
String name
|
|
|
- String value
|
|
|
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"))
|
|
|
@@ -795,8 +798,14 @@ Boolean function enact_action(pm : Element, element : String, prefix : String):
|
|
|
lst = allOutgoingAssociationInstances(pm, element, "Consumes")
|
|
|
while (set_len(lst) > 0):
|
|
|
consume = set_pop(lst)
|
|
|
- value = read_attribute(pm, readAssociationDestination(pm, consume), "name")
|
|
|
- dict_add(inputs, read_attribute(pm, consume, "name"), prefix + value)
|
|
|
+ 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")
|
|
|
@@ -805,26 +814,36 @@ Boolean function enact_action(pm : Element, element : String, prefix : String):
|
|
|
elem = readAssociationDestination(pm, produce)
|
|
|
type_name = read_attribute(pm, elem, "type")
|
|
|
elem_name = read_attribute(pm, elem, "name")
|
|
|
- dict_add(outputs, read_attribute(pm, produce, "name"), type_name)
|
|
|
- dict_add(output_map, read_attribute(pm, produce, "name"), prefix + 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(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(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(string_join("Enacting ModelTransformation: ", read_attribute(pm, element, "name")))
|
|
|
-
|
|
|
- result = execute_operation(transformation_id, inputs, read_root())
|
|
|
+ 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:
|
|
|
- keys = dict_keys(result)
|
|
|
+ // 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]) == ""):
|
|
|
@@ -832,9 +851,35 @@ Boolean function enact_action(pm : Element, element : String, prefix : String):
|
|
|
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!
|
|
|
|
|
|
-Void function enact_PM(pm : Element, prefix : String):
|
|
|
+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
|
|
|
@@ -842,85 +887,151 @@ Void function enact_PM(pm : Element, prefix : String):
|
|
|
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_node(worklist, create_tuple(set_pop(allInstances(pm, "Start")), True))
|
|
|
-
|
|
|
- while (bool_not(pm_finished(worklist, pm))):
|
|
|
- // Pop a random element from the list and execute it
|
|
|
- tuple = set_pop(worklist)
|
|
|
- element = tuple[0]
|
|
|
- result = tuple[1]
|
|
|
-
|
|
|
- // 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)
|
|
|
-
|
|
|
- if (type == "Start"):
|
|
|
- // Initial node, just progress to the next elements
|
|
|
- // Nothing to do here though, as we have just started
|
|
|
- result = True
|
|
|
- elif (type == "Finish"):
|
|
|
- // Should be impossible, as we would have ended...
|
|
|
- result = result
|
|
|
- elif (type == "Fork"):
|
|
|
- result = result
|
|
|
- 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!
|
|
|
+ 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)
|
|
|
|
|
|
- elif (type == "Exec"):
|
|
|
- // Execute a transformation
|
|
|
- // This the difficult part!
|
|
|
+ // 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)
|
|
|
|
|
|
- result = enact_action(pm, element, prefix)
|
|
|
- output("Success")
|
|
|
+ // Some types have nothing to do, such as start and fork
|
|
|
+ // Therefore, they are not mentioned in the following conditional
|
|
|
|
|
|
- elif (type == "Decision"):
|
|
|
- // If the previous result is true, we add the normal one, otherwise the false one
|
|
|
- // in this context, that means that if it is false, we should add it manually to the list, and then continue the simulation loop
|
|
|
- if (bool_not(result)):
|
|
|
- // Apparently it is False, so map this to the "Else" branch
|
|
|
- set_add_node(worklist, create_tuple(set_pop(allAssociationDestinations(pm, element, "Else")), True))
|
|
|
+ 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:
|
|
|
- // Apparently it is True, so map this to the "Then" branch
|
|
|
- set_add_node(worklist, create_tuple(set_pop(allAssociationDestinations(pm, element, "Then")), True))
|
|
|
- continue!
|
|
|
+ // No finished activities either, so we sleep for some time
|
|
|
+ sleep(0.1)
|
|
|
|
|
|
- // 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_node(worklist, create_tuple(next, result))
|
|
|
+ // Remove all mock locations again
|
|
|
+ while (set_len(mock_locations) > 0):
|
|
|
+ model_delete(get_entry_id(set_pop(mock_locations)))
|
|
|
|
|
|
- // Reached a finish element, so stop
|
|
|
return !
|
|
|
|
|
|
String function cmd_help():
|
|
|
@@ -988,36 +1099,31 @@ String function cmd_model_add(type : String, name : String, code : String):
|
|
|
// Type exists
|
|
|
if (allow_read(current_user_id, type_id)):
|
|
|
// And is readable
|
|
|
- if (get_entry_id(get_foldername(name)) != ""):
|
|
|
- // Folder doesn't exist yet!
|
|
|
- if (allow_write(current_user_id, get_entry_id(get_foldername(name)))):
|
|
|
- // Folder is writable
|
|
|
- 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!
|
|
|
+ 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)
|
|
|
+ new_model = compile_model(code, mm)
|
|
|
|
|
|
- if (element_eq(new_model, read_root())):
|
|
|
- return "Compilation error"!
|
|
|
+ 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 folder: " + get_foldername(name)!
|
|
|
+ model_create(new_model, name, type_id, "Model")
|
|
|
+ return "Success"!
|
|
|
else:
|
|
|
- return "No such folder: " + get_foldername(name)!
|
|
|
+ return "Model exists: " + name!
|
|
|
else:
|
|
|
return "Permission denied to model: " + type!
|
|
|
else:
|
|
|
return "Model not found: " + type!
|
|
|
|
|
|
-String function cmd_process_execute(process : String, prefix : String):
|
|
|
+String function cmd_process_execute(process : String, mapping : Element):
|
|
|
// Execute a process model until it reaches termination
|
|
|
String process_id
|
|
|
|
|
|
@@ -1029,13 +1135,42 @@ String function cmd_process_execute(process : String, prefix : String):
|
|
|
if (element_eq(pm, read_root())):
|
|
|
return "Specified model cannot be interpreted as a ProcessModel: " + process!
|
|
|
|
|
|
- enact_PM(pm, prefix)
|
|
|
+ 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
|
|
|
@@ -1046,7 +1181,6 @@ String function cmd_transformation_between(source_dict : String, target_dict : S
|
|
|
String link
|
|
|
Element keys
|
|
|
|
|
|
- log("Finding transformation from " + dict_to_string(source_dict) + " to " + dict_to_string(target_dict))
|
|
|
result = allInstances(core, "Transformation")
|
|
|
|
|
|
// Iterate over all inputs
|
|
|
@@ -1099,7 +1233,6 @@ String function cmd_transformation_between(source_dict : String, target_dict : S
|
|
|
transformation = set_pop(result)
|
|
|
if (allow_read(current_user_id, transformation)):
|
|
|
r = r + string_join(full_name(transformation), "\n")
|
|
|
- log("Found: " + full_name(transformation))
|
|
|
return r!
|
|
|
|
|
|
String function cmd_model_rendered(model_name : String, mapper_name : String):
|
|
|
@@ -1228,12 +1361,89 @@ String function cmd_model_render(model_name : String, mapper_name : String, rend
|
|
|
else:
|
|
|
return "Model not found: " + 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)
|
|
|
+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
|
|
|
@@ -1251,9 +1461,6 @@ String function cmd_transformation_execute(transformation_name : String, source_
|
|
|
String target_model_name
|
|
|
String source_model_name
|
|
|
String source_model_ID
|
|
|
- Element result
|
|
|
- Element keys
|
|
|
- String key
|
|
|
String assoc_name
|
|
|
|
|
|
transformation_id = get_entry_id(transformation_name)
|
|
|
@@ -1310,49 +1517,10 @@ String function cmd_transformation_execute(transformation_name : String, source_
|
|
|
else:
|
|
|
return "Permission denied to model: " + target_model_name!
|
|
|
|
|
|
- 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"))
|
|
|
+ if (do_spawn_activity(transformation_id, tracability_name, inputs, outputs, output_map)):
|
|
|
+ return "Success"!
|
|
|
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!
|
|
|
return "Failure"!
|
|
|
- else:
|
|
|
- keys = dict_keys(result)
|
|
|
- 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]))
|
|
|
-
|
|
|
- return "Success"!
|
|
|
else:
|
|
|
return "Model is not executable: " + transformation_name!
|
|
|
else:
|
|
|
@@ -1611,13 +1779,15 @@ String function transformation_add(source_models : Element, target_models : Elem
|
|
|
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 (bool_not(bool_and(dict_len(source_models) == 0, dict_len(target_models) == 0))):
|
|
|
+ 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")
|
|
|
- modify(merged_formalism, True)
|
|
|
- model_overwrite(merged_formalism, get_entry_id("merged/" + operation_name), get_entry_id("formalisms/SimpleClassDiagrams"))
|
|
|
+ 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"))
|
|
|
@@ -1639,7 +1809,7 @@ String function transformation_add(source_models : Element, target_models : Elem
|
|
|
model_create(import_node("AL/" + operation_name), operation_name, get_entry_id("formalisms/ActionLanguage"), "ActionLanguage")
|
|
|
model_id = get_entry_id(operation_name)
|
|
|
|
|
|
- if (bool_not(bool_and(dict_len(source_models) == 0, dict_len(target_models) == 0))):
|
|
|
+ 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
|
|
|
@@ -1658,7 +1828,6 @@ String function transformation_add(source_models : Element, target_models : Elem
|
|
|
keys = dict_keys(source)
|
|
|
while (set_len(keys) > 0):
|
|
|
key = set_pop(keys)
|
|
|
- log("Add transformInput link for " + model_id + " to " + cast_v2s(source[key]) + " while adding operation " + operation_name)
|
|
|
link = instantiate_link(core, "transformInput", "", model_id, source[key])
|
|
|
instantiate_attribute(core, link, "name", key)
|
|
|
|
|
|
@@ -1701,6 +1870,9 @@ String function cmd_transformation_add_MT(source_models : Element, target_models
|
|
|
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)
|
|
|
@@ -1756,7 +1928,10 @@ String function cmd_transformation_add_MT(source_models : Element, target_models
|
|
|
return "Model not found: " + name!
|
|
|
|
|
|
merged_formalism = model_fuse(to_ramify)
|
|
|
- modify(merged_formalism, True)
|
|
|
+ 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")
|
|
|
@@ -1794,7 +1969,6 @@ String function cmd_transformation_add_MT(source_models : Element, target_models
|
|
|
while (set_len(keys) > 0):
|
|
|
key = set_pop(keys)
|
|
|
dst = source[key]
|
|
|
- log("Add transformInput link for " + model_id + " to " + dst + " while adding operation " + operation_name)
|
|
|
link = instantiate_link(core, "transformInput", "", model_id, dst)
|
|
|
instantiate_attribute(core, link, "name", key)
|
|
|
|
|
|
@@ -1823,7 +1997,7 @@ String function cmd_permission_modify(model_name : String, permissions : String)
|
|
|
fail = True
|
|
|
|
|
|
while (i < 3):
|
|
|
- permission = cast_s2i(string_get(permissions, i))
|
|
|
+ permission = cast_integer(string_get(permissions, i))
|
|
|
if (bool_or(permission < 0, permission > 2)):
|
|
|
fail = True
|
|
|
break!
|
|
|
@@ -2072,7 +2246,7 @@ String function cmd_service_register(service_name : String):
|
|
|
output("Success: " + get_taskname())
|
|
|
|
|
|
// Wait until we can stop the service
|
|
|
- while (cast_v2s(input()) != "\"service_stop\""):
|
|
|
+ while (cast_value(input()) != "\"service_stop\""):
|
|
|
output("Service is running on this task: stop it by sending 'service_stop'")
|
|
|
|
|
|
model_delete_element(core, service)
|
|
|
@@ -2189,7 +2363,9 @@ Void function user_function_skip_init(user_id : String):
|
|
|
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?"), single_input("Model prefix to use?")))
|
|
|
+ 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"):
|
|
|
@@ -2213,11 +2389,11 @@ Void function user_function_skip_init(user_id : String):
|
|
|
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 model names?"), dict_input("Target model names?"), single_input("Operation name?")))
|
|
|
+ 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 model names?"), dict_input("Target model names?"), single_input("Operation name?")))
|
|
|
+ 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 model names?"), dict_input("Target models?"), single_input("Operation name?")))
|
|
|
+ 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"):
|
|
|
@@ -2267,7 +2443,6 @@ Void function user_function_skip_init(user_id : String):
|
|
|
elif (cmd == "folder_create"):
|
|
|
output(cmd_folder_create(single_input("Folder name?")))
|
|
|
elif (cmd == "add_conformance"):
|
|
|
- // TODO
|
|
|
output(cmd_conformance_add(single_input("Model name?"), single_input("Metamodel name?")))
|
|
|
elif (cmd == "remove_conformance"):
|
|
|
// TODO
|