From d7ba998cd72e3c8d60b5f34a813aa462fc6b3650 Mon Sep 17 00:00:00 2001 From: Andrei Bondarenko Date: Mon, 19 Jul 2021 07:09:39 +0200 Subject: [PATCH] Simple prompt implemented --- core/context/base.py | 4 + core/context/generic.py | 14 ++- core/context/simple_class_diagrams.py | 39 +++++---- core/manager.py | 10 +++ main.py | 121 ++++++++++++++++++++++++++ 5 files changed, 168 insertions(+), 20 deletions(-) create mode 100644 main.py diff --git a/core/context/base.py b/core/context/base.py index 627dc2e..9a13cc9 100644 --- a/core/context/base.py +++ b/core/context/base.py @@ -17,6 +17,10 @@ class Context(ABC): def __exit__(self): pass + @abstractmethod + def exposed_methods(self): + pass + @abstractmethod def instantiate(self, type_name: String, instance_name: String): pass diff --git a/core/context/generic.py b/core/context/generic.py index 35d4ed9..bc97ce2 100644 --- a/core/context/generic.py +++ b/core/context/generic.py @@ -5,6 +5,7 @@ from core.context.bottom import BottomContext class GenericContext(Context): + def __init__(self, state: State, model: Element, metamodel: Element): super().__init__(state, model, metamodel) self.bottom = BottomContext(state, model) @@ -15,13 +16,24 @@ class GenericContext(Context): def __exit__(self): pass + def exposed_methods(self): + yield from [ + self.instantiate, + self.instantiate_value, + self.instantiate_link, + self.retype_element, + self.list_elements, + self.delete_element, + self.verify, + ] + def _type_exists(self, type_name: String, instantiate_link: bool) -> bool: metamodel_root = self.state.read_dict(self.metamodel.id, "Model") type_element = self.state.read_dict(metamodel_root, type_name.value) if type_element is None: return False else: - element_is_edge = self.state.read_edge(type_element) is not None + element_is_edge = self.state.read_edge(type_element) != (None, None) return element_is_edge == instantiate_link def instantiate(self, type_name: String, name: String): diff --git a/core/context/simple_class_diagrams.py b/core/context/simple_class_diagrams.py index c013862..97c826d 100644 --- a/core/context/simple_class_diagrams.py +++ b/core/context/simple_class_diagrams.py @@ -1,4 +1,4 @@ -from core.element import Element +from core.element import Element, String, Integer, Boolean from state.base import State from core.context.generic import GenericContext @@ -7,25 +7,26 @@ class SCDContext(GenericContext): def __init__(self, state: State, model: Element, metamodel: Element): super().__init__(state, model, metamodel) + def exposed_methods(self): + yield from super().exposed_methods() + yield from [ + self.create_class, + self.create_class_attribute, + self.create_association, + self.create_inheritance + ] -def main(): - from state.devstate import DevState + def create_class(self, name: String, lower_cardinality: Integer = Element(), upper_cardinality: Integer = Element()): + pass - s = DevState() - scd = SCDContext(s, Element(), Element()) - bootstrap = scd._bootstrap_scd() - model = s.read_dict(bootstrap.id, "Model") - x = [] - for e in s.read_outgoing(model): - label_node_edge, = s.read_outgoing(e) - _, label_node = s.read_edge(label_node_edge) - type_node = s.read_dict(label_node, "Type") - x.append(f"{s.read_value(label_node)} : {s.read_value(type_node)}") - for t in sorted(x): - print(t) + def create_class_attribute(self, class_name: String, name: String, optional: Boolean = Element(value=False)): + pass - # s.dump("out/scd.dot", "out/scd.png") + def create_association(self, source_class_name: String, target_class_name: String, name: String, + source_lower_cardinality: Integer = Element(), target_lower_cardinality: Integer = Element(), + source_upper_cardinality: Integer = Element(), target_upper_cardinality: Integer = Element() + ): + pass - -if __name__ == '__main__': - main() + def create_inheritance(self, parent_class_name: String, child_class_name: String): + pass diff --git a/core/manager.py b/core/manager.py index 4c82b45..2df048c 100644 --- a/core/manager.py +++ b/core/manager.py @@ -6,6 +6,16 @@ class Manager: def __init__(self, state: State): self.state = state + def exposed_methods(self): + yield from [ + self.new_model, + self.get_model, + self.rename_model, + self.retype_model, + self.delete_model, + self.list_models, + ] + def new_model(self, name: String, type_model_name: String) -> Element: root = self.state.read_root() mm_bottom = self.state.read_dict(root, type_model_name.value) diff --git a/main.py b/main.py new file mode 100644 index 0000000..918f51d --- /dev/null +++ b/main.py @@ -0,0 +1,121 @@ +from core.element import Element +from core.manager import Manager +from core.context.bottom import BottomContext +from core.context.generic import GenericContext +from core.context import custom_contexts +from state.devstate import DevState +from bootstrap.simple_class_diagrams import bootstrap_scd + +import inspect +from ast import literal_eval +import sys +import signal +signal.signal(signal.SIGINT, signal.default_int_handler) + + +def params(method): + annotations = { + "core.element.Element[str]": "String", + "core.element.Element[int]": "Integer", + "core.element.Element[float]": "Float", + "core.element.Element[bool]": "Boolean" + } + sign = inspect.signature(method) + for param in sign.parameters.values(): + param_type = annotations.get(str(param.annotation), "Element") + if param.default is param.empty: + yield param.name, param_type + else: + yield param.name, param_type, param.default + + +def input_args(method): + args = [] + for param_tuple in params(method): + if len(param_tuple) == 3: + param_name, param_type, param_default = param_tuple + arg = input(f"{param_type} {param_name} (default = {param_default.value})? ") + if arg == '': + arg = param_default.value + else: + param_name, param_type = param_tuple + while True: + arg = input(f"{param_type} {param_name}? ") + if arg == '': + print("This arguments is non-optional, please provide a value.") + else: + break + if arg is None: + arg = Element() + elif param_type in {"Boolean", "Integer", "Float"}: + arg = Element(value=literal_eval(arg)) + else: + arg = Element(value=arg) + args.append(arg) + return args + + +def model_management_loop(manager: Manager): + try: + print("\nCurrently no model is loaded. Following model management operations are available:") + for m in manager.exposed_methods(): + print(f"\t* {m.__name__}") + while True: + command = input("\nPlease enter a command: ") + try: + method = next(m for m in manager.exposed_methods() if m.__name__ == command) + user_args = input_args(method) + model = method(*user_args) + if model is not None and not model.is_none(): + metamodel = Element(id=manager.state.read_dict(model.id, "Metamodel")) + modelling_loop(manager, model, metamodel) + break + except StopIteration: + print("Invalid command, please try again.") + except KeyboardInterrupt: + print("\nBye!") + sys.exit() + + +def modelling_loop(manager: Manager, model: Element, metamodel: Element): + model_name = manager.state.read_value(model.id) + metamodel_name = manager.state.read_value(metamodel.id) + if metamodel.is_none(): + context = BottomContext(manager.state, model) + print(f"No metamodel found. Model {model_name} has been loaded in context Bottom.") + else: + context = custom_contexts.get(metamodel_name, GenericContext)(manager.state, model, metamodel) + print(type(context)) + print(f"Model {model_name} has been loaded in context {metamodel_name}.") + print(f"To return to the model management interface press CTRL + C.") + print(f"The following operations are available in this context:") + for m in context.exposed_methods(): + print(f"\t* {m.__name__}") + try: + while True: + command = input("\nPlease enter a command: ") + try: + method = next(m for m in context.exposed_methods() if m.__name__ == command) + user_args = input_args(method) + model = method(*user_args) + if model is not None and not model.is_none(): + metamodel = Element(id=manager.state.read_dict(model.id, "Metamodel")) + modelling_loop(manager, model, metamodel) + break + except StopIteration: + print("Invalid command, please try again.") + except KeyboardInterrupt: + pass + + +if __name__ == '__main__': + state = DevState() + bootstrap_scd(state) + + man = Manager(state) + print("Welcome to MV2!") + while True: + model_management_loop(man) + + +