Clean slate
This commit is contained in:
parent
2e3576a1a8
commit
c64e348bf2
12 changed files with 0 additions and 860 deletions
|
|
@ -1,218 +0,0 @@
|
|||
from core.element import Element
|
||||
from state.base import State, STRING, INTEGER, BOOLEAN, TYPE
|
||||
from core.context.generic import GenericContext
|
||||
|
||||
|
||||
def bootstrap_scd(state: State) -> Element:
|
||||
ctx = GenericContext(state, Element(), Element())
|
||||
|
||||
scd = state.create_nodevalue("SimpleClassDiagrams")
|
||||
state.create_dict(state.read_root(), "SimpleClassDiagrams", scd)
|
||||
state.create_dict(scd, "Model", state.create_node())
|
||||
state.create_dict(scd, "Metamodel", scd)
|
||||
ctx.__init__(state, Element(id=scd), Element(id=scd))
|
||||
|
||||
# Classes --> elements that will be typed by Class
|
||||
ctx.bottom.add_node(Element(value="Element"))
|
||||
ctx.bottom.add_node(Element(value="Class"))
|
||||
ctx.bottom.add_value(Element(value="Attribute"), Element(value=TYPE))
|
||||
|
||||
# Associations --> elements that will be typed by Association
|
||||
ctx.bottom.add_edge(Element(value="Association"), Element(value="Class"), Element(value="Class"))
|
||||
ctx.bottom.add_edge(Element(value="Inheritance"), Element(value="Element"), Element(value="Element"))
|
||||
ctx.bottom.add_edge(Element(value="AttributeLink"), Element(value="Element"), Element(value="Attribute"))
|
||||
|
||||
# Attributes --> elements that will be typed by Attribute
|
||||
ctx.bottom.add_value(Element(value="Class_lower_cardinality"), Element(value=INTEGER))
|
||||
ctx.bottom.add_value(Element(value="Class_upper_cardinality"), Element(value=INTEGER))
|
||||
|
||||
ctx.bottom.add_value(Element(value="Association_source_lower_cardinality"), Element(value=INTEGER))
|
||||
ctx.bottom.add_value(Element(value="Association_source_upper_cardinality"), Element(value=INTEGER))
|
||||
ctx.bottom.add_value(Element(value="Association_target_lower_cardinality"), Element(value=INTEGER))
|
||||
ctx.bottom.add_value(Element(value="Association_target_upper_cardinality"), Element(value=INTEGER))
|
||||
|
||||
ctx.bottom.add_value(Element(value="Attribute_name"), Element(value=STRING))
|
||||
ctx.bottom.add_value(Element(value="Attribute_optional"), Element(value=BOOLEAN))
|
||||
|
||||
# Attribute instances --> elements that will be typed by one of the Attributes defined above
|
||||
ctx.bottom.add_value(Element(value="Attribute_name.name"), Element(value="name"))
|
||||
ctx.bottom.add_value(Element(value="Attribute_name.optional"), Element(value=False))
|
||||
ctx.bottom.add_value(Element(value="Attribute_optional.name"), Element(value="optional"))
|
||||
ctx.bottom.add_value(Element(value="Attribute_optional.optional"), Element(value=False))
|
||||
|
||||
ctx.bottom.add_value(Element(value="Class_lower_cardinality.name"), Element(value="lower_cardinality"))
|
||||
ctx.bottom.add_value(Element(value="Class_lower_cardinality.optional"), Element(value=True))
|
||||
ctx.bottom.add_value(Element(value="Class_upper_cardinality.name"), Element(value="upper_cardinality"))
|
||||
ctx.bottom.add_value(Element(value="Class_upper_cardinality.optional"), Element(value=True))
|
||||
|
||||
ctx.bottom.add_value(Element(value="Association_source_lower_cardinality.name"),
|
||||
Element(value="source_lower_cardinality"))
|
||||
ctx.bottom.add_value(Element(value="Association_source_lower_cardinality.optional"), Element(value=True))
|
||||
ctx.bottom.add_value(Element(value="Association_source_upper_cardinality.name"),
|
||||
Element(value="source_upper_cardinality"))
|
||||
ctx.bottom.add_value(Element(value="Association_source_upper_cardinality.optional"), Element(value=True))
|
||||
|
||||
ctx.bottom.add_value(Element(value="Association_target_lower_cardinality.name"),
|
||||
Element(value="target_lower_cardinality"))
|
||||
ctx.bottom.add_value(Element(value="Association_target_lower_cardinality.optional"), Element(value=True))
|
||||
ctx.bottom.add_value(Element(value="Association_target_upper_cardinality.name"),
|
||||
Element(value="target_upper_cardinality"))
|
||||
ctx.bottom.add_value(Element(value="Association_target_upper_cardinality.optional"), Element(value=True))
|
||||
|
||||
# Inheritance instances --> elements that will be typed by Inheritance
|
||||
ctx.bottom.add_edge(Element(value="class_inh_element"), Element(value="Class"), Element(value="Element"))
|
||||
ctx.bottom.add_edge(Element(value="attribute_inh_element"), Element(value="Attribute"), Element(value="Element"))
|
||||
ctx.bottom.add_edge(Element(value="association_inh_element"), Element(value="Association"),
|
||||
Element(value="Element"))
|
||||
ctx.bottom.add_edge(Element(value="attributelink_inh_element"), Element(value="AttributeLink"),
|
||||
Element(value="Element"))
|
||||
|
||||
# AttributeLinks --> elements that will be typed by AttributeLink
|
||||
ctx.bottom.add_edge(Element(value="Class_lower_cardinality_link"), Element(value="Class"),
|
||||
Element(value="Class_lower_cardinality"))
|
||||
ctx.bottom.add_edge(Element(value="Class_upper_cardinality_link"), Element(value="Class"),
|
||||
Element(value="Class_upper_cardinality"))
|
||||
|
||||
ctx.bottom.add_edge(Element(value="Association_source_lower_cardinality_link"), Element(value="Association"),
|
||||
Element(value="Association_source_lower_cardinality"))
|
||||
ctx.bottom.add_edge(Element(value="Association_source_upper_cardinality_link"), Element(value="Association"),
|
||||
Element(value="Association_source_upper_cardinality"))
|
||||
ctx.bottom.add_edge(Element(value="Association_target_lower_cardinality_link"), Element(value="Association"),
|
||||
Element(value="Association_target_lower_cardinality"))
|
||||
ctx.bottom.add_edge(Element(value="Association_target_upper_cardinality_link"), Element(value="Association"),
|
||||
Element(value="Association_target_upper_cardinality"))
|
||||
|
||||
ctx.bottom.add_edge(Element(value="Attribute_name_link"), Element(value="Attribute"),
|
||||
Element(value="Attribute_name"))
|
||||
ctx.bottom.add_edge(Element(value="Attribute_optional_link"), Element(value="Attribute"),
|
||||
Element(value="Attribute_optional"))
|
||||
|
||||
# AttributeLink instances --> elements that will be typed by one of the AttributeLink defined above
|
||||
ctx.bottom.add_edge(Element(value="Attribute_name.name_link"), Element(value="Attribute_name"),
|
||||
Element(value="Attribute_name.name"))
|
||||
ctx.bottom.add_edge(Element(value="Attribute_name.optional_link"), Element(value="Attribute_name"),
|
||||
Element(value="Attribute_name.optional"))
|
||||
ctx.bottom.add_edge(Element(value="Attribute_optional.name_link"), Element(value="Attribute_optional"),
|
||||
Element(value="Attribute_optional.name"))
|
||||
ctx.bottom.add_edge(Element(value="Attribute_optional.optional_link"), Element(value="Attribute_optional"),
|
||||
Element(value="Attribute_optional.optional"))
|
||||
|
||||
ctx.bottom.add_edge(Element(value="Class_lower_cardinality.name_link"), Element(value="Class_lower_cardinality"),
|
||||
Element(value="Class_lower_cardinality.name"))
|
||||
ctx.bottom.add_edge(Element(value="Class_lower_cardinality.optional_link"),
|
||||
Element(value="Class_lower_cardinality"),
|
||||
Element(value="Class_lower_cardinality.optional"))
|
||||
ctx.bottom.add_edge(Element(value="Class_upper_cardinality.name_link"), Element(value="Class_upper_cardinality"),
|
||||
Element(value="Class_upper_cardinality.name"))
|
||||
ctx.bottom.add_edge(Element(value="Class_upper_cardinality.optional_link"),
|
||||
Element(value="Class_upper_cardinality"),
|
||||
Element(value="Class_upper_cardinality.optional"))
|
||||
|
||||
ctx.bottom.add_edge(Element(value="Association_source_lower_cardinality.name_link"),
|
||||
Element(value="Association_source_lower_cardinality"),
|
||||
Element(value="Association_source_lower_cardinality.name"))
|
||||
ctx.bottom.add_edge(Element(value="Association_source_lower_cardinality.optional_link"),
|
||||
Element(value="Association_source_lower_cardinality"),
|
||||
Element(value="Association_source_lower_cardinality.optional"))
|
||||
ctx.bottom.add_edge(Element(value="Association_source_upper_cardinality.name_link"),
|
||||
Element(value="Association_source_upper_cardinality"),
|
||||
Element(value="Association_source_upper_cardinality.name"))
|
||||
ctx.bottom.add_edge(Element(value="Association_source_upper_cardinality.optional_link"),
|
||||
Element(value="Association_source_upper_cardinality"),
|
||||
Element(value="Association_source_upper_cardinality.optional"))
|
||||
|
||||
ctx.bottom.add_edge(Element(value="Association_target_lower_cardinality.name_link"),
|
||||
Element(value="Association_target_lower_cardinality"),
|
||||
Element(value="Association_target_lower_cardinality.name"))
|
||||
ctx.bottom.add_edge(Element(value="Association_target_lower_cardinality.optional_link"),
|
||||
Element(value="Association_target_lower_cardinality"),
|
||||
Element(value="Association_target_lower_cardinality.optional"))
|
||||
ctx.bottom.add_edge(Element(value="Association_target_upper_cardinality.name_link"),
|
||||
Element(value="Association_target_upper_cardinality"),
|
||||
Element(value="Association_target_upper_cardinality.name"))
|
||||
ctx.bottom.add_edge(Element(value="Association_target_upper_cardinality.optional_link"),
|
||||
Element(value="Association_target_upper_cardinality"),
|
||||
Element(value="Association_target_upper_cardinality.optional"))
|
||||
|
||||
"""
|
||||
Retype the elements of the model.
|
||||
This way we make the model "metacircular".
|
||||
"""
|
||||
ctx.retype_element(Element(value="Element"), Element(value="Class"))
|
||||
ctx.retype_element(Element(value="Class"), Element(value="Class"))
|
||||
ctx.retype_element(Element(value="Attribute"), Element(value="Class"))
|
||||
|
||||
ctx.retype_element(Element(value="Association"), Element(value="Association"))
|
||||
ctx.retype_element(Element(value="Inheritance"), Element(value="Association"))
|
||||
ctx.retype_element(Element(value="AttributeLink"), Element(value="Association"))
|
||||
|
||||
ctx.retype_element(Element(value="Class_lower_cardinality"), Element(value="Attribute"))
|
||||
ctx.retype_element(Element(value="Class_upper_cardinality"), Element(value="Attribute"))
|
||||
ctx.retype_element(Element(value="Association_source_lower_cardinality"), Element(value="Attribute"))
|
||||
ctx.retype_element(Element(value="Association_source_upper_cardinality"), Element(value="Attribute"))
|
||||
ctx.retype_element(Element(value="Association_target_lower_cardinality"), Element(value="Attribute"))
|
||||
ctx.retype_element(Element(value="Association_target_upper_cardinality"), Element(value="Attribute"))
|
||||
ctx.retype_element(Element(value="Attribute_name"), Element(value="Attribute"))
|
||||
ctx.retype_element(Element(value="Attribute_optional"), Element(value="Attribute"))
|
||||
|
||||
ctx.retype_element(Element(value="Class_lower_cardinality_link"), Element(value="AttributeLink"))
|
||||
ctx.retype_element(Element(value="Class_upper_cardinality_link"), Element(value="AttributeLink"))
|
||||
ctx.retype_element(Element(value="Association_source_lower_cardinality_link"), Element(value="AttributeLink"))
|
||||
ctx.retype_element(Element(value="Association_source_upper_cardinality_link"), Element(value="AttributeLink"))
|
||||
ctx.retype_element(Element(value="Association_target_lower_cardinality_link"), Element(value="AttributeLink"))
|
||||
ctx.retype_element(Element(value="Association_target_upper_cardinality_link"), Element(value="AttributeLink"))
|
||||
ctx.retype_element(Element(value="Attribute_name_link"), Element(value="AttributeLink"))
|
||||
ctx.retype_element(Element(value="Attribute_optional_link"), Element(value="AttributeLink"))
|
||||
|
||||
ctx.retype_element(Element(value="class_inh_element"), Element(value="Inheritance"))
|
||||
ctx.retype_element(Element(value="attribute_inh_element"), Element(value="Inheritance"))
|
||||
ctx.retype_element(Element(value="association_inh_element"), Element(value="Inheritance"))
|
||||
ctx.retype_element(Element(value="attributelink_inh_element"), Element(value="Inheritance"))
|
||||
|
||||
ctx.retype_element(Element(value="Attribute_name.name"), Element(value="Attribute_name"))
|
||||
ctx.retype_element(Element(value="Attribute_name.optional"), Element(value="Attribute_optional"))
|
||||
ctx.retype_element(Element(value="Attribute_optional.name"), Element(value="Attribute_name"))
|
||||
ctx.retype_element(Element(value="Attribute_optional.optional"), Element(value="Attribute_optional"))
|
||||
ctx.retype_element(Element(value="Class_lower_cardinality.name"), Element(value="Attribute_name"))
|
||||
ctx.retype_element(Element(value="Class_lower_cardinality.optional"), Element(value="Attribute_optional"))
|
||||
ctx.retype_element(Element(value="Class_upper_cardinality.name"), Element(value="Attribute_name"))
|
||||
ctx.retype_element(Element(value="Class_upper_cardinality.optional"), Element(value="Attribute_optional"))
|
||||
ctx.retype_element(Element(value="Association_source_lower_cardinality.name"), Element(value="Attribute_name"))
|
||||
ctx.retype_element(Element(value="Association_source_lower_cardinality.optional"),
|
||||
Element(value="Attribute_optional"))
|
||||
ctx.retype_element(Element(value="Association_source_upper_cardinality.name"), Element(value="Attribute_name"))
|
||||
ctx.retype_element(Element(value="Association_source_upper_cardinality.optional"),
|
||||
Element(value="Attribute_optional"))
|
||||
ctx.retype_element(Element(value="Association_target_lower_cardinality.name"), Element(value="Attribute_name"))
|
||||
ctx.retype_element(Element(value="Association_target_lower_cardinality.optional"),
|
||||
Element(value="Attribute_optional"))
|
||||
ctx.retype_element(Element(value="Association_target_upper_cardinality.name"), Element(value="Attribute_name"))
|
||||
ctx.retype_element(Element(value="Association_target_upper_cardinality.optional"),
|
||||
Element(value="Attribute_optional"))
|
||||
|
||||
ctx.retype_element(Element(value="Attribute_name.name_link"), Element(value="Attribute_name_link"))
|
||||
ctx.retype_element(Element(value="Attribute_name.optional_link"), Element(value="Attribute_optional_link"))
|
||||
ctx.retype_element(Element(value="Attribute_optional.name_link"), Element(value="Attribute_name_link"))
|
||||
ctx.retype_element(Element(value="Attribute_optional.optional_link"), Element(value="Attribute_optional_link"))
|
||||
ctx.retype_element(Element(value="Class_lower_cardinality.name_link"), Element(value="Attribute_name_link"))
|
||||
ctx.retype_element(Element(value="Class_lower_cardinality.optional_link"), Element(value="Attribute_optional_link"))
|
||||
ctx.retype_element(Element(value="Class_upper_cardinality.name_link"), Element(value="Attribute_name_link"))
|
||||
ctx.retype_element(Element(value="Class_upper_cardinality.optional_link"), Element(value="Attribute_optional_link"))
|
||||
ctx.retype_element(Element(value="Association_source_lower_cardinality.name_link"),
|
||||
Element(value="Attribute_name_link"))
|
||||
ctx.retype_element(Element(value="Association_source_lower_cardinality.optional_link"),
|
||||
Element(value="Attribute_optional_link"))
|
||||
ctx.retype_element(Element(value="Association_source_upper_cardinality.name_link"),
|
||||
Element(value="Attribute_name_link"))
|
||||
ctx.retype_element(Element(value="Association_source_upper_cardinality.optional_link"),
|
||||
Element(value="Attribute_optional_link"))
|
||||
ctx.retype_element(Element(value="Association_target_lower_cardinality.name_link"),
|
||||
Element(value="Attribute_name_link"))
|
||||
ctx.retype_element(Element(value="Association_target_lower_cardinality.optional_link"),
|
||||
Element(value="Attribute_optional_link"))
|
||||
ctx.retype_element(Element(value="Association_target_upper_cardinality.name_link"),
|
||||
Element(value="Attribute_name_link"))
|
||||
ctx.retype_element(Element(value="Association_target_upper_cardinality.optional_link"),
|
||||
Element(value="Attribute_optional_link"))
|
||||
|
||||
return Element(id=scd)
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
from core.context.simple_class_diagrams import SCDContext
|
||||
|
||||
custom_contexts = {
|
||||
"SimpleClassDiagrams": SCDContext
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
from abc import ABC, abstractmethod
|
||||
from state.base import State
|
||||
from core.element import Element, String
|
||||
|
||||
|
||||
class Context(ABC):
|
||||
def __init__(self, state: State, model: Element, metamodel: Element):
|
||||
self.state = state
|
||||
self.model = model
|
||||
self.metamodel = metamodel
|
||||
|
||||
@abstractmethod
|
||||
def __enter__(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def __exit__(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def exposed_methods(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def instantiate(self, type_name: String, instance_name: String):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def instantiate_value(self, type_name: String, instance_name: String, value: Element):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def instantiate_link(self, type_name: String, name: String, source: String, target: String):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def delete_element(self, name: String):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def verify(self):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def list_elements(self):
|
||||
pass
|
||||
|
||||
def list_types(self):
|
||||
# can be implemented here since we assume that metamodel
|
||||
# is always in graph fo, i.e. in the MV-state graph.
|
||||
unsorted = []
|
||||
model_root = self.state.read_dict(self.metamodel.id, "Model")
|
||||
for elem_edge in self.state.read_outgoing(model_root):
|
||||
# get element name
|
||||
label_edge, = self.state.read_outgoing(elem_edge)
|
||||
_, label_node = self.state.read_edge(label_edge)
|
||||
label = self.state.read_value(label_node)
|
||||
# find element type
|
||||
elem_type_node = self.state.read_dict(label_node, "Type")
|
||||
elem_type = self.state.read_value(elem_type_node)
|
||||
unsorted.append(f"{label} : {elem_type if elem_type is not None else '_'}")
|
||||
for i in sorted(unsorted):
|
||||
print(i)
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
from state.base import INTEGER, FLOAT, BOOLEAN, STRING, TYPE, State
|
||||
from core.element import Element, String
|
||||
|
||||
|
||||
class BottomContext:
|
||||
def __init__(self, state: State, model: Element):
|
||||
self.state = state
|
||||
self.model = model
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self):
|
||||
pass
|
||||
|
||||
def add_node(self, name: String):
|
||||
model_root = self.state.read_dict(self.model.id, "Model")
|
||||
# create model element
|
||||
element = self.state.create_node()
|
||||
# connect to model root
|
||||
self.state.create_dict(model_root, name.value, element)
|
||||
# confirm that element has been added to the model
|
||||
element_found = self.state.read_dict(model_root, name.value)
|
||||
if element_found is None:
|
||||
self.state.delete_node(element)
|
||||
print(f"Warning: Invalid name {name.value}, element not created.")
|
||||
return
|
||||
|
||||
def add_value(self, name: String, value: Element):
|
||||
model_root = self.state.read_dict(self.model.id, "Model")
|
||||
# create model element
|
||||
element = self.state.create_nodevalue(value.value)
|
||||
if element is None:
|
||||
print("Warning: Invalid value, value node not created.")
|
||||
return
|
||||
# connect to model root
|
||||
self.state.create_dict(model_root, name.value, element)
|
||||
# confirm that element has been added to the model
|
||||
element_found = self.state.read_dict(model_root, name.value)
|
||||
if element_found is None:
|
||||
self.state.delete_node(element)
|
||||
print(f"Warning: Invalid name {name.value}, element not created.")
|
||||
return
|
||||
|
||||
def add_edge(self, name: String, source: String, target: String):
|
||||
model_root = self.state.read_dict(self.model.id, "Model")
|
||||
source_element = self.state.read_dict(model_root, source.value)
|
||||
if source_element is None:
|
||||
print(f"Warning: Unknown source element {source.value}, edge not created.")
|
||||
return
|
||||
target_element = self.state.read_dict(model_root, target.value)
|
||||
if target_element is None:
|
||||
print(f"Warning: Unknown target element {target.value}, edge not created.")
|
||||
return
|
||||
# create model element
|
||||
element = self.state.create_edge(source_element, target_element)
|
||||
# connect to model root
|
||||
self.state.create_dict(model_root, name.value, element)
|
||||
# confirm that element has been added to the model
|
||||
element_found = self.state.read_dict(model_root, name.value)
|
||||
if element_found is None:
|
||||
self.state.delete_edge(element)
|
||||
print(f"Warning: Invalid name {name.value}, element not created.")
|
||||
|
||||
def delete_element(self, name: String):
|
||||
model_root = self.state.read_dict(self.model.id, "Model")
|
||||
element = self.state.read_dict(model_root, name.value)
|
||||
# could be both a node or an edge
|
||||
self.state.delete_node(element)
|
||||
self.state.delete_edge(element)
|
||||
|
||||
def list_elements(self):
|
||||
def is_edge(element: str) -> bool:
|
||||
edge = self.state.read_edge(element)
|
||||
return edge is not None
|
||||
|
||||
def value_type(value) -> str:
|
||||
mapping = {
|
||||
int: INTEGER,
|
||||
float: FLOAT,
|
||||
str: STRING,
|
||||
bool: BOOLEAN,
|
||||
tuple: TYPE
|
||||
}
|
||||
return mapping[type(value)][0]
|
||||
|
||||
unsorted = []
|
||||
model_root = self.state.read_dict(self.model.id, "Model")
|
||||
for elem_edge in self.state.read_outgoing(model_root):
|
||||
# get element name
|
||||
label_edge, = self.state.read_outgoing(elem_edge)
|
||||
_, label_node = self.state.read_edge(label_edge)
|
||||
label = self.state.read_value(label_node)
|
||||
# find element bottom type
|
||||
_, elem = self.state.read_edge(elem_edge)
|
||||
if is_edge(elem):
|
||||
bottom_type = "Edge"
|
||||
else:
|
||||
# is_node
|
||||
elem_value = self.state.read_value(elem)
|
||||
if elem_value is None:
|
||||
bottom_type = "Node"
|
||||
else:
|
||||
bottom_type = value_type
|
||||
unsorted.append(f"{label} : {bottom_type}")
|
||||
for i in sorted(unsorted):
|
||||
print(i)
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
from core.element import Element, String, Boolean
|
||||
from state.base import State
|
||||
from core.context.base import Context
|
||||
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)
|
||||
|
||||
def __enter__(self):
|
||||
pass
|
||||
|
||||
def __exit__(self):
|
||||
pass
|
||||
|
||||
def exposed_methods(self):
|
||||
yield from [
|
||||
self.instantiate,
|
||||
self.instantiate_value,
|
||||
self.instantiate_link,
|
||||
self.retype_element,
|
||||
self.delete_element,
|
||||
self.list_elements,
|
||||
self.list_types,
|
||||
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) != (None, None)
|
||||
return element_is_edge == instantiate_link
|
||||
|
||||
def instantiate(self, type_name: String, name: String):
|
||||
if not self._type_exists(type_name, instantiate_link=False):
|
||||
print(f"Attempting to instantiate element with invalid type: {type_name.value}")
|
||||
else:
|
||||
self.bottom.add_node(name)
|
||||
self.retype_element(name, type_name)
|
||||
|
||||
def instantiate_value(self, type_name: String, name: String, value: Element):
|
||||
if not self._type_exists(type_name, instantiate_link=False):
|
||||
print(f"Attempting to instantiate element with invalid type: {type_name.value}")
|
||||
else:
|
||||
self.bottom.add_value(name, value)
|
||||
self.retype_element(name, type_name)
|
||||
|
||||
def instantiate_link(self, type_name: String, name: String, source: String, target: String):
|
||||
if not self._type_exists(type_name, instantiate_link=True):
|
||||
print(f"Attempting to instantiate link with invalid type: {type_name.value}")
|
||||
else:
|
||||
self.bottom.add_edge(name, source, target)
|
||||
self.retype_element(name, type_name)
|
||||
|
||||
def delete_element(self, name: String):
|
||||
self.bottom.delete_element(name)
|
||||
|
||||
def verify(self):
|
||||
pass # TODO: implement conformance check
|
||||
|
||||
def list_elements(self):
|
||||
model_root = self.state.read_dict(self.model.id, "Model")
|
||||
unsorted = []
|
||||
for elem_edge in self.state.read_outgoing(model_root):
|
||||
# get element name
|
||||
label_edge, = self.state.read_outgoing(elem_edge)
|
||||
_, label_node = self.state.read_edge(label_edge)
|
||||
label = self.state.read_value(label_node)
|
||||
type_node = self.state.read_dict(label_node, "Type")
|
||||
type_name = self.state.read_value(type_node)
|
||||
unsorted.append(f"{label} : {type_name}")
|
||||
for i in sorted(unsorted):
|
||||
print(i)
|
||||
|
||||
def retype_element(self, name: String, type_name: String):
|
||||
model_root = self.state.read_dict(self.model.id, "Model")
|
||||
element_edge = self.state.read_dict_edge(model_root, name.value)
|
||||
if element_edge is None:
|
||||
print(f"Error: Element with name {name.value} not found.")
|
||||
return
|
||||
label_node_edge, = self.state.read_outgoing(element_edge)
|
||||
_, label_node = self.state.read_edge(label_node_edge)
|
||||
# create type name node
|
||||
type_name_node = self.state.create_nodevalue(type_name.value)
|
||||
if type_name_node is None:
|
||||
print("Error: Invalid type name, element not retyped.")
|
||||
# remove any existing type node
|
||||
existing = self.state.read_dict(label_node, "Type")
|
||||
if existing is not None:
|
||||
self.state.delete_node(existing)
|
||||
# create new type node
|
||||
self.state.create_dict(label_node, "Type", type_name_node)
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
from core.element import Element, String, Integer, Boolean
|
||||
from state.base import State
|
||||
from core.context.generic import GenericContext
|
||||
|
||||
|
||||
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 create_class(self, name: String, lower_cardinality: Integer = Element(), upper_cardinality: Integer = Element()):
|
||||
self.instantiate(Element(value="Class"), name)
|
||||
if lower_cardinality.value is not None:
|
||||
self.instantiate_value(
|
||||
Element(value="Class_lower_cardinality"),
|
||||
Element(value=name.value + ".lower_cardinality"),
|
||||
lower_cardinality
|
||||
)
|
||||
self.instantiate_link(
|
||||
Element(value="Class_lower_cardinality_link"),
|
||||
Element(value=name.value + ".lower_cardinality_link"),
|
||||
name,
|
||||
Element(value=name.value + ".lower_cardinality")
|
||||
)
|
||||
if upper_cardinality.value is not None:
|
||||
self.instantiate_value(
|
||||
Element(value="Class_upper_cardinality"),
|
||||
Element(value=name.value + ".upper_cardinality"),
|
||||
upper_cardinality
|
||||
)
|
||||
self.instantiate_link(
|
||||
Element(value="Class_upper_cardinality_link"),
|
||||
Element(value=name.value + ".upper_cardinality_link"),
|
||||
name,
|
||||
Element(value=name.value + ".upper_cardinality")
|
||||
)
|
||||
|
||||
def create_class_attribute(self, class_name: String, name: String, optional: Boolean = Element(value=False)):
|
||||
# create attribute
|
||||
element_name = Element(value=f"{class_name.value}_{name.value}")
|
||||
element_link_name = Element(value=f"{class_name.value}_{name.value}_link")
|
||||
self.instantiate(Element(value="Attribute"), element_name)
|
||||
self.instantiate_link(Element(value="AttributeLink"), element_link_name, class_name, element_name)
|
||||
# set attribute's attributes
|
||||
attr_name_name = Element(value=f"{class_name.value}_{name.value}.name")
|
||||
attr_optional_name = Element(value=f"{class_name.value}_{name.value}.optional")
|
||||
attr_name_link_name = Element(value=f"{class_name.value}_{name.value}.name_link")
|
||||
attr_optional_link_name = Element(value=f"{class_name.value}_{name.value}.optional_link")
|
||||
self.instantiate_value(Element(value="Attribute_name"), attr_name_name, name)
|
||||
self.instantiate_value(Element(value="Attribute_optional"), attr_optional_name, optional)
|
||||
self.instantiate_link(Element(value="Attribute_name_link"), attr_name_link_name, element_name, attr_name_name)
|
||||
self.instantiate_link(Element(value="Attribute_optional_link"), attr_optional_link_name, element_name, attr_optional_name)
|
||||
|
||||
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()
|
||||
):
|
||||
self.instantiate_link(Element(value="Association"), name, source_class_name, target_class_name)
|
||||
if source_lower_cardinality.value is not None:
|
||||
self.instantiate_value(
|
||||
Element(value="Association_source_lower_cardinality"),
|
||||
Element(value=name.value + ".source_lower_cardinality"),
|
||||
source_lower_cardinality
|
||||
)
|
||||
self.instantiate_link(
|
||||
Element(value="Association_source_lower_cardinality_link"),
|
||||
Element(value=name.value + ".source_lower_cardinality_link"),
|
||||
name,
|
||||
Element(value=name.value + ".source_lower_cardinality")
|
||||
)
|
||||
if source_upper_cardinality.value is not None:
|
||||
self.instantiate_value(
|
||||
Element(value="Association_source_upper_cardinality"),
|
||||
Element(value=name.value + ".source_upper_cardinality"),
|
||||
source_upper_cardinality
|
||||
)
|
||||
self.instantiate_link(
|
||||
Element(value="Association_source_upper_cardinality_link"),
|
||||
Element(value=name.value + ".source_upper_cardinality_link"),
|
||||
name,
|
||||
Element(value=name.value + ".source_upper_cardinality")
|
||||
)
|
||||
if target_lower_cardinality.value is not None:
|
||||
self.instantiate_value(
|
||||
Element(value="Association_target_lower_cardinality"),
|
||||
Element(value=name.value + ".target_lower_cardinality"),
|
||||
target_lower_cardinality
|
||||
)
|
||||
self.instantiate_link(
|
||||
Element(value="Association_target_lower_cardinality_link"),
|
||||
Element(value=name.value + ".target_lower_cardinality_link"),
|
||||
name,
|
||||
Element(value=name.value + ".target_lower_cardinality")
|
||||
)
|
||||
if target_upper_cardinality.value is not None:
|
||||
self.instantiate_value(
|
||||
Element(value="Association_target_upper_cardinality"),
|
||||
Element(value=name.value + ".target_upper_cardinality"),
|
||||
target_upper_cardinality
|
||||
)
|
||||
self.instantiate_link(
|
||||
Element(value="Association_target_upper_cardinality_link"),
|
||||
Element(value=name.value + ".target_upper_cardinality_link"),
|
||||
name,
|
||||
Element(value=name.value + ".target_upper_cardinality")
|
||||
)
|
||||
|
||||
def create_inheritance(self, parent_class_name: String, child_class_name: String):
|
||||
self.instantiate_link(
|
||||
Element(value="Inheritance"),
|
||||
Element(value=f"{child_class_name.value}_inherits_from_{parent_class_name.value}"),
|
||||
child_class_name,
|
||||
parent_class_name)
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
from dataclasses import dataclass
|
||||
from typing import TypeVar, Generic, Optional, Literal
|
||||
from state.base import INTEGER, FLOAT, BOOLEAN, STRING, TYPE
|
||||
|
||||
# Some typing information for Python static type checkers
|
||||
bottom_type = Literal[INTEGER, FLOAT, BOOLEAN, STRING, TYPE]
|
||||
T = TypeVar('T', int, float, bool, str, bottom_type)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Element(Generic[T]):
|
||||
"""
|
||||
An Element can represent one of following two things, based on the value of its attributes:
|
||||
|
||||
* An element (node or edge) in the State (id is not None). In this case the value can be None because it hasn't
|
||||
yet been read OR because the element doesn't have a value.
|
||||
* A value for which a node has not yet been materialized in the State (id is None, value is not None).
|
||||
|
||||
|
||||
If you are familiar with the Modelverse Kernel, this class serves a function similar to the {id: ..., value: ...}
|
||||
dict that is used there.
|
||||
"""
|
||||
id: Optional[str] = None
|
||||
value: Optional[T] = None
|
||||
|
||||
def is_none(self) -> bool:
|
||||
return self.id is None and self.value is None
|
||||
|
||||
|
||||
String = Element[str]
|
||||
Integer = Element[int]
|
||||
Float = Element[float]
|
||||
Boolean = Element[bool]
|
||||
Type = Element[bottom_type]
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
from state.base import State
|
||||
from core.element import Element, String
|
||||
|
||||
|
||||
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)
|
||||
if mm_bottom is None:
|
||||
print(f"Error: Invalid type model name {type_model_name.value}. Model not created.")
|
||||
return Element()
|
||||
bottom = self.state.create_nodevalue(name.value)
|
||||
if bottom is None:
|
||||
print(f"Error: Invalid model name {name.value}. Model not created.")
|
||||
return Element()
|
||||
self.state.create_dict(root, name.value, bottom)
|
||||
self.state.create_dict(bottom, "Model", self.state.create_node())
|
||||
self.state.create_dict(bottom, "Metamodel", mm_bottom)
|
||||
return Element(id=bottom)
|
||||
|
||||
def get_model(self, name: String) -> Element:
|
||||
root = self.state.read_root()
|
||||
model = self.state.read_dict(root, name.value)
|
||||
if model is None:
|
||||
print(f"Error: Cannot find model with name {name.value}.")
|
||||
return Element()
|
||||
return Element(id=model)
|
||||
|
||||
def rename_model(self, name: String, new_name: String):
|
||||
root = self.state.read_root()
|
||||
name_used = self.state.read_dict_edge(root, new_name.value)
|
||||
if name_used:
|
||||
print(f"Error: Model with name {new_name.value} already exists. Please use another name.")
|
||||
return
|
||||
mode_edge = self.state.read_dict_edge(root, name.value)
|
||||
if mode_edge is None:
|
||||
print(f"Error: Cannot find model with name {name.value}.")
|
||||
return
|
||||
_, model_node = self.state.read_edge(mode_edge)
|
||||
self.state.create_dict(root, new_name.value, model_node)
|
||||
created = self.state.read_dict_edge(root, new_name.value)
|
||||
if created is None:
|
||||
print(f"Error: Invalid model name {new_name.value}. Model not renamed.")
|
||||
else:
|
||||
self.state.delete_edge(mode_edge)
|
||||
|
||||
def delete_model(self, name: String):
|
||||
root = self.state.read_root()
|
||||
model = self.state.read_dict(root, name.value)
|
||||
if model is None:
|
||||
print(f"Error: No model found for name {name.value}.")
|
||||
else:
|
||||
self.state.delete_node(model)
|
||||
|
||||
def list_models(self):
|
||||
unsorted = []
|
||||
for edge in self.state.read_outgoing(self.state.read_root()):
|
||||
_, model = self.state.read_edge(edge)
|
||||
metamodel = self.state.read_dict(model, "Metamodel")
|
||||
unsorted.append(f"{self.state.read_value(model)} : {self.state.read_value(metamodel)}")
|
||||
for x in sorted(unsorted):
|
||||
print(x)
|
||||
|
||||
def retype_model(self, model_name: String, metamodel_name: String):
|
||||
root = self.state.read_root()
|
||||
model = self.state.read_dict(root, model_name.value)
|
||||
if model is None:
|
||||
print(f"Error: Cannot find model with name {model_name.value}.")
|
||||
metamodel = self.state.read_dict(root, metamodel_name.value)
|
||||
if metamodel is None:
|
||||
print(f"Error: Cannot find model with name {metamodel_name.value}.")
|
||||
metamodel_edge = self.state.read_dict_edge(model, "Metamodel")
|
||||
if metamodel_edge is not None:
|
||||
self.state.delete_edge(metamodel_edge)
|
||||
self.state.create_dict(model, "Metamodel", metamodel)
|
||||
124
main.py
124
main.py
|
|
@ -1,124 +0,0 @@
|
|||
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
|
||||
arg = Element(value=arg)
|
||||
args.append(arg)
|
||||
continue
|
||||
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)
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
autopep8==1.5.7
|
||||
mypy==0.910
|
||||
Loading…
Add table
Add a link
Reference in a new issue