Removed dictionaries storing datatypes and pous defined in project and pou and datatype using tree from model
authorLaurent Bessard
Tue, 03 Sep 2013 23:32:53 +0200
changeset 1302 7856cd7767d6
parent 1301 fcca121a000f
child 1303 908a5803c2cc
Removed dictionaries storing datatypes and pous defined in project and pou and datatype using tree from model
PLCControler.py
plcopen/plcopen.py
--- a/PLCControler.py	Mon Sep 02 23:46:38 2013 +0200
+++ b/PLCControler.py	Tue Sep 03 23:32:53 2013 +0200
@@ -568,7 +568,7 @@
                         instances.append(var_path)
                     else:
                         pou = project.getpou(var_type)
-                        if pou is not None and project.ElementIsUsedBy(pou_type, var_type):
+                        if pou is not None:# and project.ElementIsUsedBy(pou_type, var_type):
                             instances.extend(
                                 self.RecursiveSearchPouInstances(
                                     project, pou_type, var_path, 
@@ -603,7 +603,7 @@
                             if pou_type == words[1]:
                                 instances.append(pou_path)
                             pou = project.getpou(pou_type)
-                            if pou is not None and project.ElementIsUsedBy(words[1], pou_type):
+                            if pou is not None:# and project.ElementIsUsedBy(words[1], pou_type):
                                 instances.extend(
                                     self.RecursiveSearchPouInstances(
                                         project, words[1], pou_path, 
@@ -733,23 +733,23 @@
     
     # Return if data type given by name is used by another data type or pou
     def DataTypeIsUsed(self, name, debug = False):
-        project = self.GetProject(debug)
-        if project is not None:
-            return project.ElementIsUsed(name)
+        #project = self.GetProject(debug)
+        #if project is not None:
+        #    return project.ElementIsUsed(name)
         return False
 
     # Return if pou given by name is used by another pou
     def PouIsUsed(self, name, debug = False):
-        project = self.GetProject(debug)
-        if project is not None:
-            return project.ElementIsUsed(name)
+        #project = self.GetProject(debug)
+        #if project is not None:
+        #    return project.ElementIsUsed(name)
         return False
 
     # Return if pou given by name is directly or undirectly used by the reference pou
     def PouIsUsedBy(self, name, reference, debug = False):
-        project = self.GetProject(debug)
-        if project is not None:
-            return project.ElementIsUsedBy(name, reference)
+        #project = self.GetProject(debug)
+        #if project is not None:
+        #    return project.ElementIsUsedBy(name, reference)
         return False
 
     def GenerateProgram(self, filepath=None):
@@ -837,7 +837,6 @@
             pou = self.Project.getpou(name)
             if pou is not None:
                 pou.setpouType(pou_type)
-                self.Project.RefreshCustomBlockTypes()
                 self.BufferProject()
                 
     def GetPouXml(self, pou_name):
@@ -980,7 +979,6 @@
             if datatype is not None:
                 datatype.setname(new_name)
                 self.Project.updateElementName(old_name, new_name)
-                self.Project.RefreshElementUsingTree()
                 self.BufferProject()
     
     # Change the name of a pou
@@ -991,8 +989,6 @@
             if pou is not None:
                 pou.setname(new_name)
                 self.Project.updateElementName(old_name, new_name)
-                self.Project.RefreshElementUsingTree()
-                self.Project.RefreshCustomBlockTypes()
                 self.BufferProject()
     
     # Change the name of a pou transition
@@ -1029,7 +1025,6 @@
                     for var in varlist.getvariable():
                         if var.getname() == old_name:
                             var.setname(new_name)
-                self.Project.RefreshCustomBlockTypes()
                 self.BufferProject()
         
     # Change the name of a configuration
@@ -1068,7 +1063,6 @@
             pou = project.getpou(name)
             if pou is not None:
                 pou.setdescription(description)
-                project.RefreshCustomBlockTypes()
                 self.BufferProject()
     
     # Return the type of the pou given by its name
@@ -1402,9 +1396,7 @@
                 if not en:
                     tree.insert(0, ("EN", "BOOL", ([], [])))
                 return tree, []
-            datatype = project.getdataType(typename)
-            if datatype is None:
-                datatype = self.GetConfNodeDataType(typename)
+            datatype = self.GetDataType(typename)
             if datatype is not None:
                 tree = []
                 basetype_content = datatype.baseType.getcontent()
@@ -1463,9 +1455,7 @@
                     pou.interface = PLCOpenParser.CreateElement("interface", "pou")
                 # Set Pou interface
                 pou.setvars([varlist for varlist_type, varlist in self.ExtractVarLists(vars)])
-                self.Project.RefreshElementUsingTree()
-                self.Project.RefreshCustomBlockTypes()
-    
+                
     # Replace the return type of the pou given by its name (only for functions)
     def SetPouInterfaceReturnType(self, name, return_type):
         if self.Project is not None:
@@ -1488,9 +1478,7 @@
                     derived_type = PLCOpenParser.CreateElement("derived", "dataType")
                     derived_type.setname(return_type)
                     return_type.setcontent(derived_type)
-                self.Project.RefreshElementUsingTree()
-                self.Project.RefreshCustomBlockTypes()
-    
+                
     def UpdateProjectUsedPous(self, old_name, new_name):
         if self.Project is not None:
             self.Project.updateElementName(old_name, new_name)
@@ -1529,7 +1517,8 @@
     def AddConfNodeTypesList(self, typeslist):
         self.ConfNodeTypes.extend(typeslist)
         addedcat = [{"name": _("%s POUs") % confnodetypes["name"],
-                     "list": confnodetypes["types"].GetCustomBlockTypes()}
+                     "list": [pou.getblockInfos()
+                              for pou in confnodetypes["types"].getpous()]}
                      for confnodetypes in typeslist]
         self.TotalTypes.extend(addedcat)
         for cat in addedcat:
@@ -1543,23 +1532,14 @@
         self.TotalTypesDict = StdBlckDct.copy()
         self.TotalTypes = StdBlckLst[:]
 
-    def GetConfNodeBlockTypes(self):
-        return [{"name": _("%s POUs") % confnodetypes["name"],
-                 "list": confnodetypes["types"].GetCustomBlockTypes()}
-                for confnodetypes in self.ConfNodeTypes]
-        
     def GetConfNodeDataTypes(self, exclude = None, only_locatables = False):
         return [{"name": _("%s Data Types") % confnodetypes["name"],
-                 "list": [datatype["name"] for datatype in confnodetypes["types"].GetCustomDataTypes(exclude, only_locatables)]}
+                 "list": [
+                    datatype.getname() 
+                    for datatype in confnodetypes["types"].getdataTypes()
+                    if not only_locatables or self.IsLocatableDataType(datatype, debug)]}
                 for confnodetypes in self.ConfNodeTypes]
     
-    def GetConfNodeDataType(self, typename):
-        for confnodetype in self.ConfNodeTypes:
-            datatype = confnodetype["types"].getdataType(typename)
-            if datatype is not None:
-                return datatype
-        return None
-    
     def GetVariableLocationTree(self):
         return []
 
@@ -1613,7 +1593,16 @@
             return result_blocktype
         project = self.GetProject(debug)
         if project is not None:
-            return project.GetCustomBlockType(typename, inputs)
+            blocktype = project.getpou(typename)
+            if blocktype is not None:
+                blocktype_infos = blocktype.getblockInfos()
+                if inputs in [None, "undefined"]:
+                    return blocktype_infos
+            
+                if inputs == tuple([var_type 
+                    for name, var_type, modifier in blocktype_infos["inputs"]]):
+                    return blocktype_infos
+        
         return None
 
     # Return Block types checking for recursion
@@ -1625,22 +1614,19 @@
         if project is not None:
             pou_type = None
             if words[0] in ["P","T","A"]:
-                blocktypes = []
                 name = words[1]
                 pou_type = self.GetPouType(name, debug)
-            if pou_type == "function":
-                for category in self.TotalTypes:
-                    cat = {"name" : category["name"], "list" : []}
-                    for block in category["list"]:
-                        if block["type"] == "function":
-                            cat["list"].append(block)
-                    if len(cat["list"]) > 0:
-                        blocktypes.append(cat)
-            else:
-                blocktypes = [category for category in self.TotalTypes]
+            filter = (["function"] 
+                      if pou_type == "function" or words[0] == "T" 
+                      else ["functionBlock", "function"])
+            blocktypes = [
+                {"name": category["name"],
+                 "list": [block for block in category["list"]
+                          if block["type"] in filter]}
+                for category in self.TotalTypes]
             blocktypes.append({"name" : USER_DEFINED_POUS, 
-                "list": project.GetCustomBlockTypes(name, 
-                    pou_type == "function" or words[0] == "T")})
+                "list": [pou.getblockInfos()
+                         for pou in project.getpous(name, filter)]})
             return blocktypes
         return self.TotalTypes
 
@@ -1653,11 +1639,11 @@
                     blocktypes.append(block["name"])
         project = self.GetProject(debug)
         if project is not None:
-            name = ""
             words = tagname.split("::")
-            if words[0] in ["P","T","A"]:
-                name = words[1]
-            blocktypes.extend(project.GetCustomFunctionBlockTypes(name))
+            blocktypes.extend([pou.getname()
+                for pou in project.getpous(
+                    words[1] if words[0] in ["P","T","A"] else None,
+                    ["functionBlock"])])
         return blocktypes
 
     # Return Block types checking for recursion
@@ -1669,7 +1655,9 @@
                     blocktypes.append(blocktype["name"])
         project = self.GetProject(debug)
         if project is not None:
-            blocktypes.extend(project.GetCustomBlockResource())
+            blocktypes.extend(
+                [pou.getblockInfos()
+                 for pou in project.getpous(filter=["program"])])
         return blocktypes
 
     # Return Data Types checking for recursion
@@ -1684,7 +1672,10 @@
             words = tagname.split("::")
             if words[0] in ["D"]:
                 name = words[1]
-            datatypes.extend([datatype["name"] for datatype in project.GetCustomDataTypes(name, only_locatables)])
+            datatypes.extend([
+                datatype.getname() 
+                for datatype in project.getdataTypes(name)
+                if not only_locatables or self.IsLocatableDataType(datatype, debug)])
         if confnodetypes:
             for category in self.GetConfNodeDataTypes(name, only_locatables):
                 datatypes.extend(category["list"])
@@ -1759,23 +1750,26 @@
             return not typename.startswith("ANY")
         return True
 
+    def IsLocatableDataType(self, datatype, debug = False):
+        basetype_content = datatype.baseType.getcontent()
+        basetype_content_type = basetype_content.getLocalTag()
+        if basetype_content_type in ["enum", "struct"]:
+            return False
+        elif basetype_content_type == "derived":
+            return self.IsLocatableType(basetype_content.getname())
+        elif basetype_content_name == "array":
+            array_base_type = basetype_content.baseType.getcontent()
+            if array_base_type.getLocalTag() == "derived":
+                return self.IsLocatableType(array_base_type.getname(), debug)
+        return True
+        
     def IsLocatableType(self, typename, debug = False):
-        if isinstance(typename, TupleType) or self.GetBlockType(type) is not None:
+        if isinstance(typename, TupleType) or self.GetBlockType(typename) is not None:
             return False
         
         datatype = self.GetDataType(typename, debug)
         if datatype is not None:
-            basetype_content = datatype.baseType.getcontent()
-            basetype_content_type = basetype_content.getLocalTag()
-            if basetype_content_type in ["enum", "struct"]:
-                return False
-            elif basetype_content_type == "derived":
-                return self.IsLocatableType(basetype_content.getname())
-            elif basetype_content_name == "array":
-                array_base_type = basetype_content.baseType.getcontent()
-                if array_base_type.getLocalTag() == "derived":
-                    return self.IsLocatableType(array_base_type.getname(), debug)
-        
+            return self.IsLocatableDataType(datatype)
         return True
     
     def IsEnumeratedType(self, typename, debug = False):
@@ -2088,7 +2082,6 @@
                 datatype.initialValue.setvalue(infos["initial"])
             else:
                 datatype.initialValue = None
-            self.Project.RefreshElementUsingTree()
             self.BufferProject()
     
 #-------------------------------------------------------------------------------
@@ -2174,7 +2167,6 @@
             element = self.GetEditedElement(tagname)
             if element is not None:
                 element.settext(text)
-                self.Project.RefreshElementUsingTree()
     
     # Return the edited element text
     def GetEditedElementText(self, tagname, debug = False):
@@ -2496,7 +2488,6 @@
                 block.setinstanceName(blockname)
                 self.AddEditedElementPouVar(tagname, blocktype, blockname)
             element.addinstance(block)
-            self.Project.RefreshElementUsingTree()
     
     def SetEditedElementBlockInfos(self, tagname, id, infos):
         element = self.GetEditedElement(tagname)
@@ -2563,7 +2554,6 @@
                         variable.addconnectionPointOut()
                         variable.connectionPointOut.setrelPositionXY(position.x, position.y)
             block.tostring()
-            self.Project.RefreshElementUsingTree()
         
     def AddEditedElementVariable(self, tagname, id, var_type):
         element = self.GetEditedElement(tagname)
@@ -3042,7 +3032,6 @@
             if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")):
                 self.RemoveEditedElementPouVar(tagname, instance.gettypeName(), instance.getinstanceName())
             element.removeinstance(id)
-            self.Project.RefreshElementUsingTree()
 
     def GetEditedResourceVariables(self, tagname, debug = False):
         varlist = []
@@ -3155,8 +3144,6 @@
         except Exception, e:
             return _("Project file syntax error:\n\n") + str(e)
         self.SetFilePath(filepath)
-        self.Project.RefreshElementUsingTree()
-        self.Project.RefreshCustomBlockTypes()
         
         ## To remove when project buffering ready
         self.ProjectBufferEnabled = False
--- a/plcopen/plcopen.py	Mon Sep 02 23:46:38 2013 +0200
+++ b/plcopen/plcopen.py	Tue Sep 03 23:32:53 2013 +0200
@@ -241,8 +241,6 @@
     
 cls = PLCOpenParser.GetElementClass("project")
 if cls:
-    cls.ElementUsingTree = {}
-    cls.CustomBlockTypes = OrderedDict()
     
     def setname(self, name):
         self.contentHeader.setname(name)
@@ -305,10 +303,10 @@
                 setattr(contentheader_obj, attr, value)
     setattr(cls, "setcontentHeader", setcontentHeader)
     
-    def gettypeElement(self, element_type, name=None):
-        filter = "[@name='%s']" % name if name is not None else ""
-        elements = self.xpath("ppx:types/ppx:%(element_type)ss/ppx:%(element_type)s%(filter)s" % locals(),
-                namespaces=PLCOpenParser.NSMAP)
+    def gettypeElement(self, element_type, name):
+        elements = self.xpath(
+            "ppx:types/ppx:%(element_type)ss/ppx:%(element_type)s[@name='%(name)s']" % locals(),
+            namespaces=PLCOpenParser.NSMAP)
         if name is None:
             return elements
         elif len(elements) == 1:
@@ -316,11 +314,14 @@
         return None
     setattr(cls, "gettypeElement", gettypeElement)
     
-    def getdataTypes(self):
-        return self.getdataType()
+    def getdataTypes(self, exclude=None):
+        return self.xpath(
+            "ppx:types/ppx:dataTypes/ppx:dataType%s" % 
+                ("[@name!='%s']" % exclude if exclude is not None else ""),
+            namespaces=PLCOpenParser.NSMAP)
     setattr(cls, "getdataTypes", getdataTypes)
     
-    def getdataType(self, name=None):
+    def getdataType(self, name):
         return self.gettypeElement("dataType", name)
     setattr(cls, "getdataType", getdataType)
     
@@ -336,31 +337,32 @@
     
     def removedataType(self, name):
         self.types.removedataTypeElement(name)
-        self.RefreshElementUsingTree()
     setattr(cls, "removedataType", removedataType)
     
-    def getpous(self):
-        return self.getpou()
+    def getpous(self, exclude=None, filter=None):
+        return self.xpath(
+            "ppx:types/ppx:pous/ppx:pou%s%s" % 
+                (("[@name!='%s']" % exclude) if exclude is not None else '',
+                 ("[%s]" % " or ".join(
+                    map(lambda x: "@pouType='%s'" % x, filter)))
+                 if filter is not None else ""),
+            namespaces=PLCOpenParser.NSMAP)
     setattr(cls, "getpous", getpous)
     
-    def getpou(self, name=None):
+    def getpou(self, name):
         return self.gettypeElement("pou", name)
     setattr(cls, "getpou", getpou)
     
     def appendpou(self, name, pou_type, body_type):
         self.types.appendpouElement(name, pou_type, body_type)
-        self.AddCustomBlockType(self.getpou(name))
     setattr(cls, "appendpou", appendpou)
         
     def insertpou(self, index, pou):
         self.types.insertpouElement(index, pou)
-        self.AddCustomBlockType(pou)
     setattr(cls, "insertpou", insertpou)
     
     def removepou(self, name):
         self.types.removepouElement(name)
-        self.RefreshCustomBlockTypes()
-        self.RefreshElementUsingTree()
     setattr(cls, "removepou", removepou)
 
     def getconfigurations(self):
@@ -458,132 +460,6 @@
             configuration.removeVariableByFilter(address_model)
     setattr(cls, "removeVariableByFilter", removeVariableByFilter)
 
-    # Update Block types with user-defined pou added
-    def RefreshCustomBlockTypes(self):
-        # Reset the tree of user-defined pou cross-use
-        self.CustomBlockTypes = OrderedDict()
-        for pou in self.getpous():
-            self.AddCustomBlockType(pou)
-    setattr(cls, "RefreshCustomBlockTypes", RefreshCustomBlockTypes)
-
-    def AddCustomBlockType(self, pou): 
-        pou_name = pou.getname()
-        pou_type = pou.getpouType()
-        block_infos = {"name" : pou_name, "type" : pou_type, "extensible" : False,
-                       "inputs" : [], "outputs" : [], "comment" : pou.getdescription(),
-                       "generate" : generate_block, "initialise" : initialise_block}
-        if pou.interface is not None:
-            return_type = pou.interface.getreturnType()
-            if return_type is not None:
-                var_type = return_type.getcontent()
-                var_type_name = var_type.getLocalTag()
-                if var_type_name == "derived":
-                    block_infos["outputs"].append(("OUT", var_type.getname(), "none"))
-                elif var_type_name in ["string", "wstring"]:
-                    block_infos["outputs"].append(("OUT", var_type_name.upper(), "none"))
-                else:
-                    block_infos["outputs"].append(("OUT", var_type_name, "none"))
-            for type, varlist in pou.getvars():
-                if type == "InOut":
-                    for var in varlist.getvariable():
-                        var_type = var.type.getcontent()
-                        var_type_name = var_type.getLocalTag()
-                        if var_type_name == "derived":
-                            block_infos["inputs"].append((var.getname(), var_type.getname(), "none"))
-                            block_infos["outputs"].append((var.getname(), var_type.getname(), "none"))
-                        elif var_type_name in ["string", "wstring"]:
-                            block_infos["inputs"].append((var.getname(), var_type_name.upper(), "none"))
-                            block_infos["outputs"].append((var.getname(), var_type_name.upper(), "none"))
-                        else:
-                            block_infos["inputs"].append((var.getname(), var_type_name, "none"))
-                            block_infos["outputs"].append((var.getname(), var_type_name, "none"))
-                elif type == "Input":
-                    for var in varlist.getvariable():
-                        var_type = var.type.getcontent()
-                        var_type_name = var_type.getLocalTag()
-                        if var_type_name == "derived":
-                            block_infos["inputs"].append((var.getname(), var_type.getname(), "none"))
-                        elif var_type_name in ["string", "wstring"]:
-                            block_infos["inputs"].append((var.getname(), var_type_name.upper(), "none"))
-                        else:
-                            block_infos["inputs"].append((var.getname(), var_type_name, "none"))
-                elif type == "Output":
-                    for var in varlist.getvariable():
-                        var_type = var.type.getcontent()
-                        var_type_name = var_type.getLocalTag()
-                        if var_type_name == "derived":
-                            block_infos["outputs"].append((var.getname(), var_type.getname(), "none"))
-                        elif var_type_name in ["string", "wstring"]:
-                            block_infos["outputs"].append((var.getname(), var_type_name.upper(), "none"))
-                        else:
-                            block_infos["outputs"].append((var.getname(), var_type_name, "none"))    
-        block_infos["usage"] = "\n (%s) => (%s)" % (", ".join(["%s:%s" % (input[1], input[0]) for input in block_infos["inputs"]]),
-                                                    ", ".join(["%s:%s" % (output[1], output[0]) for output in block_infos["outputs"]]))
-        self.CustomBlockTypes[pou_name]=block_infos
-    setattr(cls, "AddCustomBlockType", AddCustomBlockType)
-
-    def AddElementUsingTreeInstance(self, name, type_infos):
-        typename = type_infos.getname()
-        elements = self.ElementUsingTree.setdefault(typename, set())
-        elements.add(name)
-    setattr(cls, "AddElementUsingTreeInstance", AddElementUsingTreeInstance)
-    
-    def RefreshElementUsingTree(self):
-        # Reset the tree of user-defined element cross-use
-        self.ElementUsingTree = {}
-        
-        # Analyze each datatype
-        for datatype in self.getdataTypes():
-            name = datatype.getname()
-            basetype_content = datatype.baseType.getcontent()
-            basetype_content_name = basetype_content.getLocalTag()
-            if basetype_content_name == "derived":
-                self.AddElementUsingTreeInstance(name, basetype_content)
-            elif basetype_content_name in ["subrangeSigned", "subrangeUnsigned", "array"]:
-                base_type = basetype_content.baseType.getcontent()
-                if base_type.getLocalTag() == "derived":
-                    self.AddElementUsingTreeInstance(name, base_type)
-            elif basetype_content_name == "struct":
-                for element in basetype_content.getvariable():
-                    type_content = element.type.getcontent()
-                    if type_content.getLocalTag() == "derived":
-                        self.AddElementUsingTreeInstance(name, type_content)
-            
-        # Analyze each pou
-        for pou in self.getpous():
-            name = pou.getname()
-            if pou.interface is not None:
-                # Extract variables from every varLists
-                for varlist_type, varlist in pou.getvars():
-                    for var in varlist.getvariable():
-                        vartype_content = var.gettype().getcontent()
-                        if vartype_content.getLocalTag() == "derived":
-                            self.AddElementUsingTreeInstance(name, vartype_content)
-        
-    setattr(cls, "RefreshElementUsingTree", RefreshElementUsingTree)
-
-    # Return if pou given by name is used by another pou
-    def ElementIsUsed(self, name):
-        elements = self.ElementUsingTree.get(name, None)
-        return elements is not None
-    setattr(cls, "ElementIsUsed", ElementIsUsed)
-
-    # Return if pou given by name is directly or undirectly used by the reference pou
-    def ElementIsUsedBy(self, name, reference):
-        elements = self.ElementUsingTree.get(name, set())
-        # Test if pou is directly used by reference
-        if reference in elements:
-            return True
-        else:
-            # Test if pou is undirectly used by reference, by testing if pous
-            # that directly use pou is directly or undirectly used by reference
-            selffn = self.ElementIsUsedBy
-            for element in elements:
-                if selffn(element, reference):
-                    return True
-        return False
-    setattr(cls, "ElementIsUsedBy", ElementIsUsedBy)
-
     def GetEnumeratedDataTypeValues(self):
         return [
             value.getname() 
@@ -592,60 +468,6 @@
                 namespaces=PLCOpenParser.NSMAP)]
     setattr(cls, "GetEnumeratedDataTypeValues", GetEnumeratedDataTypeValues)
 
-    # Function that returns the block definition associated to the block type given
-    def GetCustomBlockType(self, typename, inputs = None):
-        customblocktype = self.CustomBlockTypes.get(typename,None)
-        if customblocktype is not None:
-            if inputs is not None and inputs != "undefined":
-                customblock_inputs = tuple([var_type for name, var_type, modifier in customblocktype["inputs"]])
-                if inputs == customblock_inputs:
-                    return customblocktype
-            else:
-                return customblocktype
-        return None
-    setattr(cls, "GetCustomBlockType", GetCustomBlockType)
-
-    # Return Block types checking for recursion
-    def GetCustomBlockTypes(self, exclude = None, onlyfunctions = False):
-        if exclude is not None:
-            return [customblocktype for name,customblocktype in self.CustomBlockTypes.iteritems()
-                if (customblocktype["type"] != "program"
-                    and name != exclude
-                    and not self.ElementIsUsedBy(exclude, name)
-                    and not (onlyfunctions and customblocktype["type"] != "function"))]
-        return [customblocktype for customblocktype in self.CustomBlockTypes.itervalues()
-            if (customblocktype["type"] != "program"
-                and not (onlyfunctions and customblocktype["type"] != "function"))]
-    setattr(cls, "GetCustomBlockTypes", GetCustomBlockTypes)
-
-    # Return Function Block types checking for recursion
-    def GetCustomFunctionBlockTypes(self, exclude = None):
-        if exclude is not None:
-            return [name for name,customblocktype in self.CustomBlockTypes.iteritems()
-                if (customblocktype["type"] == "functionBlock" 
-                    and name != exclude 
-                    and not self.ElementIsUsedBy(exclude, name))]
-        return [name for customblocktype in self.CustomBlockTypes.itervalues()
-            if customblocktype["type"] == "functionBlock"]
-    setattr(cls, "GetCustomFunctionBlockTypes", GetCustomFunctionBlockTypes)
-
-    # Return Block types checking for recursion
-    def GetCustomBlockResource(self):
-        return [customblocktype["name"] for customblocktype in self.CustomBlockTypes.itervalues()
-            if customblocktype["type"] == "program"]
-    setattr(cls, "GetCustomBlockResource", GetCustomBlockResource)
-
-    # Return Data Types checking for recursion
-    def GetCustomDataTypes(self, exclude = "", only_locatable = False):
-        customdatatypes = []
-        for customdatatype in self.getdataTypes():
-            if not only_locatable or self.IsLocatableType(customdatatype):
-                customdatatype_name = customdatatype.getname()
-                if customdatatype_name != exclude and not self.ElementIsUsedBy(exclude, customdatatype_name):
-                    customdatatypes.append({"name": customdatatype_name, "infos": customdatatype})
-        return customdatatypes
-    setattr(cls, "GetCustomDataTypes", GetCustomDataTypes)
-
     def Search(self, criteria, parent_infos=[]):
         result = self.types.Search(criteria, parent_infos)
         for configuration in self.instances.configurations.getconfiguration():
@@ -1168,9 +990,50 @@
         return search_result
     setattr(cls, "Search", Search)
 
+def _getvariableTypeinfos(variable_type):
+    type_content = variable_type.getcontent()
+    type_content_type = type_content.getLocalTag()
+    if type_content_type == "derived":
+        return type_content.getname()
+    return type_content_type.upper()
+    
 cls = PLCOpenParser.GetElementClass("pou", "pous")
 if cls:
     
+    def getblockInfos(self): 
+        block_infos = {
+            "name" : self.getname(), 
+            "type" : self.getpouType(), 
+            "extensible" : False,
+            "inputs" : [], 
+            "outputs" : [], 
+            "comment" : self.getdescription(),
+            "generate" : generate_block, 
+            "initialise" : initialise_block}
+        if self.interface is not None:
+            return_type = self.interface.getreturnType()
+            if return_type is not None:
+                block_infos["outputs"].append(
+                    ("OUT", _getvariableTypeinfos(return_type), "none"))
+            for var in self.xpath(
+                "ppx:interface/*[self::ppx:inputVars or self::ppx:inOutVars]/ppx:variable",
+                namespaces=PLCOpenParser.NSMAP):
+                block_infos["inputs"].append(
+                    (var.getname(), _getvariableTypeinfos(var.type), "none"))
+            for var in self.xpath(
+                "ppx:interface/*[self::ppx:outputVars or self::ppx:inOutVars]/ppx:variable",
+                namespaces=PLCOpenParser.NSMAP):
+                block_infos["outputs"].append(
+                    (var.getname(), _getvariableTypeinfos(var.type), "none"))
+            
+        block_infos["usage"] = ("\n (%s) => (%s)" % 
+            (", ".join(["%s:%s" % (input[1], input[0]) 
+                        for input in block_infos["inputs"]]),
+             ", ".join(["%s:%s" % (output[1], output[0]) 
+                        for output in block_infos["outputs"]])))
+        return block_infos
+    setattr(cls, "getblockInfos", getblockInfos)
+    
     def setdescription(self, description):
         doc = self.getdocumentation()
         if doc is None:
@@ -2333,7 +2196,7 @@
     def getBoundingBox(self):
         bbox = _getBoundingBoxSingle(self)
         condition_connection = self.getconditionConnection()
-        if condition_connection:
+        if condition_connection is not None:
             bbox.union(_getConnectionsBoundingBox(condition_connection))
         return bbox
     setattr(cls, "getBoundingBox", getBoundingBox)