from sccd.runtime.statecharts_core import Event import sccd.runtime.socket2event as socket2event import modelverse_SCCD import time import threading # Exceptions class ModelverseException(Exception): pass class UnknownError(ModelverseException): pass class UnknownIdentifier(ModelverseException): pass class CompilationError(ModelverseException): pass class NoSuchAttribute(ModelverseException): pass class UnknownModel(ModelverseException): pass class ConnectionError(ModelverseException): pass class ModelExists(ModelverseException): pass class PermissionDenied(ModelverseException): pass class InvalidMode(ModelverseException): pass class InterfaceMismatch(ModelverseException): pass class UnknownMetamodellingHierarchy(ModelverseException): pass def run_controller(): try: controller.start() finally: controller.stop() def _next_ID(): global ID ID += 1 return ID def INPUT(action, context, parameters): controller.addInput(Event("action", "action_in", [action, _next_ID(), context, parameters])) def OUTPUT(): while 1: response = responses.fetch(-1) if response.name == "result": return response.parameters[1] elif response.name == "exception": if response.parameters[1] == "UnknownIdentifier": raise UnknownIdentifier() elif response.parameters[1] == "UnknownMetamodellingHierarchy": raise UnknownMetamodellingHierarchy() else: print("Unknown error: " + str(response.parameters)) raise UnknownError() def init(address_param="127.0.0.1:8001", timeout=20.0): global controller global ID global responses controller = modelverse_SCCD.Controller() socket2event.boot_translation_service(controller) ID = 0 thrd = threading.Thread(target=run_controller) thrd.daemon = True thrd.start() responses = controller.addOutputListener("action_out") controller.addOutputListener("ready").fetch(-1) INPUT("init", None, [address_param, timeout]) controller.address = address_param return OUTPUT() def login(username, password): INPUT("login", None, [username, password]) return OUTPUT() def model_list(location): INPUT("model_list", None, [location]) return OUTPUT() def model_add(model_name, metamodel_name, model_code=""): INPUT("model_add", None, [model_name, metamodel_name, model_code]) return OUTPUT() def model_delete(model_name): INPUT("model_delete", None, [model_name]) return OUTPUT() def model_list_full(location): INPUT("model_list_full", None, [location]) return OUTPUT() def verify(model_name, metamodel_name): INPUT("verify", None, [model_name, metamodel_name]) return OUTPUT() def model_overwrite(model_name, new_model, context=None): INPUT("model_overwrite", context, [model_name, new_model]) return OUTPUT() def disconnect(): INPUT("disconnect", None, []) return OUTPUT() def user_logout(): INPUT("user_logout", None, []) return OUTPUT() def user_delete(): INPUT("user_delete", None, []) return OUTPUT() def model_render(model_name, mapper_name, rendered_name): INPUT("model_render", None, [model_name, mapper_name, rendered_name]) return OUTPUT() def transformation_between(sources, targets): INPUT("transformation_between", None, [source, target]) return OUTPUT() def transformation_add_MT(source_metamodels, target_metamodels, operation_name, code, callback=None): INPUT("transformation_add_MT", None, [source_metamodels, target_metamodels, operation_name, code]) context = OUTPUT() if callback is not None: callback(context) INPUT("exit", context, []) return OUTPUT() def transformation_add_AL(source_metamodels, target_metamodels, operation_name, code, callback=None): INPUT("transformation_add_AL", None, [source_metamodels, target_metamodels, operation_name, code]) context = OUTPUT() if context is None: # In case the source and target metamodels are empty, the context will be None, indicating that we are finished already (no callbacks allowed) return if callback is not None: callback(context) INPUT("exit", context, []) return OUTPUT() def transformation_add_MANUAL(source_metamodels, target_metamodels, operation_name, callback=None): INPUT("transformation_add_MANUAL", None, [source_metamodels, target_metamodels, operation_name]) context = OUTPUT() if callback is not None: callback(context) INPUT("exit", context, []) return OUTPUT() def transformation_execute_MT(operation_name, input_models_dict, output_models_dict, statechart=None, tracability_model="", fetch_output=True): if statechart is not None: port_sc = statechart[0].addOutputListener(statechart[2]) INPUT("transformation_execute_MT", None, [operation_name, input_models_dict, output_models_dict, tracability_model, fetch_output]) context = OUTPUT() if statechart is not None: while 1: empty = True # Fetch output from the MV response = responses.fetch(0) if response is not None: if response.name == "data_output": # Got output of MV, so forward to SCCD statechart[0].addInput(Event("input", statechart[1], response.parameters)) elif response.name == "result": # Finished execution, so continue and return result statechart[0].addInput(Event("terminate", statechart[1], [])) return response.parameters[1] empty = False # Fetch output from the SC response = port_sc.fetch(0) if response is not None: if response.name == "output": controller.addInput(Event("data_input", "action_in", [response.parameters, context])) empty = False if empty: time.sleep(0.01) else: return OUTPUT() def transformation_execute_AL(operation_name, input_models_dict, output_models_dict, statechart=None, tracability_model="", fetch_output=True): if statechart is not None: port_sc = statechart[0].addOutputListener(statechart[2]) INPUT("transformation_execute_AL", None, [operation_name, input_models_dict, output_models_dict, tracability_model, fetch_output]) context = OUTPUT() if statechart is not None: while 1: empty = True # Fetch output from the MV response = responses.fetch(0) if response is not None: if response.name == "data_output": # Got output of MV, so forward to SCCD statechart[0].addInput(Event("input", statechart[1], response.parameters)) elif response.name == "result": # Finished execution, so continue and return result statechart[0].addInput(Event("terminate", statechart[1], [])) return response.parameters[1] empty = False # Fetch output from the SC response = port_sc.fetch(0) if response is not None: if response.name == "output": controller.addInput(Event("data_input", "action_in", [response.parameters, context])) empty = False if empty: time.sleep(0.01) else: return OUTPUT() def transformation_execute_MANUAL(operation_name, input_models_dict, output_models_dict, callback=None, tracability_model=""): INPUT("transformation_execute_MANUAL", None, [operation_name, input_models_dict, output_models_dict, tracability_model]) context = OUTPUT() if callback is not None: callback(context) INPUT("exit", context, []) return OUTPUT() def transformation_signature(operation_name): INPUT("transformation_signature", None, [operation_name]) return OUTPUT() def process_signature(process_name): INPUT("process_signature", None, [operation_name]) return OUTPUT() def permission_modify(model_name, permissions): INPUT("permission_modify", None, [model_name, permissions]) return OUTPUT() def permission_owner(model_name, permission): INPUT("permission_owner", None, [model_name, permission]) return OUTPUT() def permission_group(model_name, group): INPUT("permission_group", None, [model_name, group]) return OUTPUT() def group_create(group_name): INPUT("group_create", None, [group_name]) return OUTPUT() def group_delete(group_name): INPUT("group_delete", None, [group_name]) return OUTPUT() def group_owner_add(group_name, user_name): INPUT("group_owner_add", None, [group_name, user_name]) return OUTPUT() def group_owner_delete(group_name, user_name): INPUT("group_owner_delete", None, [group_name, user_name]) return OUTPUT() def group_join(group_name, user_name): INPUT("group_join", None, [group_name, user_name]) return OUTPUT() def group_kick(group_name, user_name): INPUT("group_kick", None, [group_name, user_name]) return OUTPUT() def group_list(): INPUT("group_list", None, []) return OUTPUT() def admin_promote(user_name): INPUT("admin_promote", None, [user_name]) return OUTPUT() def admin_demote(user_name): INPUT("admin_demote", None, [user_name]) return OUTPUT() def conformance_delete(model_name, metamodel_name): INPUT("conformance_delete", None, [model_name, metamodel_name]) return OUTPUT() def conformance_add(model_name, metamodel_name): INPUT("conformance_add", None, [model_name, metamodel_name]) return OUTPUT() def folder_create(folder_name): INPUT("folder_create", None, [folder_name]) return OUTPUT() def model_types(model_name): INPUT("model_types", None, [model_name]) return OUTPUT() def alter_context(model_name, metamodel_name): INPUT("alter_context", None, [model_name, metamodel_name]) return OUTPUT() def element_list(model_name, context=None): INPUT("element_list", context, [model_name]) return OUTPUT() def element_list_nice(model_name, context=None): INPUT("element_list_nice", context, [model_name]) return OUTPUT() def types(model_name, context=None): INPUT("types", context, [model_name]) return OUTPUT() def types_full(model_name, context=None): INPUT("types_full", context, [model_name]) return OUTPUT() def read_info(model_name, ID, context=None): INPUT("read_info", context, [model_name, ID]) return OUTPUT() def read_attrs(model_name, ID, context=None): INPUT("read_attrs", context, [model_name, ID]) return OUTPUT() def instantiate(model_name, typename, edge=None, ID="", context=None): INPUT("instantiate", context, [model_name, typename, edge, ID]) return OUTPUT() def delete_element(model_name, ID, context=None): INPUT("delete_element", context, [model_name, ID]) return OUTPUT() def attr_assign(model_name, ID, attr, value, context=None): INPUT("attr_assign", context, [model_name, ID, attr, value]) return OUTPUT() def attr_assign_code(model_name, ID, attr, code, context=None): INPUT("attr_assign_code", context, [model_name, ID, attr, code]) return OUTPUT() def attr_delete(model_name, ID, attr, context=None): INPUT("attr_delete", context, [model_name, ID, attr]) return OUTPUT() def read_outgoing(model_name, ID, typename, context=None): INPUT("read_outgoing", context, [model_name, ID, typename]) return OUTPUT() def read_incoming(model_name, ID, typename, context=None): INPUT("read_incoming", context, [model_name, ID, typename]) return OUTPUT() def read_association_source(model_name, ID, context=None): INPUT("read_association_source", context, [model_name, ID]) return OUTPUT() def read_association_destination(model_name, ID, context=None): INPUT("read_association_destination", context, [model_name, ID]) return OUTPUT() def connections_between(model_name, source, target, context=None): INPUT("connections_between", context, [model_name, source, target]) return OUTPUT() def define_attribute(model_name, node, attr_name, attr_type, context=None): INPUT("define_attribute", context, [model_name, node, attr_name, attr_type]) return OUTPUT() def all_instances(model_name, type_name, context=None): INPUT("all_instances", context, [model_name, type_name]) return OUTPUT() def process_execute(process_name, prefix, callbacks=None): # for all callbacks to SCs, start up the output port already sc_ports = {} for k, v in callbacks.items(): if isinstance(v, (tuple, list)): # Is a statechart, so register already sc_ports[k] = v[0].addOutputListener(v[2]) INPUT("process_execute", None, [process_name, prefix]) operation = OUTPUT() while 1: if isinstance(operation, (list, tuple)): t, name, context = operation if t == "OP": if name in callbacks: callbacks[name](context) INPUT("exit", context, []) operation = OUTPUT() elif t == "SC": if name in callbacks: statechart = callbacks[name] else: statechart = None while 1: empty = True # Fetch output from the MV response = responses.fetch(0) if response is not None: if response.name == "data_output": # Got output of MV, so forward to SCCD if statechart: statechart[0].addInput(Event("input", statechart[1], response.parameters)) elif response.name == "result": # Finished execution, so continue and return result if statechart: statechart[0].addInput(Event("terminate", statechart[1], [])) # Break from the most inner loop operation = response.parameters[1] break empty = False # Fetch output from the SC if statechart: response = sc_ports[name].fetch(0) if response is not None: if response.name == "output": controller.addInput(Event("data_input", "action_in", [response.parameters, context])) empty = False if empty: time.sleep(0.01) else: if operation == "Finished": # Finished execution of the process, so exit return None def get_taskname(): """Fetch the taskname of the current connection.""" return controller.taskname """ Some hardcoded functions... Way easier to express them with code than with statecharts!""" import json import urllib import urllib2 def service_register(name, function): """Register a function as a service with a specific name.""" INPUT("service_register", None, [name, function]) port = OUTPUT() return port def service_stop(): """Stop the currently executing process.""" INPUT("service_stop", None, []) return OUTPUT() def service_get(port): """Get the values on the specified port.""" val = json.loads(urllib2.urlopen(urllib2.Request("http://%s" % controller.address, urllib.urlencode({"op": "get_output", "taskname": port}))).read()) return val def service_set(port, value): """Set a value on a specified port.""" if isinstance(value, type([])): value = json.dumps(value) urllib2.urlopen(urllib2.Request("http://%s" % controller.address, urllib.urlencode({"op": "set_input", "data": value, "taskname": port}))).read() else: value = json.dumps(value) urllib2.urlopen(urllib2.Request("http://%s" % controller.address, urllib.urlencode({"op": "set_input", "value": value, "taskname": port}))).read() def service_poll(port): """Checks whether or not the Modelverse side has any input ready to be processed.""" raise NotImplementedError()