import urllib import urllib2 import json import random from urllib2 import URLError import sys # Bind to the compiler (might have to update path manually!) sys.path.append("interface/HUTN") from hutn_compiler.compiler import main as do_compile # Helper functions and configuration: do not use yourself! taskname = random.random() address = None last_output = None mode = 0 def _input(value): # Ugly json encoding of primitives if isinstance(value, type([])): value = json.dumps(value) urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "data": value, "taskname": taskname}))).read() else: value = json.dumps(value) urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "value": value, "taskname": taskname}))).read() #print("Set input: " + str(value)) def _input_raw(value, taskname): # Ugly json encoding of primitives urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "value": value, "taskname": taskname}))).read() def _compile_AL(code): # Compile an action language file and send the compiled code code_fragments = code.split("\n") code_fragments = [i for i in code_fragments if i.strip() != ""] code_fragments = [i.replace(" ", "\t") for i in code_fragments] initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments]) code_fragments = [i[initial_tabs:] for i in code_fragments] code_fragments.append("") code = "\n".join(code_fragments) with open("__constraint.alc", "w") as f: f.write(code) f.flush() return do_compile("__constraint.alc", "interface/HUTN/grammars/actionlanguage.g", "CS") def _compile_model(code): # Compile a model and send the compiled graph # First change multiple spaces to a tab code_fragments = code.split("\n") code_fragments = [i for i in code_fragments if i.strip() != ""] code_fragments = [i.replace(" ", "\t") for i in code_fragments] initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments]) code_fragments = [i[initial_tabs:] for i in code_fragments] code_fragments.append("") code = "\n".join(code_fragments) with open("__model.mvc", "w") as f: f.write(code) f.flush() return do_compile("__model.mvc", "interface/HUTN/grammars/modelling.g", "M") + ["exit"] def _output(expected=None): try: global last_output last_output = json.loads(urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "taskname": taskname}))).read()) #print("Got output: " + str(last_output)) except: raise UnknownError() if expected is not None and last_output != expected: raise InterfaceMismatch(_last_output(), expected) return last_output def _last_output(): return last_output # Exceptions class ModelverseException(Exception): pass class UnknownException(ModelverseException): pass class UnknownIdentifier(ModelverseException): pass class UnknownType(ModelverseException): pass class NotAnAssociation(ModelverseException): pass class UnsupportedValue(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 # Main MvC operations def init(address_param="http://localhost:8001"): """Starts up the connection to the Modelverse.""" # return None # raises ConnectionError # raises UnknownError # raises InvalidMode global mode if mode != 0: raise InvalidMode() global address address = address_param try: _input_raw('"%s"' % taskname, "task_manager") mode = 1 except URLError as e: raise ConnectionError(e.reason) def login(username, password): """Log in a user, if user doesn't exist, it is created.""" # return None # raises UnknownError # raises PermissionDenied # raises InterfaceMismatch global mode if mode != 1: raise InvalidMode() _output("Log on as which user?") _input(username) if _output() == "Password for existing user?": _input(password) if _output() == "Welcome to the Model Management Interface v2.0!": _output("Use the 'help' command for a list of possible commands") _output("Ready for command...") mode = 2 elif _last_output() == "Wrong password!": raise PermissionDenied() else: raise InterfaceMismatch(_last_output()) elif _last_output() == "This is a new user: please give password!": _input(password) _output("Please repeat the password") _input(password) if _output() == "Passwords match!": _output("Welcome to the Model Management Interface v2.0!") _output("Use the 'help' command for a list of possible commands") _output("Ready for command...") mode = 2 elif _last_output() == "Not the same password!": # We just sent the same password, so it should be identical, unless the interface changed raise InterfaceMismatch(_last_output()) else: raise InterfaceMismatch(_last_output()) else: raise InterfaceMismatch(_last_output()) def model_add(model_name, metamodel_name, model_code=None): """Instantiate a new model.""" # return None # raises UnknownModel # raises ModelExists # raises UnknownError # raises PermissionDenied # raises CompilationError if mode != 2: raise InvalidMode() # Do this before creating the model, as otherwise compilation errors would make us inconsistent if model_code is not None: try: compiled = _compile_model(model_code) except: raise CompilationError() else: compiled = ["exit"] _input("model_add") _output("Creating new model!") _output("Model type?") _input(metamodel_name) if _output() == "Model name?": _input(model_name) if _output() == "Waiting for model constructors...": _input(compiled) _output("Model upload success!") _output("Ready for command...") elif _last_output() == "Model with that name already exists!": _output("Ready for command...") raise ModelExists() else: raise InterfaceMismatch(_last_output()) elif _last_output().startswith("Could not find type model"): _output("Ready for command...") raise UnknownModel() elif _last_output() == "Permission denied": _output("Ready for command...") raise PermissionDenied() def model_modify(model_name): """Modify an existing model.""" # return is_write # raises UnknownModel # raises PermissionDenied # raises UnknownError global mode if mode != 2: raise InvalidMode() _input("model_modify") _output("Which model do you want to modify?") _input(model_name) if _output() == "Permission denied": _output("Ready for command...") raise PermissionDenied() elif _last_output() == "Could not find model!": _output("Ready for command...") raise UnknownModel() elif _last_output() == "Model loaded, ready for commands!": mode = 3 if ("r/w" in _output()): write = True else: write = False _output("Use 'help' command for a list of possible commands") _output("Please give your command.") return write else: raise InterfaceMismatch() def model_list(): """List all models.""" # return [(model1, metamodel1), (model2, metamodel2), ...] # raises UnknownError if mode != 2: raise InvalidMode() _input("model_list") lst = [] while (_output() != "Ready for command..."): v = _last_output() m, mm = v.split(":") m = m.strip() mm = mm.strip() lst.append((m, mm)) return lst def model_list_full(): """List full information on all models.""" # return [(model1, metamodel1, owner1, group1, permissions1), (model2, metamodel2, owner2, group2, permissions2), ...] # raises UnknownError if mode != 2: raise InvalidMode() _input("model_list_full") lst = [] while (_output() != "Ready for command..."): v = _last_output() m, mm = v.split(":") m = m.strip() mm = mm.strip() perm, own, grp, m = m.split(" ") lst.append((m, mm, own, grp, perm)) return lst def verify(model): """Verify if a model conforms to its metamodel.""" # return "verification_result" # raises UnknownError # raises UnknownModel if mode != 2: raise InvalidMode() _input("verify") _output("Which model to verify?") _input(model) if _output() == "Verifying model...": result = _output() _output("Ready for command...") return result elif _last_output() == "Permission denied": _output("Ready for command...") raise PermissionDenied() elif _last_output() == "No such model": _output("Ready for command...") raise UnknownModel() else: raise InterfaceMismatch(_last_output()) def model_overwrite(model_name, new_model=None): """Upload a new model and overwrite an existing model.""" # return None # raises UnknownModel # raises PermissionDenied # raises CompilationError # raises UnknownError if mode != 2: raise InvalidMode() if new_model is not None: try: compiled = _compile_model(new_model) except Exception as e: raise CompilationError(e) else: compiled = ["exit"] _input("model_overwrite") _output("Which model to overwrite?") _input(model_name) if _output() == "Permission denied": _output("Ready for command...") raise PermissionDenied() elif _last_output() == "No such model": _output("Ready for command...") raise UnknownModel() elif _last_output() == "Waiting for model constructors...": _input(compiled) _output("Model overwrite success") _output("Ready for command...") def user_logout(): """Log out the current user and break the connection.""" # return None # raises UnknownException global mode if mode != 2: raise InvalidMode() _input("exit") mode = 0 def user_delete(): """Removes the current user and break the connection.""" # return None # raises UnknownException global mode if mode != 2: raise InvalidMode() _input("self-destruct") mode = 0 def model_render(model, mapper): """Fetch a rendered verion of a model.""" # return JSON_representation # raises UnknownException # raises UnknownIdentifier # raises InterfaceMismatch global mode if mode != 2: raise InvalidMode() _input("model_render") _output() _input(model) _output() _input(mapper) rendered = _output() _output("Ready for command...") return rendered def transformation_add_MT_language(): """Create a new Model Transformation language out of a set of metamodels.""" raise NotImplementedError() def transformation_add_MT(): """Create a new model transformation.""" raise NotImplementedError() def transformation_add_AL(): """Create a new action language fragment.""" raise NotImplementedError() def transformation_add_MANUAL(): """Create a new manual model operation.""" raise NotImplementedError() def transformation_execute(): """Execute an existing model operation.""" raise NotImplementedError() def transformation_list(): """List existing model operations.""" raise NotImplementedError() def transformation_list_full(): """List detailed information on model operations.""" raise NotImplementedError() def transformation_detail(): """List full details of a a model operation.""" raise NotImplementedError() def transformation_RAMify(): """Ramify an existing metamodel.""" raise NotImplementedError() def process_execute(): """Execute a process model.""" raise NotImplementedError() def permission_modify(): """Modify permissions of a model.""" raise NotImplementedError() def permission_owner(): """Modify the owning user of a model.""" raise NotImplementedError() def permission_group(): """Modify the owning group of a model.""" raise NotImplementedError() def group_create(): """Create a new group.""" raise NotImplementedError() def group_delete(): """Delete a group of which you are an owner.""" raise NotImplementedError() def group_owner_add(): """Add a new owning user to a group you own.""" raise NotImplementedError() def group_owner_delete(): """Delete an owning user to a group you own.""" raise NotImplementedError() def group_join(): """Add a new user to a group you own.""" raise NotImplementedError() def group_kick(): """Delete a user from a group you own.""" raise NotImplementedError() def group_list(): """List existing groups.""" raise NotImplementedError() def admin_promote(): """Promote a user to admin status.""" raise NotImplementedError() def admin_demote(): """Demote a user from admin status.""" raise NotImplementedError() # Actual operations on the model def element_list(): """Return a list of all IDs and the type of the element""" # return [(name1, type1), (name2, type2), ...] # raises UnknownError if mode != 3: raise InvalidMode() _input("list") lst = [] _output("List of all elements:") while (_output() != "Please give your command."): v = _last_output() m, mm = v.split(":") m = m.strip() mm = mm.strip() lst.append((m, mm)) return lst def types(): """Return a list of all types usable in the model""" # return [type1, type2, ...] # raises UnknownError if mode != 3: raise InvalidMode() _input("types") _output("List of types:") lst = [] while (_output() != "Please give your command."): v = _last_output() m, mm = v.split(":") m = m.strip() lst.append(m) return lst def read(ID): """Return a tuple of information on the element: its type and source/target (None if not an edge)""" # return (type, (source, target)) # raises UnknownError # raises UnknownIdentifier if mode != 3: raise InvalidMode() _input("read") _output("Element to read?") _input(ID) if _output() == "Unknown element; aborting": _output("Please give your command.") raise UnknownIdentifier() elif _last_output() == "ID: " + str(ID): t = _output().split(":")[1].strip() if (not _output().startswith("Source:")): rval = (t, None) else: src = _last_output().split(":")[1].strip() trg = _output().split(":")[1].strip() rval = (t, (src, trg)) while (_output() != "Please give your command."): pass return rval def read_attrs(ID): """Return a dictionary of attribute value pairs""" # return {attr1: value1, attr2: value2, ...} # raises UnknownError # raises UnknownIdentifier if mode != 3: raise InvalidMode() _input("read") _output("Element to read?") _input(ID) if _output() == "Unknown element; aborting": _output("Please give your command.") raise UnknownIdentifier() elif _last_output() == "ID: " + str(ID): rval = {} # Skip until attributes while (_output() != "Attributes:"): pass while (_output() != "Please give your command."): r = _last_output() key, value = r.split(":") _, value = value.split("=") key = json.loads(key.strip()) value = value.strip() value = None if value == "None" else json.loads(value) rval[key] = value return rval def instantiate(typename, edge=None, ID=""): """Create a new instance of the specified typename, between the selected elements (if not None), and with the provided ID (if any)""" # return instantiated_ID # raises UnknownError # raises UnknownType # raises UnknownIdentifier # raises NotAnEdge if mode != 3: raise InvalidMode() _input("instantiate") if (_output() == "Permission denied"): _output("Please give your command.") raise PermissionDenied() else: _input(typename) if (_output() == "Name of new element?"): _input(ID) if (_output() == "Element already exists; aborting"): _output("Please give your command.") raise ElementExists() if (edge is not None) and (_last_output() == "Source name?"): # Is an edge and we have data _input(edge[0]) if _output() == "Destination name?": _input(edge[1]) if _output() == "Instantiation successful!": ID = _output() _output("Please give your command.") return ID elif _last_output() == "Unknown destination; aborting": _output("Please give your command.") raise UnknownIdentifier() else: raise InterfaceMismatch(_last_output()) elif _last_output() == "Unknown source; aborting": _output("Please give your command.") raise UnknownIdentifier() else: raise InterfaceMismatch(_last_output()) elif (edge is None) and (_last_output() != "Source name?"): # Is no edge and we don't have data if _last_output() == "Instantiation successful!": ID = _output() _output("Please give your command.") return ID else: raise InterfaceMismatch(_last_output()) elif (edge is not None) and (_last_output() != "Source name?"): # Is no edge, but we have edge data to input: ERROR # Delete the element again ID = _last_output() _output("Please give your command.") delete_element(ID) raise NotAnEdge() elif (edge is None) and (_last_output() == "Source name?"): # Is an edge, but we have no edge data to input: ERROR # Add an empty source, which is guaranteed not to be there _input("") _output("Unknown source; aborting") _output("Please give your command.") raise NotAnEdge() elif (_last_output() == "Permission denied"): _output("Please give your command.") raise PermissionDenied() elif (_last_output() == "Unknown type specified; aborting"): _output("Please give your command.") raise UnknownType() else: raise InterfaceMismatch(_last_output()) def delete_element(ID): """Delete the element with the given ID""" # return None # raises UnknownError # raises UnknownIdentifier if mode != 3: raise InvalidMode() _input("delete") if _output() == "What is the name of the element you want to delete?": _input(ID) if _output() == "Deleted!": _output("Please give your command.") elif _last_output() == "No such element; aborting": _output("Please give your command.") raise UnknownIdentifier() else: raise InterfaceMismatch(_last_output()) elif _last_output() == "Permission denied": _output("Please give your command.") raise PermissionDenied() else: raise InterfaceMismatch(_last_output()) def attr_assign(ID, attr, value): """Assign a value to an attribute""" # return None # raises UnknownError # raises UnknownIdentifier # raises NoSuchAttribute # raises UnsupportedValue if mode != 3: raise InvalidMode() _input("attr_add") if _output() == "Which element do you want to assign an attribute to?": _input(ID) if _output() == "Which attribute do you wish to assign?": _input(attr) if _output() == "Value of attribute?": _input(value) _output("Added attribute!") _output("Please give your command.") elif _last_output() == "No such attribute!": _output("Please give your command.") raise NoSuchAttribute() else: raise InterfaceMismatch(_last_output()) elif _last_output() == "No such element!": _output("Please give your command.") raise UnknownIdentifier() else: raise InterfaceMismatch(_last_output()) elif _last_output() == "Permission denied": _output("Please give your command.") raise PermissionDenied() else: raise InterfaceMismatch(_last_output()) def attr_assign_code(ID, attr, code): """Assign a piece of Action Language code to the attribute""" # return None # raises UnknownError # raises UnknownIdentifier # raises NoSuchAttribute # raises UnsupportedValue if mode != 3: raise InvalidMode() try: compiled = _compile_AL(code) except Exception as e: raise CompilationError(e) _input("attr_add") if _output() == "Which element do you want to assign an attribute to?": _input(ID) if _output() == "Which attribute do you want to assign?": _input(attr) if _output() == "Waiting for code constructors...": _input(compiled) _output("Added attribute!") _output("Please give your command.") elif _last_output() == "No such attribute!": _output("Please give your command.") raise NoSuchAttribute() else: raise InterfaceMismatch(_last_output()) elif _last_output() == "No such element!": _output("Please give your command.") raise UnknownIdentifier() else: raise InterfaceMismatch(_last_output()) elif _last_output() == "Permission denied": _output("Please give your command.") raise PermissionDenied() else: raise InterfaceMismatch(_last_output()) def attr_delete(ID, attr): """Remove an attribute.""" if mode != 3: raise InvalidMode() _input("attr_del") if _output() == "Which element do you want to remove an attribute of?": _input(ID) if _output() == "Which attribute do you want to delete?": _input(attr) if _output() == "Attribute deleted!": _output("Please give your command.") elif _last_output() == "No such attribute!": _output("Please give your command.") raise NoSuchAttribute() else: raise InterfaceMismatch(_last_output()) elif _last_output() == "No such element!": _output("Please give your command.") raise UnknownIdentifier() else: raise InterfaceMismatch(_last_output()) elif _last_output() == "Permission denied": _output("Please give your command.") raise PermissionDenied() else: raise InterfaceMismatch(_last_output()) def read_outgoing(ID, typename): """Returns a list of all outgoing associations of a specific type ("" = all)""" # return [name1, name2, ...] # raises UnknownError # raises UnknownIdentifier if mode != 3: raise InvalidMode() _input("read_outgoing") _output("Element to read from?") _input(ID) if _output() == "Type of outgoing edge (empty for all)?": _input(typename) lst = [] while (_output() != "Please give your command."): lst.append(_last_output()) return lst elif _last_output() == "Unknown element; aborting": _output("Please give your command.") raise UnknownIdentifier() else: raise InterfaceMismatch() def read_incoming(ID, typename): """Returns a list of all incoming associations of a specific type ("" = all)""" # return [name1, name2, ...] # raises UnknownError # raises UnknownIdentifier # raises UnknownType if mode != 3: raise InvalidMode() _input("read_incoming") _output("Element to read from?") _input(ID) if _output() == "Type of incoming edge (empty for all)?": _input(typename) lst = [] while (_output() != "Please give your command."): lst.append(_last_output()) return lst elif _last_output() == "Unknown element; aborting": _output("Please give your command.") raise UnknownIdentifier() else: raise InterfaceMismatch() def read_association_source(ID): """Returns the source of an association.""" # returns name # raises UnknownError # raises UnknownIdentifier # raises NotAnAssociation _input("read_association_source") _output("Association to read source of?") _input(ID) if _output() == "Read source:": result = _output() _output("Please give your command.") return result elif _last_output() == "Unknown element; aborting": _output("Please give your command.") raise UnknownIdentifier() elif _last_output() == "Not an association; aborting": _output("Please give your command.") raise NotAnEdge() else: raise InterfaceMismatch(_last_output()) def read_association_destination(ID): """Returns the destination of an association.""" # returns name # raises UnknownError # raises UnknownIdentifier # raises NotAnAssociation _input("read_association_destination") _output("Association to read destination of?") _input(ID) if _output() == "Read destination:": result = _output() _output("Please give your command.") return result elif _last_output() == "Unknown element; aborting": _output("Please give your command.") raise UnknownIdentifier() elif _last_output() == "Not an association; aborting": _output("Please give your command.") raise NotAnEdge() else: raise InterfaceMismatch(_last_output()) def model_exit(): """Leave model modify mode.""" # return None # raises UnknownError global mode if mode != 3: raise InvalidMode() _input("exit") _output("Ready for command...") mode = 2