Bläddra i källkod

reworked code for verifying node attributes in instance model

Lucas Heer 7 år sedan
förälder
incheckning
a195ba50da

+ 7 - 0
models/sketching/example_model_1.mvc

@@ -30,3 +30,10 @@ Edge e2(n1, n3) {
 Edge e3(n1, n4) {
     directed = False
 }
+
+Attribute a1 {
+    key = "IP"
+    value = "192.168.0.1"
+}
+
+NodeAttribute na1(n1, a1) {}

+ 13 - 7
models/sketching/example_model_2.mvc

@@ -23,13 +23,6 @@ Node n5 {
     typeID = "PC"
 }
 
-Attribute a1 {
-    key = "owner"
-    value = "Peter"
-}
-
-NodeAttribute na1(n5, a1) {}
-
 Edge e1(n1, n2) {
     directed = False
 }
@@ -45,3 +38,16 @@ Edge e3(n2, n4) {
 Edge e4(n1, n5) {
     directed = False
 }
+
+Attribute a1 {
+    key = "owner"
+    value = "Peter"
+}
+
+Attribute a2 {
+    key = "IP"
+    value = "192.168.0.1"
+}
+
+NodeAttribute na1(n5, a1) {}
+NodeAttribute na2(n1, a2) {}

+ 2 - 0
sketchUI/im_mainwindow.py

@@ -177,6 +177,7 @@ class IMMainWindow(QMainWindow, Ui_MainWindow):
         verify = Verifier(self._cur_model)
         verify.init()
 
+        """
         self.plainTextEdit.appendPlainText("Verify: Checking node typing ...")
         self.plainTextEdit.repaint()
         ret = verify.verify_node_typing()
@@ -198,6 +199,7 @@ class IMMainWindow(QMainWindow, Ui_MainWindow):
         else:
             self.plainTextEdit.appendPlainText("OK")
             self.plainTextEdit.repaint()
+        """
 
         self.plainTextEdit.appendPlainText("Verify: Checking attributes ...")
         self.plainTextEdit.repaint()

+ 80 - 14
verifier.py

@@ -46,21 +46,11 @@ class Verifier(object):
         Should actually not be neccessary since instance modeling only allows types from
         example models.
         """
-        # First, get a list of all types found in all example models.
-        all_types = []
-        for exm in self._example_models:
-            all_nodes = mv.all_instances(exm, "Node")
-            for node in all_nodes:
-                typ = mv.read_attrs(exm, node)["typeID"]
-                if not typ in all_types:
-                    all_types.append(typ)
-        # print("Verify: types found in example models: {}".format(all_types))
-
         # Check for every node in instance model if it has a valid type
         all_nodes = mv.all_instances(self._instance_model, "Node")
         for node in all_nodes:
             node_typ = commons.get_node_type(self._instance_model, node)
-            if node_typ not in all_types:
+            if node_typ not in self._available_types:
                 return {"OK": False, "error": "Type {} from instance model not in example models".format(node_typ)}
 
         return {"OK":True, "error":None}
@@ -84,14 +74,91 @@ class Verifier(object):
 
         return {"OK": True, "error": None}
 
+    def _get_attributes_of_all_types(self):
+        """
+        Helper for attribute check that returns a dictionary of the form {type:[attr_key_1, attr_key_2, ...], ...},
+        listing all attributes of every type from example models
+        """
+        attrs_of_types = {node_type:[] for node_type in self._available_types}
+        for exm in self._example_models:
+            for node_type, attrs in attrs_of_types.iteritems():
+                attrs_of_type_in_exm = [x.key for x in commons.get_all_attributes_of_type(exm, node_type)]
+                for attr in attrs_of_type_in_exm:
+                    if not attr in attrs:
+                        attrs.append(attr)
+        return attrs_of_types
+
+    def _is_attribute_mandatory_in(self, model, node_type, attr_key):
+        """
+        Helper for attribute check that returns True if the attribute attr_key of type node_type is mandatory (i.e
+        occurs in every node of the type) in model.
+        """
+        nodes_of_type = commons.all_nodes_with_type(model, node_type)
+        attrs_of_type = commons.get_all_attributes_of_type(model, node_type)
+        ctr = 0
+        for attr in attrs_of_type:
+            if attr.key == attr_key:
+                ctr += 1
+        return len(nodes_of_type) == ctr
+
+    def _is_attribute_mandatory(self, node_type, attr_key):
+        """
+        Helper for attribute check that returns True if the attribute attr_key of type node_type is mandatory by
+        looking at all example models.
+        """
+        mand_list = []
+        for exm in self._example_models:
+            is_mandatory = self._is_attribute_mandatory_in(exm, node_type, attr_key)
+            mand_list.append(is_mandatory)
+        return all(mand_list)
+
     def verify_attributes(self):
         """
         1. For every attribute key of a typed node in the instance model, there must be a corresponding
         attribute key in some example model.
         2. An attribute for a type is mandatory if it occurs in every example model.
         """
-
-        # TODO: implement
+        # Check attribute keys for every node in instance model
+        all_nodes = mv.all_instances(self._instance_model, "Node")
+        for node in all_nodes:
+            attrs = commons.get_attributes_of_node(self._instance_model, node)
+            if not attrs:
+                continue
+            node_typ = commons.get_node_type(self._instance_model, node)
+            for attr in attrs:
+                # check every example model if such an attribute key is present for the specific type
+                for exm in self._example_models:
+                    exm_attrs = commons.get_all_attributes_of_type(exm, node_typ)
+                    if attr.key in [x.key for x in exm_attrs]:
+                        break
+                else:
+                    # loop completed without break, so we did not find any key in example models
+                    return {"OK": False, "error": "No key {} for type {} in example models".format(attr.key, node_typ)}
+
+        # Check if mandatory attributes are present in instance model
+        attr_mandatory = {node_type:{} for node_type in self._available_types}
+        all_attrs = self._get_attributes_of_all_types()
+        for typ_i, attr_list in all_attrs.iteritems():
+            for typ_j, dic in attr_mandatory.iteritems():
+                if typ_j == typ_i:
+                    for attr in attr_list:
+                        dic[attr] = False
+        # have dict like {"PC": {"owner":False}, "Router": {"IP":False}, ...}
+        # now need to check which one is mandatory and set the boolean accordingly
+        for node_type, attr_dict in attr_mandatory.iteritems():
+            for attr, _ in attr_dict.iteritems():
+                if self._is_attribute_mandatory(node_type, attr):
+                    attr_dict[attr] = True
+
+        # for every node in instance model, check if it has the mandatory attributes
+        for node in mv.all_instances(self._instance_model, "Node"):
+            node_type = commons.get_node_type(self._instance_model, node)
+            node_attrs = commons.get_attributes_of_node(self._instance_model, node)
+            attr_mand = attr_mandatory[node_type]
+            for attr, mand in attr_mand.iteritems():
+                if mand:
+                    if not attr in [x.key for x in node_attrs]:
+                        return {"OK": False, "error":"Attribute {} for type {} mandatory".format(attr, node_type)}
 
         return {"OK": True, "error": None}
 
@@ -105,7 +172,6 @@ class Verifier(object):
         to connect two nodes).
         """
 
-        # TODO: implement
 
         return {"OK": True, "error": None}
 

+ 1 - 1
wrappers/modelverse_SCCD.py

@@ -1,7 +1,7 @@
 """
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
-Date:   Thu Apr 26 11:05:54 2018
+Date:   Thu Apr 26 14:15:31 2018
 
 Model author: Yentl Van Tendeloo
 Model name:   MvK Server