Implement a recursive validation api in the base Element class.
authorJosh Blum <josh@joshknows.com>
Sat, 5 Sep 2009 07:45:14 +0000 (00:45 -0700)
committerJosh Blum <josh@joshknows.com>
Sat, 5 Sep 2009 07:45:14 +0000 (00:45 -0700)
The rewrite and validate methods will invoke themselves on the child elements.
The error messages are now a super-list of element and child error messages.

As a side-effect, this cleans up code in base Block and Flowgraph class.

grc/base/Block.py
grc/base/Element.py
grc/base/FlowGraph.py

index fc501205fdb10091fd1fe5d420029daa81470f2c..cb21c3958a2f0e3da1fb32025ec747e32528ad1e 100644 (file)
@@ -132,28 +132,6 @@ class Block(Element):
                """
                self.get_param('_enabled').set_value(str(enabled))
 
-       def rewrite(self):
-               """
-               Rewrite critical structures.
-               Call rewrite on all sub elements.
-               """
-               Element.rewrite(self)
-               for elem in self.get_ports() + self.get_params(): elem.rewrite()
-
-       def validate(self):
-               """
-               Validate the block.
-               All ports and params must be valid.
-               All checks must evaluate to true.
-               Validate the params, ports, and the connections to this block.
-               """
-               Element.validate(self)
-               for c in self.get_params() + self.get_ports() + self.get_connections():
-                       c.validate()
-                       if not c.is_valid():
-                               for msg in c.get_error_messages():
-                                       self.add_error_message('>>> %s:\n\t%s'%(c, msg))
-
        def __str__(self): return 'Block - %s - %s(%s)'%(self.get_id(), self.get_name(), self.get_key())
 
        def get_id(self): return self.get_param('id').get_value()
@@ -163,6 +141,7 @@ class Block(Element):
        def get_category(self): return self._category
        def get_doc(self): return ''
        def get_ports(self): return self.get_sources() + self.get_sinks()
+       def get_children(self): return self.get_ports() + self.get_params()
        def get_block_wrapper_path(self): return self._block_wrapper_path
 
        ##############################################
index 43cee886c18f38d0c78b18767a6e6c0c33199fc7..e77e7ce0891447c4d3ee53d2fe16b1f6755242b0 100644 (file)
@@ -25,16 +25,54 @@ class Element(object):
        ##################################################
        # Element Validation API
        ##################################################
-       def validate(self): self._error_messages = list()
-       def is_valid(self): return not self.get_error_messages() or not self.get_enabled()
-       def add_error_message(self, msg): self._error_messages.append(msg)
-       def get_error_messages(self): return self._error_messages
+       def validate(self):
+               """
+               Validate this element and call validate on all children.
+               Call this base method before adding error messages in the subclass.
+               """
+               self._error_messages = list()
+               for child in self.get_children(): child.validate()
 
-       def rewrite(self): pass
+       def is_valid(self):
+               """
+               Is this element valid?
+               @return true when the element is enabled and has no error messages
+               """
+               return not self.get_error_messages() or not self.get_enabled()
+
+       def add_error_message(self, msg):
+               """
+               Add an error message to the list of errors.
+               @param msg the error message string
+               """
+               self._error_messages.append(msg)
+
+       def get_error_messages(self):
+               """
+               Get the list of error messages from this element and all of its children.
+               Cleverly indent the children error messages for printing purposes.
+               @return a list of error message strings
+               """
+               error_messages = list(self._error_messages) #make a copy
+               for child in self.get_children():
+                       for msg in child.get_error_messages():
+                               error_messages.append("%s:\n\t%s"%(child, msg.replace("\n", "\n\t")))
+               return error_messages
+
+       def rewrite(self):
+               """
+               Rewrite this element and call rewrite on all children.
+               Call this base method before rewriting the element.
+               """
+               for child in self.get_children(): child.rewrite()
 
        def get_enabled(self): return True
 
+       ##############################################
+       ## Tree-like API
+       ##############################################
        def get_parent(self): return self._parent
+       def get_children(self): return list()
 
        ##############################################
        ## Type testing methods
index b24f13b092ba2196a1a40c8ffe6de92e34df4eb7..ce370ca242036486d975c17676c9e0ab0a0cdfa8 100644 (file)
@@ -68,6 +68,7 @@ class FlowGraph(Element):
        def get_block(self, id): return filter(lambda b: b.get_id() == id, self.get_blocks())[0]
        def get_blocks(self): return filter(lambda e: e.is_block(), self.get_elements())
        def get_connections(self): return filter(lambda e: e.is_connection(), self.get_elements())
+       def get_children(self): return self.get_elements()
        def get_elements(self):
                """
                Get a list of all the elements.
@@ -144,26 +145,6 @@ class FlowGraph(Element):
                """
                raise NotImplementedError
 
-       def rewrite(self):
-               """
-               Rewrite critical structures.
-               Call rewrite on all sub elements.
-               """
-               Element.rewrite(self)
-               for elem in self.get_elements(): elem.rewrite()
-
-       def validate(self):
-               """
-               Validate the flow graph.
-               Validate only the blocks.
-               Connections will be validated within the blocks.
-               """
-               Element.validate(self)
-               for c in self.get_blocks():
-                       c.validate()
-                       if not c.is_valid():
-                               self.add_error_message('Element "%s" is not valid.'%c)
-
        ##############################################
        ## Import/Export Methods
        ##############################################