Browse Source

reworked code for verifying node attributes in instance model

Lucas Heer 7 years ago
parent
commit
a195ba50da

+ 7 - 0
models/sketching/example_model_1.mvc

@@ -30,3 +30,10 @@ Edge e2(n1, n3) {
 Edge e3(n1, n4) {
 Edge e3(n1, n4) {
     directed = False
     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"
     typeID = "PC"
 }
 }
 
 
-Attribute a1 {
-    key = "owner"
-    value = "Peter"
-}
-
-NodeAttribute na1(n5, a1) {}
-
 Edge e1(n1, n2) {
 Edge e1(n1, n2) {
     directed = False
     directed = False
 }
 }
@@ -45,3 +38,16 @@ Edge e3(n2, n4) {
 Edge e4(n1, n5) {
 Edge e4(n1, n5) {
     directed = False
     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 = Verifier(self._cur_model)
         verify.init()
         verify.init()
 
 
+        """
         self.plainTextEdit.appendPlainText("Verify: Checking node typing ...")
         self.plainTextEdit.appendPlainText("Verify: Checking node typing ...")
         self.plainTextEdit.repaint()
         self.plainTextEdit.repaint()
         ret = verify.verify_node_typing()
         ret = verify.verify_node_typing()
@@ -198,6 +199,7 @@ class IMMainWindow(QMainWindow, Ui_MainWindow):
         else:
         else:
             self.plainTextEdit.appendPlainText("OK")
             self.plainTextEdit.appendPlainText("OK")
             self.plainTextEdit.repaint()
             self.plainTextEdit.repaint()
+        """
 
 
         self.plainTextEdit.appendPlainText("Verify: Checking attributes ...")
         self.plainTextEdit.appendPlainText("Verify: Checking attributes ...")
         self.plainTextEdit.repaint()
         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
         Should actually not be neccessary since instance modeling only allows types from
         example models.
         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
         # Check for every node in instance model if it has a valid type
         all_nodes = mv.all_instances(self._instance_model, "Node")
         all_nodes = mv.all_instances(self._instance_model, "Node")
         for node in all_nodes:
         for node in all_nodes:
             node_typ = commons.get_node_type(self._instance_model, node)
             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": False, "error": "Type {} from instance model not in example models".format(node_typ)}
 
 
         return {"OK":True, "error":None}
         return {"OK":True, "error":None}
@@ -84,14 +74,91 @@ class Verifier(object):
 
 
         return {"OK": True, "error": None}
         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):
     def verify_attributes(self):
         """
         """
         1. For every attribute key of a typed node in the instance model, there must be a corresponding
         1. For every attribute key of a typed node in the instance model, there must be a corresponding
         attribute key in some example model.
         attribute key in some example model.
         2. An attribute for a type is mandatory if it occurs in every 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}
         return {"OK": True, "error": None}
 
 
@@ -105,7 +172,6 @@ class Verifier(object):
         to connect two nodes).
         to connect two nodes).
         """
         """
 
 
-        # TODO: implement
 
 
         return {"OK": True, "error": None}
         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)
 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 author: Yentl Van Tendeloo
 Model name:   MvK Server
 Model name:   MvK Server