plcopen/plcopen.py
changeset 814 5743cbdff669
child 824 be669f4c51c4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plcopen/plcopen.py	Fri Sep 07 16:45:55 2012 +0200
@@ -0,0 +1,2843 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+#This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
+#based on the plcopen standard. 
+#
+#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
+#
+#See COPYING file for copyrights details.
+#
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU General Public
+#License as published by the Free Software Foundation; either
+#version 2.1 of the License, or (at your option) any later version.
+#
+#This library is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#General Public License for more details.
+#
+#You should have received a copy of the GNU General Public
+#License along with this library; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+from xmlclass import *
+from structures import *
+from types import *
+import os, re
+
+"""
+Dictionary that makes the relation between var names in plcopen and displayed values
+"""
+VarTypes = {"Local" : "localVars", "Temp" : "tempVars", "Input" : "inputVars",
+            "Output" : "outputVars", "InOut" : "inOutVars", "External" : "externalVars",
+            "Global" : "globalVars", "Access" : "accessVars"}
+
+searchResultVarTypes = {
+    "inputVars": "var_input",
+    "outputVars": "var_output",
+    "inOutVars": "var_inout"
+}
+
+"""
+Define in which order var types must be displayed
+"""
+VarOrder = ["Local","Temp","Input","Output","InOut","External","Global","Access"]
+
+"""
+Define which action qualifier must be associated with a duration 
+"""
+QualifierList = {"N" : False, "R" : False, "S" : False, "L" : True, "D" : True, 
+    "P" : False, "P0" : False, "P1" : False, "SD" : True, "DS" : True, "SL" : True}
+
+
+FILTER_ADDRESS_MODEL = "(%%[IQM](?:[XBWDL])?)(%s)((?:\.[0-9]+)*)" 
+
+def update_address(address, address_model, new_leading):
+    result = address_model.match(address)
+    if result is None:
+        return address
+    groups = result.groups()
+    return groups[0] + new_leading + groups[2]
+
+def _init_and_compare(function, v1, v2):
+    if v1 is None:
+        return v2
+    if v2 is not None:
+        return function(v1, v2)
+    return v1
+
+"""
+Helper class for bounding_box calculation 
+"""
+class rect:
+    
+    def __init__(self, x=None, y=None, width=None, height=None):
+        self.x_min = x
+        self.x_max = None
+        self.y_min = y
+        self.y_max = None
+        if width is not None and x is not None:
+            self.x_max = x + width
+        if height is not None and y is not None:
+            self.y_max = y + height
+    
+    def update(self, x, y):
+        self.x_min = _init_and_compare(min, self.x_min, x)
+        self.x_max = _init_and_compare(max, self.x_max, x)
+        self.y_min = _init_and_compare(min, self.y_min, y)
+        self.y_max = _init_and_compare(max, self.y_max, y)
+        
+    def union(self, rect):
+        self.x_min = _init_and_compare(min, self.x_min, rect.x_min)
+        self.x_max = _init_and_compare(max, self.x_max, rect.x_max)
+        self.y_min = _init_and_compare(min, self.y_min, rect.y_min)
+        self.y_max = _init_and_compare(max, self.y_max, rect.y_max)
+    
+    def bounding_box(self):
+        width = height = None
+        if self.x_min is not None and self.x_max is not None:
+            width = self.x_max - self.x_min
+        if self.y_min is not None and self.y_max is not None:
+            height = self.y_max - self.y_min
+        return self.x_min, self.y_min, width, height
+
+def TextLenInRowColumn(text):
+    if text == "":
+        return (0, 0)
+    lines = text.split("\n")
+    return len(lines) - 1, len(lines[-1])
+
+def TestTextElement(text, criteria):
+    lines = text.splitlines()
+    if not criteria["case_sensitive"]:
+        text = text.upper()
+    test_result = []
+    result = criteria["pattern"].search(text)
+    while result is not None:
+        start = TextLenInRowColumn(text[:result.start()])
+        end = TextLenInRowColumn(text[:result.end() - 1])
+        test_result.append((start, end, "\n".join(lines[start[0]:end[0] + 1])))
+        result = criteria["pattern"].search(text, result.end())
+    return test_result
+
+PLCOpenClasses = GenerateClassesFromXSD(os.path.join(os.path.split(__file__)[0], "tc6_xml_v201.xsd"))
+
+ElementNameToClass = {}
+
+cls = PLCOpenClasses.get("formattedText", None)
+if cls:
+    def updateElementName(self, old_name, new_name):
+        text = self.text.decode("utf-8")
+        index = text.find(old_name)
+        while index != -1:
+            if index > 0 and (text[index - 1].isalnum() or text[index - 1] == "_"):
+                index = text.find(old_name, index + len(old_name))
+            elif index < len(text) - len(old_name) and (text[index + len(old_name)].isalnum() or text[index + len(old_name)] == "_"):
+                index = text.find(old_name, index + len(old_name))
+            else:
+                text = text[:index] + new_name + text[index + len(old_name):]
+                index = text.find(old_name, index + len(new_name))
+        self.text = text.encode("utf-8")
+    setattr(cls, "updateElementName", updateElementName)
+    
+    def updateElementAddress(self, address_model, new_leading):
+        text = self.text.decode("utf-8")
+        startpos = 0
+        result = address_model.search(text, startpos)
+        while result is not None:
+            groups = result.groups()
+            new_address = groups[0] + new_leading + groups[2]
+            text = text[:result.start()] + new_address + text[result.end():]
+            startpos = result.start() + len(new_address)
+            result = address_model.search(self.text, startpos)
+        self.text = text.encode("utf-8")
+    setattr(cls, "updateElementAddress", updateElementAddress)
+    
+    def Search(self, criteria, parent_infos):
+        return [(tuple(parent_infos),) + result for result in TestTextElement(self.gettext(), criteria)]
+    setattr(cls, "Search", Search)
+    
+cls = PLCOpenClasses.get("project", None)
+if cls:
+    cls.singleLineAttributes = False
+    cls.EnumeratedDataTypeValues = {}
+    cls.CustomDataTypeRange = {}
+    cls.CustomTypeHierarchy = {}
+    cls.ElementUsingTree = {}
+    cls.CustomBlockTypes = []
+    
+    def setname(self, name):
+        self.contentHeader.setname(name)
+    setattr(cls, "setname", setname)
+        
+    def getname(self):
+        return self.contentHeader.getname()
+    setattr(cls, "getname", getname)
+    
+    def getfileHeader(self):
+        fileheader = {}
+        for name, value in [("companyName", self.fileHeader.getcompanyName()),
+                            ("companyURL", self.fileHeader.getcompanyURL()),
+                            ("productName", self.fileHeader.getproductName()),
+                            ("productVersion", self.fileHeader.getproductVersion()),
+                            ("productRelease", self.fileHeader.getproductRelease()),
+                            ("creationDateTime", self.fileHeader.getcreationDateTime()),
+                            ("contentDescription", self.fileHeader.getcontentDescription())]:
+            if value is not None:
+                fileheader[name] = value
+            else:
+                fileheader[name] = ""
+        return fileheader
+    setattr(cls, "getfileHeader", getfileHeader)
+    
+    def setfileHeader(self, fileheader):
+        if fileheader.has_key("companyName"):
+            self.fileHeader.setcompanyName(fileheader["companyName"])
+        if fileheader.has_key("companyURL"):
+            self.fileHeader.setcompanyURL(fileheader["companyURL"])
+        if fileheader.has_key("productName"):
+            self.fileHeader.setproductName(fileheader["productName"])
+        if fileheader.has_key("productVersion"):
+            self.fileHeader.setproductVersion(fileheader["productVersion"])
+        if fileheader.has_key("productRelease"):
+            self.fileHeader.setproductRelease(fileheader["productRelease"])
+        if fileheader.has_key("creationDateTime"):
+            self.fileHeader.setcreationDateTime(fileheader["creationDateTime"])
+        if fileheader.has_key("contentDescription"):
+            self.fileHeader.setcontentDescription(fileheader["contentDescription"])
+    setattr(cls, "setfileHeader", setfileHeader)
+    
+    def getcontentHeader(self):
+        contentheader = {}
+        for name, value in [("projectName", self.contentHeader.getname()),
+                            ("projectVersion", self.contentHeader.getversion()),
+                            ("modificationDateTime", self.contentHeader.getmodificationDateTime()),
+                            ("organization", self.contentHeader.getorganization()),
+                            ("authorName", self.contentHeader.getauthor()),
+                            ("language", self.contentHeader.getlanguage())]:
+            if value is not None:
+                contentheader[name] = value
+            else:
+                contentheader[name] = ""
+        contentheader["pageSize"] = self.contentHeader.getpageSize()
+        contentheader["scaling"] = self.contentHeader.getscaling()
+        return contentheader
+    setattr(cls, "getcontentHeader", getcontentHeader)
+    
+    def setcontentHeader(self, contentheader):
+        if contentheader.has_key("projectName"):
+            self.contentHeader.setname(contentheader["projectName"])
+        if contentheader.has_key("projectVersion"):
+            self.contentHeader.setversion(contentheader["projectVersion"])
+        if contentheader.has_key("modificationDateTime"):
+            self.contentHeader.setmodificationDateTime(contentheader["modificationDateTime"])
+        if contentheader.has_key("organization"):
+            self.contentHeader.setorganization(contentheader["organization"])
+        if contentheader.has_key("authorName"):
+            self.contentHeader.setauthor(contentheader["authorName"])
+        if contentheader.has_key("language"):
+            self.contentHeader.setlanguage(contentheader["language"])
+        if contentheader.has_key("pageSize"):
+            self.contentHeader.setpageSize(*contentheader["pageSize"])
+        if contentheader.has_key("scaling"):
+            self.contentHeader.setscaling(contentheader["scaling"])
+    setattr(cls, "setcontentHeader", setcontentHeader)
+    
+    def getdataTypes(self):
+        return self.types.getdataTypeElements()
+    setattr(cls, "getdataTypes", getdataTypes)
+    
+    def getdataType(self, name):
+        return self.types.getdataTypeElement(name)
+    setattr(cls, "getdataType", getdataType)
+    
+    def appenddataType(self, name):
+        if self.CustomTypeHierarchy.has_key(name):
+            raise ValueError, "\"%s\" Data Type already exists !!!"%name
+        self.types.appenddataTypeElement(name)
+        self.AddCustomDataType(self.getdataType(name))
+    setattr(cls, "appenddataType", appenddataType)
+        
+    def insertdataType(self, index, datatype):
+        self.types.insertdataTypeElement(index, datatype)
+        self.AddCustomDataType(datatype)
+    setattr(cls, "insertdataType", insertdataType)
+    
+    def removedataType(self, name):
+        self.types.removedataTypeElement(name)
+        self.RefreshDataTypeHierarchy()
+        self.RefreshElementUsingTree()
+    setattr(cls, "removedataType", removedataType)
+    
+    def getpous(self):
+        return self.types.getpouElements()
+    setattr(cls, "getpous", getpous)
+    
+    def getpou(self, name):
+        return self.types.getpouElement(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):
+        configurations = self.instances.configurations.getconfiguration()
+        if configurations:
+            return configurations
+        return []
+    setattr(cls, "getconfigurations", getconfigurations)
+
+    def getconfiguration(self, name):
+        for configuration in self.instances.configurations.getconfiguration():
+            if configuration.getname() == name:
+                return configuration
+        return None
+    setattr(cls, "getconfiguration", getconfiguration)
+
+    def addconfiguration(self, name):
+        for configuration in self.instances.configurations.getconfiguration():
+            if configuration.getname() == name:
+                raise ValueError, _("\"%s\" configuration already exists !!!")%name
+        new_configuration = PLCOpenClasses["configurations_configuration"]()
+        new_configuration.setname(name)
+        self.instances.configurations.appendconfiguration(new_configuration)
+    setattr(cls, "addconfiguration", addconfiguration)    
+
+    def removeconfiguration(self, name):
+        found = False
+        for idx, configuration in enumerate(self.instances.configurations.getconfiguration()):
+            if configuration.getname() == name:
+                self.instances.configurations.removeconfiguration(idx)
+                found = True
+                break
+        if not found:
+            raise ValueError, ("\"%s\" configuration doesn't exist !!!")%name
+    setattr(cls, "removeconfiguration", removeconfiguration)
+
+    def getconfigurationResource(self, config_name, name):
+        configuration = self.getconfiguration(config_name)
+        if configuration:
+            for resource in configuration.getresource():
+                if resource.getname() == name:
+                    return resource
+        return None
+    setattr(cls, "getconfigurationResource", getconfigurationResource)
+
+    def addconfigurationResource(self, config_name, name):
+        configuration = self.getconfiguration(config_name)
+        if configuration:
+            for resource in configuration.getresource():
+                if resource.getname() == name:
+                    raise ValueError, _("\"%s\" resource already exists in \"%s\" configuration !!!")%(name, config_name)
+            new_resource = PLCOpenClasses["configuration_resource"]()
+            new_resource.setname(name)
+            configuration.appendresource(new_resource)
+    setattr(cls, "addconfigurationResource", addconfigurationResource)
+
+    def removeconfigurationResource(self, config_name, name):
+        configuration = self.getconfiguration(config_name)
+        if configuration:
+            found = False
+            for idx, resource in enumerate(configuration.getresource()):
+                if resource.getname() == name:
+                    configuration.removeresource(idx)
+                    found = True
+                    break
+            if not found:
+                raise ValueError, _("\"%s\" resource doesn't exist in \"%s\" configuration !!!")%(name, config_name)
+    setattr(cls, "removeconfigurationResource", removeconfigurationResource)
+
+    def updateElementName(self, old_name, new_name):
+        for datatype in self.types.getdataTypeElements():
+            datatype.updateElementName(old_name, new_name)
+        for pou in self.types.getpouElements():
+            pou.updateElementName(old_name, new_name)
+        for configuration in self.instances.configurations.getconfiguration():
+            configuration.updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, old_leading, new_leading):
+        address_model = re.compile(FILTER_ADDRESS_MODEL % old_leading)
+        for pou in self.types.getpouElements():
+            pou.updateElementAddress(address_model, new_leading)
+        for configuration in self.instances.configurations.getconfiguration():
+            configuration.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def removeVariableByAddress(self, address):
+        for pou in self.types.getpouElements():
+            pou.removeVariableByAddress(address)
+        for configuration in self.instances.configurations.getconfiguration():
+            configuration.removeVariableByAddress(address)
+    setattr(cls, "removeVariableByAddress", removeVariableByAddress)
+
+    def removeVariableByFilter(self, leading):
+        address_model = re.compile(FILTER_ADDRESS_MODEL % leading)
+        for pou in self.types.getpouElements():
+            pou.removeVariableByFilter(address_model)
+        for configuration in self.instances.configurations.getconfiguration():
+            configuration.removeVariableByFilter(address_model)
+    setattr(cls, "removeVariableByFilter", removeVariableByFilter)
+
+    def RefreshDataTypeHierarchy(self):
+        self.EnumeratedDataTypeValues = {}
+        self.CustomDataTypeRange = {}
+        self.CustomTypeHierarchy = {}
+        for datatype in self.getdataTypes():
+            self.AddCustomDataType(datatype)
+    setattr(cls, "RefreshDataTypeHierarchy", RefreshDataTypeHierarchy)
+
+    def AddCustomDataType(self, datatype):
+        name = datatype.getname()
+        basetype_content = datatype.getbaseType().getcontent()
+        if basetype_content["value"] is None:
+            self.CustomTypeHierarchy[name] = basetype_content["name"]
+        elif basetype_content["name"] in ["string", "wstring"]:
+            self.CustomTypeHierarchy[name] = basetype_content["name"].upper()
+        elif basetype_content["name"] == "derived":
+            self.CustomTypeHierarchy[name] = basetype_content["value"].getname()
+        elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]:
+            range = (basetype_content["value"].range.getlower(), 
+                     basetype_content["value"].range.getupper())
+            self.CustomDataTypeRange[name] = range
+            base_type = basetype_content["value"].baseType.getcontent()
+            if base_type["value"] is None:
+                self.CustomTypeHierarchy[name] = base_type["name"]
+            else:
+                self.CustomTypeHierarchy[name] = base_type["value"].getname()
+        else:
+            if basetype_content["name"] == "enum":
+                values = []
+                for value in basetype_content["value"].values.getvalue():
+                    values.append(value.getname())
+                self.EnumeratedDataTypeValues[name] = values
+            self.CustomTypeHierarchy[name] = "ANY_DERIVED"
+    setattr(cls, "AddCustomDataType", AddCustomDataType)
+
+    # Update Block types with user-defined pou added
+    def RefreshCustomBlockTypes(self):
+        # Reset the tree of user-defined pou cross-use
+        self.CustomBlockTypes = []
+        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.getinterface():
+            return_type = pou.interface.getreturnType()
+            if return_type:
+                var_type = return_type.getcontent()
+                if var_type["name"] == "derived":
+                    block_infos["outputs"].append(("", var_type["value"].getname(), "none"))
+                elif var_type["name"] in ["string", "wstring"]:
+                    block_infos["outputs"].append(("", var_type["name"].upper(), "none"))
+                else:
+                    block_infos["outputs"].append(("", var_type["name"], "none"))
+            for type, varlist in pou.getvars():
+                if type == "InOut":
+                    for var in varlist.getvariable():
+                        var_type = var.type.getcontent()
+                        if var_type["name"] == "derived":
+                            block_infos["inputs"].append((var.getname(), var_type["value"].getname(), "none"))
+                            block_infos["outputs"].append((var.getname(), var_type["value"].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()
+                        if var_type["name"] == "derived":
+                            block_infos["inputs"].append((var.getname(), var_type["value"].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()
+                        if var_type["name"] == "derived":
+                            block_infos["outputs"].append((var.getname(), var_type["value"].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.append(block_infos)
+    setattr(cls, "AddCustomBlockType", AddCustomBlockType)
+
+    def RefreshElementUsingTree(self):
+        # Reset the tree of user-defined element cross-use
+        self.ElementUsingTree = {}
+        pous = self.getpous()
+        datatypes = self.getdataTypes()
+        # Reference all the user-defined elementu names and initialize the tree of 
+        # user-defined elemnt cross-use
+        elementnames = [datatype.getname() for datatype in datatypes] + \
+                       [pou.getname() for pou in pous]
+        for name in elementnames:
+            self.ElementUsingTree[name] = []
+        # Analyze each datatype
+        for datatype in datatypes:
+            name = datatype.getname()
+            basetype_content = datatype.baseType.getcontent()
+            if basetype_content["name"] == "derived":
+                typename = basetype_content["value"].getname()
+                if name in self.ElementUsingTree[typename]:
+                    self.ElementUsingTree[typename].append(name)
+            elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned", "array"]:
+                base_type = basetype_content["value"].baseType.getcontent()
+                if base_type["name"] == "derived":
+                    typename = base_type["value"].getname()
+                    if self.ElementUsingTree.has_key(typename) and name not in self.ElementUsingTree[typename]:
+                        self.ElementUsingTree[typename].append(name)
+            elif basetype_content["name"] == "struct":
+                for element in basetype_content["value"].getvariable():
+                    type_content = element.type.getcontent()
+                    if type_content["name"] == "derived":
+                        typename = type_content["value"].getname()
+                        if self.ElementUsingTree.has_key(typename) and name not in self.ElementUsingTree[typename]:
+                            self.ElementUsingTree[typename].append(name)
+        # Analyze each pou
+        for pou in pous:
+            name = pou.getname()
+            if pou.interface:
+                # Extract variables from every varLists
+                for type, varlist in pou.getvars():
+                    for var in varlist.getvariable():
+                        vartype_content = var.gettype().getcontent()
+                        if vartype_content["name"] == "derived":
+                            typename = vartype_content["value"].getname()
+                            if self.ElementUsingTree.has_key(typename) and name not in self.ElementUsingTree[typename]:
+                                self.ElementUsingTree[typename].append(name)
+    setattr(cls, "RefreshElementUsingTree", RefreshElementUsingTree)
+
+    def GetParentType(self, type):
+        if self.CustomTypeHierarchy.has_key(type):
+            return self.CustomTypeHierarchy[type]
+        elif TypeHierarchy.has_key(type):
+            return TypeHierarchy[type]
+        return None
+    setattr(cls, "GetParentType", GetParentType)
+
+    def GetBaseType(self, type):
+        parent_type = self.GetParentType(type)
+        if parent_type is not None:
+            if parent_type.startswith("ANY"):
+                return type
+            else:
+                return self.GetBaseType(parent_type)
+        return None
+    setattr(cls, "GetBaseType", GetBaseType)
+
+    def GetSubrangeBaseTypes(self, exclude):
+        derived = []
+        for type in self.CustomTypeHierarchy.keys():
+            for base_type in DataTypeRange.keys():
+                if self.IsOfType(type, base_type) and not self.IsOfType(type, exclude):
+                    derived.append(type)
+                    break
+        return derived
+    setattr(cls, "GetSubrangeBaseTypes", GetSubrangeBaseTypes)
+
+    """
+    returns true if the given data type is the same that "reference" meta-type or one of its types.
+    """
+    def IsOfType(self, type, reference):
+        if reference is None:
+            return True
+        elif type == reference:
+            return True
+        else:
+            parent_type = self.GetParentType(type)
+            if parent_type is not None:
+                return self.IsOfType(parent_type, reference)
+        return False
+    setattr(cls, "IsOfType", IsOfType)
+
+    # Return if pou given by name is used by another pou
+    def ElementIsUsed(self, name):
+        if self.ElementUsingTree.has_key(name):
+            return len(self.ElementUsingTree[name]) > 0
+        return False
+    setattr(cls, "ElementIsUsed", ElementIsUsed)
+
+    def DataTypeIsDerived(self, name):
+        return name in self.CustomTypeHierarchy.values()
+    setattr(cls, "DataTypeIsDerived", DataTypeIsDerived)
+
+    # Return if pou given by name is directly or undirectly used by the reference pou
+    def ElementIsUsedBy(self, name, reference):
+        if self.ElementUsingTree.has_key(name):
+            list = self.ElementUsingTree[name]
+            # Test if pou is directly used by reference
+            if reference in list:
+                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
+                used = False
+                for element in list:
+                    used |= self.ElementIsUsedBy(element, reference)
+                return used
+        return False
+    setattr(cls, "ElementIsUsedBy", ElementIsUsedBy)
+
+    def GetDataTypeRange(self, type):
+        if self.CustomDataTypeRange.has_key(type):
+            return self.CustomDataTypeRange[type]
+        elif DataTypeRange.has_key(type):
+            return DataTypeRange[type]
+        else:
+            parent_type = self.GetParentType(type)
+            if parent_type is not None:
+                return self.GetDataTypeRange(parent_type)
+        return None
+    setattr(cls, "GetDataTypeRange", GetDataTypeRange)
+
+    def GetEnumeratedDataTypeValues(self, type = None):
+        if type is None:
+            all_values = []
+            for values in self.EnumeratedDataTypeValues.values():
+                all_values.extend(values)
+            return all_values
+        elif self.EnumeratedDataTypeValues.has_key(type):
+            return self.EnumeratedDataTypeValues[type]
+        return []
+    setattr(cls, "GetEnumeratedDataTypeValues", GetEnumeratedDataTypeValues)
+
+    # Function that returns the block definition associated to the block type given
+    def GetCustomBlockType(self, type, inputs = None):
+        for customblocktype in self.CustomBlockTypes:
+            if inputs is not None and inputs != "undefined":
+                customblock_inputs = tuple([var_type for name, var_type, modifier in customblocktype["inputs"]])
+                same_inputs = inputs == customblock_inputs
+            else:
+                same_inputs = True
+            if customblocktype["name"] == type and same_inputs:
+                return customblocktype
+        return None
+    setattr(cls, "GetCustomBlockType", GetCustomBlockType)
+
+    # Return Block types checking for recursion
+    def GetCustomBlockTypes(self, exclude = "", onlyfunctions = False):
+        type = None
+        if exclude != "":
+            pou = self.getpou(exclude)
+            if pou is not None:
+                type = pou.getpouType()
+        customblocktypes = []
+        for customblocktype in self.CustomBlockTypes:
+            if customblocktype["type"] != "program" and customblocktype["name"] != exclude and not self.ElementIsUsedBy(exclude, customblocktype["name"]) and not (onlyfunctions and customblocktype["type"] != "function"):
+                customblocktypes.append(customblocktype)
+        return customblocktypes
+    setattr(cls, "GetCustomBlockTypes", GetCustomBlockTypes)
+
+    # Return Function Block types checking for recursion
+    def GetCustomFunctionBlockTypes(self, exclude = ""):
+        customblocktypes = []
+        for customblocktype in self.CustomBlockTypes:
+            if customblocktype["type"] == "functionBlock" and customblocktype["name"] != exclude and not self.ElementIsUsedBy(exclude, customblocktype["name"]):
+                customblocktypes.append(customblocktype["name"])
+        return customblocktypes
+    setattr(cls, "GetCustomFunctionBlockTypes", GetCustomFunctionBlockTypes)
+
+    # Return Block types checking for recursion
+    def GetCustomBlockResource(self):
+        customblocktypes = []
+        for customblocktype in self.CustomBlockTypes:
+            if customblocktype["type"] == "program":
+                customblocktypes.append(customblocktype["name"])
+        return customblocktypes
+    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)
+
+    # Return if Data Type can be used for located variables
+    def IsLocatableType(self, datatype):
+        basetype_content = datatype.baseType.getcontent()
+        if basetype_content["name"] in ["enum", "struct"]:
+            return False
+        elif basetype_content["name"] == "derived":
+            base_type = self.getdataType(basetype_content["value"].getname())
+            if base_type is not None:
+                return self.IsLocatableType(base_type)
+        elif basetype_content["name"] == "array":
+            array_base_type = basetype_content["value"].baseType.getcontent()
+            if array_base_type["value"] is not None and array_base_type["name"] not in ["string", "wstring"]:
+                base_type = self.getdataType(array_base_type["value"].getname())
+                if base_type is not None:
+                    return self.IsLocatableType(base_type)
+        return True
+    setattr(cls, "IsLocatableType", IsLocatableType)
+
+    def Search(self, criteria, parent_infos=[]):
+        result = self.types.Search(criteria, parent_infos)
+        for configuration in self.instances.configurations.getconfiguration():
+            result.extend(configuration.Search(criteria, parent_infos))
+        return result
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("project_fileHeader", None)
+if cls:
+    cls.singleLineAttributes = False
+
+cls = PLCOpenClasses.get("project_contentHeader", None)
+if cls:
+    cls.singleLineAttributes = False
+    
+    def setpageSize(self, width, height):
+        self.coordinateInfo.setpageSize(width, height)
+    setattr(cls, "setpageSize", setpageSize)
+    
+    def getpageSize(self):
+        return self.coordinateInfo.getpageSize()
+    setattr(cls, "getpageSize", getpageSize)
+
+    def setscaling(self, scaling):
+        for language, (x, y) in scaling.items():
+            self.coordinateInfo.setscaling(language, x, y)
+    setattr(cls, "setscaling", setscaling)
+    
+    def getscaling(self):
+        scaling = {}
+        scaling["FBD"] = self.coordinateInfo.getscaling("FBD")
+        scaling["LD"] = self.coordinateInfo.getscaling("LD")
+        scaling["SFC"] = self.coordinateInfo.getscaling("SFC")
+        return scaling
+    setattr(cls, "getscaling", getscaling)
+
+cls = PLCOpenClasses.get("contentHeader_coordinateInfo", None)
+if cls:
+    def setpageSize(self, width, height):
+        if width == 0 and height == 0:
+            self.deletepageSize()
+        else:
+            if self.pageSize is None:
+                self.addpageSize()
+            self.pageSize.setx(width)
+            self.pageSize.sety(height)
+    setattr(cls, "setpageSize", setpageSize)
+    
+    def getpageSize(self):
+        if self.pageSize is not None:
+            return self.pageSize.getx(), self.pageSize.gety()
+        return 0, 0
+    setattr(cls, "getpageSize", getpageSize)
+
+    def setscaling(self, language, x, y):
+        if language == "FBD":
+            self.fbd.scaling.setx(x)
+            self.fbd.scaling.sety(y)
+        elif language == "LD":
+            self.ld.scaling.setx(x)
+            self.ld.scaling.sety(y)
+        elif language == "SFC":
+            self.sfc.scaling.setx(x)
+            self.sfc.scaling.sety(y)
+    setattr(cls, "setscaling", setscaling)
+    
+    def getscaling(self, language):
+        if language == "FBD":
+            return self.fbd.scaling.getx(), self.fbd.scaling.gety()
+        elif language == "LD":
+            return self.ld.scaling.getx(), self.ld.scaling.gety()
+        elif language == "SFC":
+            return self.sfc.scaling.getx(), self.sfc.scaling.gety()
+        return 0, 0
+    setattr(cls, "getscaling", getscaling)
+
+def _Search(attributes, criteria, parent_infos):
+    search_result = []
+    for attr, value in attributes:
+        if value is not None:
+            search_result.extend([(tuple(parent_infos + [attr]),) + result for result in TestTextElement(value, criteria)])
+    return search_result
+
+def _updateConfigurationResourceElementName(self, old_name, new_name):
+    for varlist in self.getglobalVars():
+        for var in varlist.getvariable():
+            var_address = var.getaddress()
+            if var_address is not None:
+                if var_address == old_name:
+                    var.setaddress(new_name)
+                if var.getname() == old_name:
+                    var.setname(new_name)
+
+def _updateConfigurationResourceElementAddress(self, address_model, new_leading):
+    for varlist in self.getglobalVars():
+        for var in varlist.getvariable():
+            var_address = var.getaddress()
+            if var_address is not None:
+                var.setaddress(update_address(var_address, address_model, new_leading))
+
+def _removeConfigurationResourceVariableByAddress(self, address):
+    for varlist in self.getglobalVars():
+        variables = varlist.getvariable()
+        for i in xrange(len(variables)-1, -1, -1):
+            if variables[i].getaddress() == address:
+                variables.pop(i)
+
+def _removeConfigurationResourceVariableByFilter(self, address_model):
+    for varlist in self.getglobalVars():
+        variables = varlist.getvariable()
+        for i in xrange(len(variables)-1, -1, -1):
+            var_address = variables[i].getaddress()
+            if var_address is not None:
+                result = address_model.match(var_address)
+                if result is not None:
+                    variables.pop(i)
+
+def _SearchInConfigurationResource(self, criteria, parent_infos=[]):
+    search_result = _Search([("name", self.getname())], criteria, parent_infos)
+    var_number = 0
+    for varlist in self.getglobalVars():
+        variable_type = searchResultVarTypes.get("globalVars", "var_local")
+        variables = varlist.getvariable()
+        for modifier, has_modifier in [("constant", varlist.getconstant()),
+                                       ("retain", varlist.getretain()),
+                                       ("non_retain", varlist.getnonretain())]:
+            if has_modifier:
+                for result in TestTextElement(modifier, criteria):
+                    search_result.append((tuple(parent_infos + [variable_type, (var_number, var_number + len(variables)), modifier]),) + result)
+                break
+        for variable in variables:
+            search_result.extend(variable.Search(criteria, parent_infos + [variable_type, var_number]))
+            var_number += 1
+    return search_result
+
+cls = PLCOpenClasses.get("configurations_configuration", None)
+if cls:
+    def updateElementName(self, old_name, new_name):
+        _updateConfigurationResourceElementName(self, old_name, new_name)
+        for resource in self.getresource():
+            resource.updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        _updateConfigurationResourceElementAddress(self, address_model, new_leading)
+        for resource in self.getresource():
+            resource.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    setattr(cls, "removeVariableByAddress", _removeConfigurationResourceVariableByAddress)
+    setattr(cls, "removeVariableByFilter", _removeConfigurationResourceVariableByFilter)
+
+    def Search(self, criteria, parent_infos=[]):
+        search_result = []
+        parent_infos = parent_infos + ["C::%s" % self.getname()]
+        filter = criteria["filter"]
+        if filter == "all" or "configuration" in filter:
+            search_result = _SearchInConfigurationResource(self, criteria, parent_infos)
+            for resource in self.getresource():
+                search_result.extend(resource.Search(criteria, parent_infos))
+        return search_result
+    setattr(cls, "Search", Search)
+    
+cls = PLCOpenClasses.get("configuration_resource", None)
+if cls:
+    def updateElementName(self, old_name, new_name):
+        _updateConfigurationResourceElementName(self, old_name, new_name)
+        for instance in self.getpouInstance():
+            instance.updateElementName(old_name, new_name)
+        for task in self.gettask():
+            task.updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        _updateConfigurationResourceElementAddress(self, address_model, new_leading)
+        for task in self.gettask():
+            task.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    setattr(cls, "removeVariableByAddress", _removeConfigurationResourceVariableByAddress)
+    setattr(cls, "removeVariableByFilter", _removeConfigurationResourceVariableByFilter)
+
+    def Search(self, criteria, parent_infos=[]):
+        parent_infos = parent_infos[:-1] + ["R::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())]
+        search_result = _SearchInConfigurationResource(self, criteria, parent_infos)
+        task_number = 0
+        instance_number = 0
+        for task in self.gettask():
+            results = TestTextElement(task.getname(), criteria)
+            for result in results:
+                search_result.append((tuple(parent_infos + ["task", task_number, "name"]),) + result)
+            search_result.extend(task.Search(criteria, parent_infos + ["task", task_number]))
+            task_number += 1
+            for instance in task.getpouInstance():
+                search_result.extend(task.Search(criteria, parent_infos + ["instance", instance_number]))
+                for result in results:
+                    search_result.append((tuple(parent_infos + ["instance", instance_number, "task"]),) + result)
+                instance_number += 1
+        for instance in self.getpouInstance():
+            search_result.extend(instance.Search(criteria, parent_infos + ["instance", instance_number]))
+            instance_number += 1
+        return search_result
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("resource_task", None)
+if cls:
+    def compatibility(self, tree):
+        if tree.hasAttribute("interval"):
+            interval = GetAttributeValue(tree._attrs["interval"])
+            result = time_model.match(interval)
+            if result is not None:
+                values = result.groups()
+                time_values = [int(v) for v in values[:2]]
+                seconds = float(values[2])
+                time_values.extend([int(seconds), int((seconds % 1) * 1000000)])
+                text = "t#"
+                if time_values[0] != 0:
+                    text += "%dh"%time_values[0]
+                if time_values[1] != 0:
+                    text += "%dm"%time_values[1]
+                if time_values[2] != 0:
+                    text += "%ds"%time_values[2]
+                if time_values[3] != 0:
+                    if time_values[3] % 1000 != 0:
+                        text += "%.3fms"%(float(time_values[3]) / 1000)
+                    else:
+                        text += "%dms"%(time_values[3] / 1000)
+                NodeSetAttr(tree, "interval", text)
+    setattr(cls, "compatibility", compatibility)
+    
+    def updateElementName(self, old_name, new_name):
+        if self.single == old_name:
+            self.single = new_name
+        if self.interval == old_name:
+            self.interval = new_name
+        for instance in self.getpouInstance():
+            instance.updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        if self.single is not None:
+            self.single = update_address(self.single, address_model, new_leading)
+        if self.interval is not None:
+            self.interval = update_address(self.interval, address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def Search(self, criteria, parent_infos=[]):
+        return _Search([("single", self.getsingle()), 
+                        ("interval", self.getinterval()),
+                        ("priority", str(self.getpriority()))],
+                       criteria, parent_infos)
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("pouInstance", None)
+if cls:
+    def compatibility(self, tree):
+        if tree.hasAttribute("type"):
+            NodeRenameAttr(tree, "type", "typeName")
+    setattr(cls, "compatibility", compatibility)
+    
+    def updateElementName(self, old_name, new_name):
+        if self.typeName == old_name:
+            self.typeName = new_name
+    setattr(cls, "updateElementName", updateElementName)
+
+    def Search(self, criteria, parent_infos=[]):
+        return _Search([("name", self.getname()), 
+                        ("type", self.gettypeName())],
+                       criteria, parent_infos)
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("varListPlain_variable", None)
+if cls:
+    def gettypeAsText(self):
+        vartype_content = self.gettype().getcontent()
+        # Variable type is a user data type
+        if vartype_content["name"] == "derived":
+            return vartype_content["value"].getname()
+        # Variable type is a string type
+        elif vartype_content["name"] in ["string", "wstring"]:
+            return vartype_content["name"].upper()
+        # Variable type is an array
+        elif vartype_content["name"] == "array":
+            base_type = vartype_content["value"].baseType.getcontent()
+            # Array derived directly from a user defined type 
+            if base_type["name"] == "derived":
+                basetype_name = base_type["value"].getname()
+            # Array derived directly from a string type 
+            elif base_type["name"] in ["string", "wstring"]:
+                basetype_name = base_type["name"].upper()
+            # Array derived directly from an elementary type 
+            else:
+                basetype_name = base_type["name"]
+            return "ARRAY [%s] OF %s" % (",".join(map(lambda x : "%s..%s" % (x.getlower(), x.getupper()), vartype_content["value"].getdimension())), basetype_name)
+        # Variable type is an elementary type
+        return vartype_content["name"]
+    setattr(cls, "gettypeAsText", gettypeAsText)
+    
+    def Search(self, criteria, parent_infos=[]):
+        search_result = _Search([("name", self.getname()), 
+                                 ("type", self.gettypeAsText()),
+                                 ("location", self.getaddress())],
+                                criteria, parent_infos)
+        initial = self.getinitialValue()
+        if initial is not None:
+            search_result.extend(_Search([("initial value", initial.getvalue())], criteria, parent_infos))
+        doc = self.getdocumentation()
+        if doc is not None:
+            search_result.extend(doc.Search(criteria, parent_infos + ["documentation"]))
+        return search_result
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("project_types", None)
+if cls:
+    def getdataTypeElements(self):
+        return self.dataTypes.getdataType()
+    setattr(cls, "getdataTypeElements", getdataTypeElements)
+    
+    def getdataTypeElement(self, name):
+        elements = self.dataTypes.getdataType()
+        for element in elements:
+            if element.getname() == name:
+                return element
+        return None
+    setattr(cls, "getdataTypeElement", getdataTypeElement)
+
+    def appenddataTypeElement(self, name):
+        new_datatype = PLCOpenClasses["dataTypes_dataType"]()
+        new_datatype.setname(name)
+        new_datatype.baseType.setcontent({"name" : "BOOL", "value" : None})
+        self.dataTypes.appenddataType(new_datatype)
+    setattr(cls, "appenddataTypeElement", appenddataTypeElement)
+    
+    def insertdataTypeElement(self, index, dataType):
+        self.dataTypes.insertdataType(index, dataType)
+    setattr(cls, "insertdataTypeElement", insertdataTypeElement)
+    
+    def removedataTypeElement(self, name):
+        found = False
+        for idx, element in enumerate(self.dataTypes.getdataType()):
+            if element.getname() == name:
+                self.dataTypes.removedataType(idx)
+                found = True
+                break
+        if not found:
+            raise ValueError, _("\"%s\" Data Type doesn't exist !!!")%name
+    setattr(cls, "removedataTypeElement", removedataTypeElement)
+    
+    def getpouElements(self):
+        return self.pous.getpou()
+    setattr(cls, "getpouElements", getpouElements)
+    
+    def getpouElement(self, name):
+        elements = self.pous.getpou()
+        for element in elements:
+            if element.getname() == name:
+                return element
+        return None
+    setattr(cls, "getpouElement", getpouElement)
+
+    def appendpouElement(self, name, pou_type, body_type):
+        for element in self.pous.getpou():
+            if element.getname() == name:
+                raise ValueError, _("\"%s\" POU already exists !!!")%name
+        new_pou = PLCOpenClasses["pous_pou"]()
+        new_pou.setname(name)
+        new_pou.setpouType(pou_type)
+        new_pou.appendbody(PLCOpenClasses["body"]())
+        new_pou.setbodyType(body_type)
+        self.pous.appendpou(new_pou)
+    setattr(cls, "appendpouElement", appendpouElement)
+        
+    def insertpouElement(self, index, pou):
+        self.pous.insertpou(index, pou)
+    setattr(cls, "insertpouElement", insertpouElement)
+    
+    def removepouElement(self, name):
+        found = False
+        for idx, element in enumerate(self.pous.getpou()):
+            if element.getname() == name:
+                self.pous.removepou(idx)
+                found = True
+                break
+        if not found:
+            raise ValueError, _("\"%s\" POU doesn't exist !!!")%name
+    setattr(cls, "removepouElement", removepouElement)
+
+    def Search(self, criteria, parent_infos=[]):
+        search_result = []
+        filter = criteria["filter"]
+        for datatype in self.dataTypes.getdataType():
+            search_result.extend(datatype.Search(criteria, parent_infos))
+        for pou in self.pous.getpou():
+            search_result.extend(pou.Search(criteria, parent_infos))
+        return search_result
+    setattr(cls, "Search", Search)
+
+def _updateBaseTypeElementName(self, old_name, new_name):
+    self.baseType.updateElementName(old_name, new_name)
+
+cls = PLCOpenClasses.get("dataTypes_dataType", None)
+if cls:
+    setattr(cls, "updateElementName", _updateBaseTypeElementName)
+    
+    def Search(self, criteria, parent_infos=[]):
+        search_result = []
+        filter = criteria["filter"]
+        if filter == "all" or "datatype" in filter:
+            parent_infos = parent_infos + ["D::%s" % self.getname()]
+            search_result.extend(_Search([("name", self.getname())], criteria, parent_infos))
+            search_result.extend(self.baseType.Search(criteria, parent_infos))
+            if self.initialValue is not None:
+                search_result.extend(_Search([("initial", self.initialValue.getvalue())], criteria, parent_infos))
+        return search_result
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("dataType", None)
+if cls:
+    
+    def updateElementName(self, old_name, new_name):
+        if self.content["name"] in ["derived", "array", "subrangeSigned", "subrangeUnsigned"]:
+            self.content["value"].updateElementName(old_name, new_name)
+        elif self.content["name"] == "struct":
+            for element in self.content["value"].getvariable():
+                element_type = element.type.updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def Search(self, criteria, parent_infos=[]):
+        search_result = []
+        if self.content["name"] in ["derived", "array", "enum", "subrangeSigned", "subrangeUnsigned"]:
+            search_result.extend(self.content["value"].Search(criteria, parent_infos))
+        elif self.content["name"] == "struct":
+            for i, element in enumerate(self.content["value"].getvariable()):
+                search_result.extend(element.Search(criteria, parent_infos + ["struct", i]))
+        else:
+            basetype = self.content["name"]
+            if basetype in ["string", "wstring"]:
+                basetype = basetype.upper()
+            search_result.extend(_Search([("base", basetype)], criteria, parent_infos))
+        return search_result
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("derivedTypes_array", None)
+if cls:
+    setattr(cls, "updateElementName", _updateBaseTypeElementName)
+    
+    def Search(self, criteria, parent_infos=[]):
+        search_result = self.baseType.Search(criteria, parent_infos)
+        for i, dimension in enumerate(self.getdimension()):
+            search_result.extend(_Search([("lower", dimension.getlower()),
+                                          ("upper", dimension.getupper())],
+                                         criteria, parent_infos + ["range", i]))
+        return search_result
+    setattr(cls, "Search", Search)
+
+def _SearchInSubrange(self, criteria, parent_infos=[]):
+    search_result = self.baseType.Search(criteria, parent_infos)
+    search_result.extend(_Search([("lower", self.range.getlower()),
+                                  ("upper", self.range.getupper())],
+                                 criteria, parent_infos))
+    return search_result
+
+cls = PLCOpenClasses.get("derivedTypes_subrangeSigned", None)
+if cls:
+    setattr(cls, "updateElementName", _updateBaseTypeElementName)
+    setattr(cls, "Search", _SearchInSubrange)
+
+cls = PLCOpenClasses.get("derivedTypes_subrangeUnsigned", None)
+if cls:
+    setattr(cls, "updateElementName", _updateBaseTypeElementName)
+    setattr(cls, "Search", _SearchInSubrange)
+
+cls = PLCOpenClasses.get("derivedTypes_enum", None)
+if cls:
+    
+    def updateElementName(self, old_name, new_name):
+        pass
+    setattr(cls, "updateElementName", updateElementName)
+    
+    def Search(self, criteria, parent_infos=[]):
+        search_result = []
+        for i, value in enumerate(self.values.getvalue()):
+            for result in TestTextElement(value.getname(), criteria):
+                search_result.append((tuple(parent_infos + ["value", i]),) + result)
+        return search_result
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("pous_pou", None)
+if cls:
+    
+    def setdescription(self, description):
+        doc = self.getdocumentation()
+        if doc is None:
+            doc = PLCOpenClasses["formattedText"]()
+            self.setdocumentation(doc)
+        doc.settext(description)
+    setattr(cls, "setdescription", setdescription)
+    
+    def getdescription(self):
+        doc = self.getdocumentation()
+        if doc is not None:
+            return doc.gettext()
+        return ""
+    setattr(cls, "getdescription", getdescription)
+    
+    def setbodyType(self, type):
+        if len(self.body) > 0:
+            if type == "IL":
+                self.body[0].setcontent({"name" : "IL", "value" : PLCOpenClasses["formattedText"]()})
+            elif type == "ST":
+                self.body[0].setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
+            elif type == "LD":
+                self.body[0].setcontent({"name" : "LD", "value" : PLCOpenClasses["body_LD"]()})
+            elif type == "FBD":
+                self.body[0].setcontent({"name" : "FBD", "value" : PLCOpenClasses["body_FBD"]()})
+            elif type == "SFC":
+                self.body[0].setcontent({"name" : "SFC", "value" : PLCOpenClasses["body_SFC"]()})
+            else:
+                raise ValueError, "%s isn't a valid body type!"%type
+    setattr(cls, "setbodyType", setbodyType)
+    
+    def getbodyType(self):
+        if len(self.body) > 0:
+            return self.body[0].getcontent()["name"]
+    setattr(cls, "getbodyType", getbodyType)
+    
+    def resetexecutionOrder(self):
+        if len(self.body) > 0:
+            self.body[0].resetexecutionOrder()
+    setattr(cls, "resetexecutionOrder", resetexecutionOrder)
+    
+    def compileexecutionOrder(self):
+        if len(self.body) > 0:
+            self.body[0].compileexecutionOrder()
+    setattr(cls, "compileexecutionOrder", compileexecutionOrder)
+    
+    def setelementExecutionOrder(self, instance, new_executionOrder):
+        if len(self.body) > 0:
+            self.body[0].setelementExecutionOrder(instance, new_executionOrder)
+    setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
+    
+    def addinstance(self, name, instance):
+        if len(self.body) > 0:
+            self.body[0].appendcontentInstance(name, instance)
+    setattr(cls, "addinstance", addinstance)
+    
+    def getinstances(self):
+        if len(self.body) > 0:
+            return self.body[0].getcontentInstances()
+        return []
+    setattr(cls, "getinstances", getinstances)
+    
+    def getinstance(self, id):
+        if len(self.body) > 0:
+            return self.body[0].getcontentInstance(id)
+        return None
+    setattr(cls, "getinstance", getinstance)
+    
+    def getrandomInstance(self, exclude):
+        if len(self.body) > 0:
+            return self.body[0].getcontentRandomInstance(exclude)
+        return None
+    setattr(cls, "getrandomInstance", getrandomInstance)
+    
+    def getinstanceByName(self, name):
+        if len(self.body) > 0:
+            return self.body[0].getcontentInstanceByName(name)
+        return None
+    setattr(cls, "getinstanceByName", getinstanceByName)
+    
+    def removeinstance(self, id):
+        if len(self.body) > 0:
+            self.body[0].removecontentInstance(id)
+    setattr(cls, "removeinstance", removeinstance)
+    
+    def settext(self, text):
+        if len(self.body) > 0:
+            self.body[0].settext(text)
+    setattr(cls, "settext", settext)
+    
+    def gettext(self):
+        if len(self.body) > 0:
+            return self.body[0].gettext()
+        return ""
+    setattr(cls, "gettext", gettext)
+
+    def getvars(self):
+        vars = []
+        if self.interface is not None:
+            reverse_types = {}
+            for name, value in VarTypes.items():
+                reverse_types[value] = name
+            for varlist in self.interface.getcontent():
+                vars.append((reverse_types[varlist["name"]], varlist["value"]))
+        return vars
+    setattr(cls, "getvars", getvars)
+    
+    def setvars(self, vars):
+        if self.interface is None:
+            self.interface = PLCOpenClasses["pou_interface"]()
+        self.interface.setcontent([])
+        for vartype, varlist in vars:
+            self.interface.appendcontent({"name" : VarTypes[vartype], "value" : varlist})
+    setattr(cls, "setvars", setvars)
+    
+    def addpouLocalVar(self, type, name, location="", description=""):
+        self.addpouVar(type, name, location=location, description=description)
+    setattr(cls, "addpouLocalVar", addpouLocalVar)
+        
+    def addpouExternalVar(self, type, name):
+        self.addpouVar(type, name, "externalVars")
+    setattr(cls, "addpouExternalVar", addpouExternalVar)
+    
+    def addpouVar(self, type, name, var_class="localVars", location="", description=""):
+        if self.interface is None:
+            self.interface = PLCOpenClasses["pou_interface"]()
+        content = self.interface.getcontent()
+        if len(content) == 0 or content[-1]["name"] != var_class:
+            content.append({"name" : var_class, "value" : PLCOpenClasses["interface_%s" % var_class]()})
+        else:
+            varlist = content[-1]["value"]
+            variables = varlist.getvariable()
+            if varlist.getconstant() or varlist.getretain() or len(variables) > 0 and variables[0].getaddress():
+                content.append({"name" : var_class, "value" : PLCOpenClasses["interface_%s" % var_class]()})
+        var = PLCOpenClasses["varListPlain_variable"]()
+        var.setname(name)
+        var_type = PLCOpenClasses["dataType"]()
+        if type in [x for x,y in TypeHierarchy_list if not x.startswith("ANY")]:
+            if type == "STRING":
+                var_type.setcontent({"name" : "string", "value" : PLCOpenClasses["elementaryTypes_string"]()})
+            elif type == "WSTRING":
+                var_type.setcontent({"name" : "wstring", "value" : PLCOpenClasses["elementaryTypes_wstring"]()})
+            else:
+                var_type.setcontent({"name" : type, "value" : None})
+        else:
+            derived_type = PLCOpenClasses["derivedTypes_derived"]()
+            derived_type.setname(type)
+            var_type.setcontent({"name" : "derived", "value" : derived_type})
+        var.settype(var_type)
+        if location != "":
+            var.setaddress(location)
+        if description != "":
+            ft = PLCOpenClasses["formattedText"]()
+            ft.settext(description)
+            var.setdocumentation(ft)
+        
+        content[-1]["value"].appendvariable(var)
+    setattr(cls, "addpouVar", addpouVar)
+    
+    def changepouVar(self, old_type, old_name, new_type, new_name):
+        if self.interface is not None:
+            content = self.interface.getcontent()
+            for varlist in content:
+                variables = varlist["value"].getvariable()
+                for var in variables:
+                    if var.getname() == old_name:
+                        vartype_content = var.gettype().getcontent()
+                        if vartype_content["name"] == "derived" and vartype_content["value"].getname() == old_type:
+                            var.setname(new_name)
+                            vartype_content["value"].setname(new_type)
+                            return
+    setattr(cls, "changepouVar", changepouVar)
+    
+    def removepouVar(self, type, name):
+        if self.interface is not None:
+            content = self.interface.getcontent()
+            for varlist in content:
+                variables = varlist["value"].getvariable()
+                for var in variables:
+                    if var.getname() == name:
+                        vartype_content = var.gettype().getcontent()
+                        if vartype_content["name"] == "derived" and vartype_content["value"].getname() == type:
+                            variables.remove(var)
+                            break
+                if len(varlist["value"].getvariable()) == 0:
+                    content.remove(varlist)
+                    break
+    setattr(cls, "removepouVar", removepouVar)
+    
+    def hasblock(self, name):
+        if self.getbodyType() in ["FBD", "LD", "SFC"]:
+            for instance in self.getinstances():
+                if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
+                    return True
+            if self.transitions:
+                for transition in self.transitions.gettransition():
+                    result = transition.hasblock(name)
+                    if result:
+                        return result
+            if self.actions:
+                for action in self.actions.getaction():
+                    result = action.hasblock(name)
+                    if result:
+                        return result
+        return False
+    setattr(cls, "hasblock", hasblock)
+    
+    def addtransition(self, name, type):
+        if not self.transitions:
+            self.addtransitions()
+            self.transitions.settransition([])
+        transition = PLCOpenClasses["transitions_transition"]()
+        transition.setname(name)
+        transition.setbodyType(type)
+        if type == "ST":
+            transition.settext(":= ;")
+        elif type == "IL":
+            transition.settext("\tST\t%s"%name)
+        self.transitions.appendtransition(transition)
+    setattr(cls, "addtransition", addtransition)
+    
+    def gettransition(self, name):
+        if self.transitions:
+            for transition in self.transitions.gettransition():
+                if transition.getname() == name:
+                    return transition
+        return None
+    setattr(cls, "gettransition", gettransition)
+        
+    def gettransitionList(self):
+        if self.transitions:
+            return self.transitions.gettransition()
+        return []
+    setattr(cls, "gettransitionList", gettransitionList)
+    
+    def removetransition(self, name):
+        if self.transitions:
+            transitions = self.transitions.gettransition()
+            i = 0
+            removed = False
+            while i < len(transitions) and not removed:
+                if transitions[i].getname() == name:
+                    transitions.pop(i)
+                    removed = True
+                i += 1
+            if not removed:
+                raise ValueError, _("Transition with name %s doesn't exist!")%name
+    setattr(cls, "removetransition", removetransition)
+
+    def addaction(self, name, type):
+        if not self.actions:
+            self.addactions()
+            self.actions.setaction([])
+        action = PLCOpenClasses["actions_action"]()
+        action.setname(name)
+        action.setbodyType(type)
+        self.actions.appendaction(action)
+    setattr(cls, "addaction", addaction)
+    
+    def getaction(self, name):
+        if self.actions:
+            for action in self.actions.getaction():
+                if action.getname() == name:
+                    return action
+        return None
+    setattr(cls, "getaction", getaction)
+    
+    def getactionList(self):
+        if self.actions:
+            return self.actions.getaction()
+        return []
+    setattr(cls, "getactionList", getactionList)
+        
+    def removeaction(self, name):
+        if self.actions:
+            actions = self.actions.getaction()
+            i = 0
+            removed = False
+            while i < len(actions) and not removed:
+                if actions[i].getname() == name:
+                    actions.pop(i)
+                    removed = True
+                i += 1
+            if not removed:
+                raise ValueError, _("Action with name %s doesn't exist!")%name
+    setattr(cls, "removeaction", removeaction)
+
+    def updateElementName(self, old_name, new_name):
+        if self.interface:
+            for content in self.interface.getcontent():
+                for var in content["value"].getvariable():
+                    var_address = var.getaddress()
+                    if var_address is not None:
+                        if var_address == old_name:
+                            var.setaddress(new_name)
+                        if var.getname() == old_name:
+                            var.setname(new_name)
+                    var_type_content = var.gettype().getcontent()
+                    if var_type_content["name"] == "derived":
+                        if var_type_content["value"].getname() == old_name:
+                            var_type_content["value"].setname(new_name)
+        self.body[0].updateElementName(old_name, new_name)
+        for action in self.getactionList():
+            action.updateElementName(old_name, new_name)
+        for transition in self.gettransitionList():
+            transition.updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        if self.interface:
+            for content in self.interface.getcontent():
+                for var in content["value"].getvariable():
+                    var_address = var.getaddress()
+                    if var_address is not None:
+                        var.setaddress(update_address(var_address, address_model, new_leading))
+        self.body[0].updateElementAddress(address_model, new_leading)
+        for action in self.getactionList():
+            action.updateElementAddress(address_model, new_leading)
+        for transition in self.gettransitionList():
+            transition.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def removeVariableByAddress(self, address):
+        if self.interface:
+            for content in self.interface.getcontent():
+                variables = content["value"].getvariable()
+                for i in xrange(len(variables)-1, -1, -1):
+                    if variables[i].getaddress() == address:
+                        variables.pop(i)
+    setattr(cls, "removeVariableByAddress", removeVariableByAddress)
+
+    def removeVariableByFilter(self, address_model):
+        if self.interface:
+            for content in self.interface.getcontent():
+                variables = content["value"].getvariable()
+                for i in xrange(len(variables)-1, -1, -1):
+                    var_address = variables[i].getaddress()
+                    if var_address is not None:
+                        result = address_model.match(var_address)
+                        if result is not None:
+                            variables.pop(i)
+    setattr(cls, "removeVariableByFilter", removeVariableByFilter)
+    
+    def Search(self, criteria, parent_infos=[]):
+        search_result = []
+        filter = criteria["filter"]
+        if filter == "all" or self.getpouType() in filter:
+            parent_infos = parent_infos + ["P::%s" % self.getname()]
+            search_result.extend(_Search([("name", self.getname())], criteria, parent_infos))
+            if self.interface is not None:
+                var_number = 0
+                for content in self.interface.getcontent():
+                    variable_type = searchResultVarTypes.get(content["value"], "var_local")
+                    variables = content["value"].getvariable()
+                    for modifier, has_modifier in [("constant", content["value"].getconstant()),
+                                                   ("retain", content["value"].getretain()),
+                                                   ("non_retain", content["value"].getnonretain())]:
+                        if has_modifier:
+                            for result in TestTextElement(modifier, criteria):
+                                search_result.append((tuple(parent_infos + [variable_type, (var_number, var_number + len(variables)), modifier]),) + result)
+                            break
+                    for variable in variables:
+                        search_result.extend(variable.Search(criteria, parent_infos + [variable_type, var_number]))
+                        var_number += 1
+            if len(self.body) > 0:
+                search_result.extend(self.body[0].Search(criteria, parent_infos))
+            for action in self.getactionList():
+                search_result.extend(action.Search(criteria, parent_infos))
+            for transition in self.gettransitionList():
+                search_result.extend(transition.Search(criteria, parent_infos))
+        return search_result
+    setattr(cls, "Search", Search)
+
+def setbodyType(self, type):
+    if type == "IL":
+        self.body.setcontent({"name" : "IL", "value" : PLCOpenClasses["formattedText"]()})
+    elif type == "ST":
+        self.body.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
+    elif type == "LD":
+        self.body.setcontent({"name" : "LD", "value" : PLCOpenClasses["body_LD"]()})
+    elif type == "FBD":
+        self.body.setcontent({"name" : "FBD", "value" : PLCOpenClasses["body_FBD"]()})
+    elif type == "SFC":
+        self.body.setcontent({"name" : "SFC", "value" : PLCOpenClasses["body_SFC"]()})
+    else:
+        raise ValueError, "%s isn't a valid body type!"%type
+
+def getbodyType(self):
+    return self.body.getcontent()["name"]
+
+def resetexecutionOrder(self):
+    self.body.resetexecutionOrder()
+
+def compileexecutionOrder(self):
+    self.body.compileexecutionOrder()
+
+def setelementExecutionOrder(self, instance, new_executionOrder):
+    self.body.setelementExecutionOrder(instance, new_executionOrder)
+
+def addinstance(self, name, instance):
+    self.body.appendcontentInstance(name, instance)
+
+def getinstances(self):
+    return self.body.getcontentInstances()
+
+def getinstance(self, id):
+    return self.body.getcontentInstance(id)
+
+def getrandomInstance(self, exclude):
+    return self.body.getcontentRandomInstance(exclude)
+
+def getinstanceByName(self, name):
+    return self.body.getcontentInstanceByName(name)
+
+def removeinstance(self, id):
+    self.body.removecontentInstance(id)
+
+def settext(self, text):
+    self.body.settext(text)
+
+def gettext(self):
+    return self.body.gettext()
+
+cls = PLCOpenClasses.get("transitions_transition", None)
+if cls:
+    setattr(cls, "setbodyType", setbodyType)
+    setattr(cls, "getbodyType", getbodyType)
+    setattr(cls, "resetexecutionOrder", resetexecutionOrder)
+    setattr(cls, "compileexecutionOrder", compileexecutionOrder)
+    setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
+    setattr(cls, "addinstance", addinstance)
+    setattr(cls, "getinstances", getinstances)
+    setattr(cls, "getinstance", getinstance)
+    setattr(cls, "getrandomInstance", getrandomInstance)
+    setattr(cls, "getinstanceByName", getinstanceByName)
+    setattr(cls, "removeinstance", removeinstance)
+    setattr(cls, "settext", settext)
+    setattr(cls, "gettext", gettext)
+
+    def updateElementName(self, old_name, new_name):
+        self.body.updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        self.body.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def hasblock(self, name):
+        if self.getbodyType() in ["FBD", "LD", "SFC"]:
+            for instance in self.getinstances():
+                if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
+                    return True
+        return False
+    setattr(cls, "hasblock", hasblock)
+
+    def Search(self, criteria, parent_infos):
+        search_result = []
+        parent_infos = parent_infos[:-1] + ["T::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())]
+        for result in TestTextElement(self.getname(), criteria):
+            search_result.append((tuple(parent_infos + ["name"]),) + result)
+        search_result.extend(self.body.Search(criteria, parent_infos))
+        return search_result
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("actions_action", None)
+if cls:
+    setattr(cls, "setbodyType", setbodyType)
+    setattr(cls, "getbodyType", getbodyType)
+    setattr(cls, "resetexecutionOrder", resetexecutionOrder)
+    setattr(cls, "compileexecutionOrder", compileexecutionOrder)
+    setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
+    setattr(cls, "addinstance", addinstance)
+    setattr(cls, "getinstances", getinstances)
+    setattr(cls, "getinstance", getinstance)
+    setattr(cls, "getrandomInstance", getrandomInstance)
+    setattr(cls, "getinstanceByName", getinstanceByName)
+    setattr(cls, "removeinstance", removeinstance)
+    setattr(cls, "settext", settext)
+    setattr(cls, "gettext", gettext)
+
+    def updateElementName(self, old_name, new_name):
+        self.body.updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        self.body.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def hasblock(self, name):
+        if self.getbodyType() in ["FBD", "LD", "SFC"]:
+            for instance in self.getinstances():
+                if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
+                    return True
+        return False
+    setattr(cls, "hasblock", hasblock)
+
+    def Search(self, criteria, parent_infos):
+        search_result = []
+        parent_infos = parent_infos[:-1] + ["A::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())]
+        for result in TestTextElement(self.getname(), criteria):
+            search_result.append((tuple(parent_infos + ["name"]),) + result)
+        search_result.extend(self.body.Search(criteria, parent_infos))
+        return search_result
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("body", None)
+if cls:
+    cls.currentExecutionOrderId = 0
+    
+    def resetcurrentExecutionOrderId(self):
+        object.__setattr__(self, "currentExecutionOrderId", 0)
+    setattr(cls, "resetcurrentExecutionOrderId", resetcurrentExecutionOrderId)
+    
+    def getnewExecutionOrderId(self):
+        object.__setattr__(self, "currentExecutionOrderId", self.currentExecutionOrderId + 1)
+        return self.currentExecutionOrderId
+    setattr(cls, "getnewExecutionOrderId", getnewExecutionOrderId)
+    
+    def resetexecutionOrder(self):
+        if self.content["name"] == "FBD":
+            for element in self.content["value"].getcontent():
+                if not isinstance(element["value"], (PLCOpenClasses.get("commonObjects_comment", None), 
+                                                     PLCOpenClasses.get("commonObjects_connector", None), 
+                                                     PLCOpenClasses.get("commonObjects_continuation", None))):
+                    element["value"].setexecutionOrderId(0)
+        else:
+            raise TypeError, _("Can only generate execution order on FBD networks!")
+    setattr(cls, "resetexecutionOrder", resetexecutionOrder)
+    
+    def compileexecutionOrder(self):
+        if self.content["name"] == "FBD":
+            self.resetexecutionOrder()
+            self.resetcurrentExecutionOrderId()
+            for element in self.content["value"].getcontent():
+                if isinstance(element["value"], PLCOpenClasses.get("fbdObjects_outVariable", None)) and element["value"].getexecutionOrderId() == 0:
+                    connections = element["value"].connectionPointIn.getconnections()
+                    if connections and len(connections) == 1:
+                        self.compileelementExecutionOrder(connections[0])
+                    element["value"].setexecutionOrderId(self.getnewExecutionOrderId())
+        else:
+            raise TypeError, _("Can only generate execution order on FBD networks!")
+    setattr(cls, "compileexecutionOrder", compileexecutionOrder)
+    
+    def compileelementExecutionOrder(self, link):
+        if self.content["name"] == "FBD":
+            localid = link.getrefLocalId()
+            instance = self.getcontentInstance(localid)
+            if isinstance(instance, PLCOpenClasses.get("fbdObjects_block", None)) and instance.getexecutionOrderId() == 0:
+                for variable in instance.inputVariables.getvariable():
+                    connections = variable.connectionPointIn.getconnections()
+                    if connections and len(connections) == 1:
+                        self.compileelementExecutionOrder(connections[0])
+                instance.setexecutionOrderId(self.getnewExecutionOrderId())
+            elif isinstance(instance, PLCOpenClasses.get("commonObjects_continuation", None)) and instance.getexecutionOrderId() == 0:
+                name = instance.getname()
+                for tmp_instance in self.getcontentInstances():
+                    if isinstance(tmp_instance, PLCOpenClasses.get("commonObjects_connector", None)) and tmp_instance.getname() == name and tmp_instance.getexecutionOrderId() == 0:
+                        connections = tmp_instance.connectionPointIn.getconnections()
+                        if connections and len(connections) == 1:
+                            self.compileelementExecutionOrder(connections[0])
+        else:
+            raise TypeError, _("Can only generate execution order on FBD networks!")
+    setattr(cls, "compileelementExecutionOrder", compileelementExecutionOrder)
+    
+    def setelementExecutionOrder(self, instance, new_executionOrder):
+        if self.content["name"] == "FBD":
+            old_executionOrder = instance.getexecutionOrderId()
+            if old_executionOrder is not None and old_executionOrder != 0 and new_executionOrder != 0:
+                for element in self.content["value"].getcontent():
+                    if element["value"] != instance and not isinstance(element["value"], PLCOpenClasses.get("commonObjects_comment", None)):
+                        element_executionOrder = element["value"].getexecutionOrderId()
+                        if old_executionOrder <= element_executionOrder <= new_executionOrder:
+                            element["value"].setexecutionOrderId(element_executionOrder - 1)
+                        if new_executionOrder <= element_executionOrder <= old_executionOrder:
+                            element["value"].setexecutionOrderId(element_executionOrder + 1)
+            instance.setexecutionOrderId(new_executionOrder)
+        else:
+            raise TypeError, _("Can only generate execution order on FBD networks!")
+    setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
+    
+    def appendcontentInstance(self, name, instance):
+        if self.content["name"] in ["LD","FBD","SFC"]:
+            self.content["value"].appendcontent({"name" : name, "value" : instance})
+        else:
+            raise TypeError, _("%s body don't have instances!")%self.content["name"]
+    setattr(cls, "appendcontentInstance", appendcontentInstance)
+    
+    def getcontentInstances(self):
+        if self.content["name"] in ["LD","FBD","SFC"]:
+            instances = []
+            for element in self.content["value"].getcontent():
+                instances.append(element["value"])
+            return instances
+        else:
+            raise TypeError, _("%s body don't have instances!")%self.content["name"]
+    setattr(cls, "getcontentInstances", getcontentInstances)
+
+    def getcontentInstance(self, id):
+        if self.content["name"] in ["LD","FBD","SFC"]:
+            for element in self.content["value"].getcontent():
+                if element["value"].getlocalId() == id:
+                    return element["value"]
+            return None
+        else:
+            raise TypeError, _("%s body don't have instances!")%self.content["name"]
+    setattr(cls, "getcontentInstance", getcontentInstance)
+    
+    def getcontentRandomInstance(self, exclude):
+        if self.content["name"] in ["LD","FBD","SFC"]:
+            for element in self.content["value"].getcontent():
+                if element["value"].getlocalId() not in exclude:
+                    return element["value"]
+            return None
+        else:
+            raise TypeError, _("%s body don't have instances!")%self.content["name"]
+    setattr(cls, "getcontentRandomInstance", getcontentRandomInstance)
+    
+    def getcontentInstanceByName(self, name):
+        if self.content["name"] in ["LD","FBD","SFC"]:
+            for element in self.content["value"].getcontent():
+                if isinstance(element["value"], PLCOpenClasses.get("fbdObjects_block", None)) and element["value"].getinstanceName() == name:
+                    return element["value"]
+        else:
+            raise TypeError, _("%s body don't have instances!")%self.content["name"]
+    setattr(cls, "getcontentInstanceByName", getcontentInstanceByName)
+    
+    def removecontentInstance(self, id):
+        if self.content["name"] in ["LD","FBD","SFC"]:
+            i = 0
+            removed = False
+            elements = self.content["value"].getcontent()
+            while i < len(elements) and not removed:
+                if elements[i]["value"].getlocalId() == id:
+                    self.content["value"].removecontent(i)
+                    removed = True
+                i += 1
+            if not removed:
+                raise ValueError, _("Instance with id %d doesn't exist!")%id
+        else:
+            raise TypeError, "%s body don't have instances!"%self.content["name"]
+    setattr(cls, "removecontentInstance", removecontentInstance)
+    
+    def settext(self, text):
+        if self.content["name"] in ["IL","ST"]:
+            self.content["value"].settext(text)
+        else:
+            raise TypeError, _("%s body don't have text!")%self.content["name"]
+    setattr(cls, "settext", settext)
+
+    def gettext(self):
+        if self.content["name"] in ["IL","ST"]:
+            return self.content["value"].gettext()
+        else:
+            raise TypeError, _("%s body don't have text!")%self.content["name"]
+    setattr(cls, "gettext", gettext)
+    
+    def updateElementName(self, old_name, new_name):
+        if self.content["name"] in ["IL", "ST"]:
+            self.content["value"].updateElementName(old_name, new_name)
+        else:
+            for element in self.content["value"].getcontent():
+                element["value"].updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        if self.content["name"] in ["IL", "ST"]:
+            self.content["value"].updateElementAddress(address_model, new_leading)
+        else:
+            for element in self.content["value"].getcontent():
+                element["value"].updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def Search(self, criteria, parent_infos=[]):
+        if self.content["name"] in ["IL", "ST"]:
+            search_result = self.content["value"].Search(criteria, parent_infos + ["body", 0])
+        else:
+            search_result = []
+            for element in self.content["value"].getcontent():
+                search_result.extend(element["value"].Search(criteria, parent_infos))
+        return search_result
+    setattr(cls, "Search", Search)
+
+def getx(self):
+    return self.position.getx()
+
+def gety(self):
+    return self.position.gety()
+
+def setx(self, x):
+    self.position.setx(x)
+    
+def sety(self, y):
+    self.position.sety(y)
+
+def _getBoundingBox(self):
+    return rect(self.getx(), self.gety(), self.getwidth(), self.getheight())
+
+def _getConnectionsBoundingBox(connectionPointIn):
+    bbox = rect()
+    connections = connectionPointIn.getconnections()
+    if connections is not None:
+        for connection in connections:
+            for x, y in connection.getpoints():
+                bbox.update(x, y)
+    return bbox
+
+def _getBoundingBoxSingle(self):
+    bbox = _getBoundingBox(self)
+    if self.connectionPointIn is not None:
+        bbox.union(_getConnectionsBoundingBox(self.connectionPointIn))
+    return bbox
+
+def _getBoundingBoxMultiple(self):
+    bbox = _getBoundingBox(self)
+    for connectionPointIn in self.getconnectionPointIn():
+        bbox.union(_getConnectionsBoundingBox(connectionPointIn))
+    return bbox
+
+def _filterConnections(connectionPointIn, localId, connections):
+    in_connections = connectionPointIn.getconnections()
+    if in_connections is not None:
+        to_delete = []
+        for i, connection in enumerate(in_connections):
+            connected = connection.getrefLocalId()
+            if not connections.has_key((localId, connected)) and \
+               not connections.has_key((connected, localId)):
+                to_delete.append(i)
+        to_delete.reverse()
+        for i in to_delete:
+            connectionPointIn.removeconnection(i)
+
+def _filterConnectionsSingle(self, connections):
+    if self.connectionPointIn is not None:
+        _filterConnections(self.connectionPointIn, self.localId, connections)
+
+def _filterConnectionsMultiple(self, connections):
+    for connectionPointIn in self.getconnectionPointIn():
+        _filterConnections(connectionPointIn, self.localId, connections)
+
+def _getconnectionsdefinition(instance, connections_end):
+    id = instance.getlocalId()
+    return dict([((id, end), True) for end in connections_end])
+
+def _updateConnectionsId(connectionPointIn, translation):
+    connections_end = []
+    connections = connectionPointIn.getconnections()
+    if connections is not None:
+        for connection in connections:
+            refLocalId = connection.getrefLocalId()
+            new_reflocalId = translation.get(refLocalId, refLocalId)
+            connection.setrefLocalId(new_reflocalId)
+            connections_end.append(new_reflocalId)
+    return connections_end
+
+def _updateConnectionsIdSingle(self, translation):
+    connections_end = []
+    if self.connectionPointIn is not None:
+        connections_end = _updateConnectionsId(self.connectionPointIn, translation)
+    return _getconnectionsdefinition(self, connections_end)
+
+def _updateConnectionsIdMultiple(self, translation):
+    connections_end = []
+    for connectionPointIn in self.getconnectionPointIn():
+        connections_end.extend(_updateConnectionsId(connectionPointIn, translation))
+    return _getconnectionsdefinition(self, connections_end)
+
+def _translate(self, dx, dy):
+    self.setx(self.getx() + dx)
+    self.sety(self.gety() + dy)
+    
+def _translateConnections(connectionPointIn, dx, dy):
+    connections = connectionPointIn.getconnections()
+    if connections is not None:
+        for connection in connections:
+            for position in connection.getposition():
+                position.setx(position.getx() + dx)
+                position.sety(position.gety() + dy)
+
+def _translateSingle(self, dx, dy):
+    _translate(self, dx, dy)
+    if self.connectionPointIn is not None:
+        _translateConnections(self.connectionPointIn, dx, dy)
+
+def _translateMultiple(self, dx, dy):
+    _translate(self, dx, dy)
+    for connectionPointIn in self.getconnectionPointIn():
+        _translateConnections(connectionPointIn, dx, dy)
+
+def _updateElementName(self, old_name, new_name):
+    pass
+
+def _updateElementAddress(self, address_model, new_leading):
+    pass
+
+def _SearchInElement(self, criteria, parent_infos=[]):
+    return []
+
+_connectionsFunctions = {
+    "bbox": {"none": _getBoundingBox,
+             "single": _getBoundingBoxSingle,
+             "multiple": _getBoundingBoxMultiple},
+    "translate": {"none": _translate,
+               "single": _translateSingle,
+               "multiple": _translateMultiple},
+    "filter": {"none": lambda self, connections: None,
+               "single": _filterConnectionsSingle,
+               "multiple": _filterConnectionsMultiple},
+    "update": {"none": lambda self, translation: {},
+               "single": _updateConnectionsIdSingle,
+               "multiple": _updateConnectionsIdMultiple},
+}
+
+def _initElementClass(name, classname, connectionPointInType="none"):
+    ElementNameToClass[name] = classname
+    cls = PLCOpenClasses.get(classname, None)
+    if cls:
+        setattr(cls, "getx", getx)
+        setattr(cls, "gety", gety)
+        setattr(cls, "setx", setx)
+        setattr(cls, "sety", sety)
+        setattr(cls, "updateElementName", _updateElementName)
+        setattr(cls, "updateElementAddress", _updateElementAddress)
+        setattr(cls, "getBoundingBox", _connectionsFunctions["bbox"][connectionPointInType])
+        setattr(cls, "translate", _connectionsFunctions["translate"][connectionPointInType])
+        setattr(cls, "filterConnections", _connectionsFunctions["filter"][connectionPointInType])
+        setattr(cls, "updateConnectionsId", _connectionsFunctions["update"][connectionPointInType])
+        setattr(cls, "Search", _SearchInElement)
+    return cls
+
+def _getexecutionOrder(instance, specific_values):
+    executionOrder = instance.getexecutionOrderId()
+    if executionOrder is None:
+        executionOrder = 0
+    specific_values["executionOrder"] = executionOrder
+    
+def _getdefaultmodifiers(instance, infos):
+    infos["negated"] = instance.getnegated()
+    infos["edge"] = instance.getedge()
+
+def _getinputmodifiers(instance, infos):
+    infos["negated"] = instance.getnegatedIn()
+    infos["edge"] = instance.getedgeIn()
+
+def _getoutputmodifiers(instance, infos):
+    infos["negated"] = instance.getnegatedOut()
+    infos["edge"] = instance.getedgeOut()
+
+MODIFIERS_FUNCTIONS = {"default": _getdefaultmodifiers,
+                       "input": _getinputmodifiers,
+                       "output": _getoutputmodifiers}
+
+def _getconnectioninfos(instance, connection, links=False, modifiers=None, parameter=False):
+    infos = {"position": connection.getrelPositionXY()}
+    if parameter:
+        infos["name"] = instance.getformalParameter()
+    MODIFIERS_FUNCTIONS.get(modifiers, lambda x, y: None)(instance, infos)
+    if links:
+        infos["links"] = []
+        connections = connection.getconnections()
+        if connections is not None:
+            for link in connections:
+                dic = {"refLocalId": link.getrefLocalId(),
+                       "points": link.getpoints(),
+                       "formalParameter": link.getformalParameter()}
+                infos["links"].append(dic)
+    return infos
+
+def _getelementinfos(instance):
+    return {"id": instance.getlocalId(),
+            "x": instance.getx(),
+            "y": instance.gety(),
+            "height": instance.getheight(),
+            "width": instance.getwidth(),
+            "specific_values": {},
+            "inputs": [],
+            "outputs": []}
+
+def _getvariableinfosFunction(type, input, output):
+    def getvariableinfos(self):
+        infos = _getelementinfos(self)
+        infos["type"] = type
+        specific_values = infos["specific_values"]
+        specific_values["name"] = self.getexpression()
+        _getexecutionOrder(self, specific_values)
+        if input and output:
+            infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True, "input"))
+            infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut, False, "output"))
+        elif input:
+            infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True, "default"))
+        elif output:
+            infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut, False, "default"))
+        return infos
+    return getvariableinfos
+
+def _getconnectorinfosFunction(type):
+    def getvariableinfos(self):
+        infos = _getelementinfos(self)
+        infos["type"] = type
+        infos["specific_values"]["name"] = self.getname()
+        if type == "connector":
+            infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
+        elif type == "continuation":
+            infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
+        return infos
+    return getvariableinfos
+
+def _getpowerrailinfosFunction(type):
+    def getpowerrailinfos(self):
+        infos = _getelementinfos(self)
+        infos["type"] = type
+        if type == "rightPowerRail":
+            for connectionPointIn in self.getconnectionPointIn():
+                infos["inputs"].append(_getconnectioninfos(self, connectionPointIn, True))
+            infos["specific_values"]["connectors"] = len(infos["inputs"])
+        elif type == "leftPowerRail":
+            for connectionPointOut in self.getconnectionPointOut():
+                infos["outputs"].append(_getconnectioninfos(self, connectionPointOut))
+            infos["specific_values"]["connectors"] = len(infos["outputs"])
+        return infos
+    return getpowerrailinfos
+
+def _getldelementinfosFunction(type):
+    def getldelementinfos(self):
+        infos = _getelementinfos(self)
+        infos["type"] = type
+        specific_values = infos["specific_values"]
+        specific_values["name"] = self.getvariable()
+        _getexecutionOrder(self, specific_values)
+        specific_values["negated"] = self.getnegated()
+        specific_values["edge"] = self.getedge()
+        if type == "coil":
+            specific_values["storage"] = self.getstorage()
+        infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
+        infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
+        return infos
+    return getldelementinfos
+
+DIVERGENCE_TYPES = {(True, True): "simultaneousDivergence",
+                    (True, False): "selectionDivergence",
+                    (False, True): "simultaneousConvergence",
+                    (False, False): "selectionConvergence"}
+
+def _getdivergenceinfosFunction(divergence, simultaneous):
+    def getdivergenceinfos(self):
+        infos = _getelementinfos(self)
+        infos["type"] = DIVERGENCE_TYPES[(divergence, simultaneous)]
+        if divergence:
+            infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
+            for connectionPointOut in self.getconnectionPointOut():
+                infos["outputs"].append(_getconnectioninfos(self, connectionPointOut))
+            infos["specific_values"]["connectors"] = len(infos["outputs"])
+        else:
+            for connectionPointIn in self.getconnectionPointIn():
+                infos["inputs"].append(_getconnectioninfos(self, connectionPointIn, True))
+            infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
+            infos["specific_values"]["connectors"] = len(infos["inputs"])
+        return infos
+    return getdivergenceinfos
+
+cls = _initElementClass("comment", "commonObjects_comment")
+if cls:
+    def getinfos(self):
+        infos = _getelementinfos(self)
+        infos["type"] = "comment"
+        infos["specific_values"]["content"] = self.getcontentText()
+        return infos
+    setattr(cls, "getinfos", getinfos)
+    
+    def setcontentText(self, text):
+        self.content.settext(text)
+    setattr(cls, "setcontentText", setcontentText)
+        
+    def getcontentText(self):
+        return self.content.gettext()
+    setattr(cls, "getcontentText", getcontentText)
+    
+    def updateElementName(self, old_name, new_name):
+        self.content.updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        self.content.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def Search(self, criteria, parent_infos=[]):
+        return self.content.Search(criteria, parent_infos + ["comment", self.getlocalId(), "content"])
+    setattr(cls, "Search", Search)
+
+cls = _initElementClass("block", "fbdObjects_block")
+if cls:
+    def getBoundingBox(self):
+        bbox = _getBoundingBox(self)
+        for input in self.inputVariables.getvariable():
+            bbox.union(_getConnectionsBoundingBox(input.connectionPointIn))
+        return bbox
+    setattr(cls, "getBoundingBox", getBoundingBox)
+
+    def getinfos(self):
+        infos = _getelementinfos(self)
+        infos["type"] = self.gettypeName()
+        specific_values = infos["specific_values"]
+        specific_values["name"] = self.getinstanceName()
+        _getexecutionOrder(self, specific_values)
+        for variable in self.inputVariables.getvariable():
+            infos["inputs"].append(_getconnectioninfos(variable, variable.connectionPointIn, True, "default", True))
+        for variable in self.outputVariables.getvariable():
+            infos["outputs"].append(_getconnectioninfos(variable, variable.connectionPointOut, False, "default", True))
+        return infos
+    setattr(cls, "getinfos", getinfos)
+
+    def updateElementName(self, old_name, new_name):
+        if self.typeName == old_name:
+            self.typeName = new_name
+    setattr(cls, "updateElementName", updateElementName)
+
+    def filterConnections(self, connections):
+        for input in self.inputVariables.getvariable():
+            _filterConnections(input.connectionPointIn, self.localId, connections)
+    setattr(cls, "filterConnections", filterConnections)
+
+    def updateConnectionsId(self, translation):
+        connections_end = []
+        for input in self.inputVariables.getvariable():
+            connections_end.extend(_updateConnectionsId(input.connectionPointIn, translation))
+        return _getconnectionsdefinition(self, connections_end)
+    setattr(cls, "updateConnectionsId", updateConnectionsId)
+
+    def translate(self, dx, dy):
+        _translate(self, dx, dy)
+        for input in self.inputVariables.getvariable():
+            _translateConnections(input.connectionPointIn, dx, dy)
+    setattr(cls, "translate", translate)
+
+    def Search(self, criteria, parent_infos=[]):
+        parent_infos = parent_infos + ["block", self.getlocalId()]
+        search_result = _Search([("name", self.getinstanceName()),
+                                 ("type", self.gettypeName())],
+                                criteria, parent_infos)
+        for i, variable in enumerate(self.inputVariables.getvariable()):
+            for result in TestTextElement(variable.getformalParameter(), criteria):
+                search_result.append((tuple(parent_infos + ["input", i]),) + result)
+        for i, variable in enumerate(self.outputVariables.getvariable()):
+            for result in TestTextElement(variable.getformalParameter(), criteria):
+                search_result.append((tuple(parent_infos + ["output", i]),) + result)
+        return search_result
+    setattr(cls, "Search", Search)
+
+cls = _initElementClass("leftPowerRail", "ldObjects_leftPowerRail")
+if cls:
+    setattr(cls, "getinfos", _getpowerrailinfosFunction("leftPowerRail"))
+
+cls = _initElementClass("rightPowerRail", "ldObjects_rightPowerRail", "multiple")
+if cls:
+    setattr(cls, "getinfos", _getpowerrailinfosFunction("rightPowerRail"))
+
+cls = _initElementClass("contact", "ldObjects_contact", "single")
+if cls:
+    setattr(cls, "getinfos", _getldelementinfosFunction("contact"))
+    
+    def updateElementName(self, old_name, new_name):
+        if self.variable == old_name:
+            self.variable = new_name
+    setattr(cls, "updateElementName", updateElementName)
+    
+    def updateElementAddress(self, address_model, new_leading):
+        self.variable = update_address(self.variable, address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+    
+    def Search(self, criteria, parent_infos=[]):
+        return _Search([("reference", self.getvariable())], criteria, parent_infos + ["contact", self.getlocalId()])
+    setattr(cls, "Search", Search)
+
+cls = _initElementClass("coil", "ldObjects_coil", "single")
+if cls:
+    setattr(cls, "getinfos", _getldelementinfosFunction("coil"))
+    
+    def updateElementName(self, old_name, new_name):
+        if self.variable == old_name:
+            self.variable = new_name
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        self.variable = update_address(self.variable, address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def Search(self, criteria, parent_infos=[]):
+        return _Search([("reference", self.getvariable())], criteria, parent_infos + ["coil", self.getlocalId()])
+    setattr(cls, "Search", Search)
+
+cls = _initElementClass("step", "sfcObjects_step", "single")
+if cls:
+    def getinfos(self):
+        infos = _getelementinfos(self)
+        infos["type"] = "step"
+        specific_values = infos["specific_values"]
+        specific_values["name"] = self.getname()
+        specific_values["initial"] = self.getinitialStep()
+        if self.connectionPointIn:
+            infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
+        if self.connectionPointOut:
+            infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
+        if self.connectionPointOutAction:
+            specific_values["action"] = _getconnectioninfos(self, self.connectionPointOutAction)
+        return infos
+    setattr(cls, "getinfos", getinfos)
+
+    def Search(self, criteria, parent_infos=[]):
+        return _Search([("name", self.getname())], criteria, parent_infos + ["step", self.getlocalId()])
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("transition_condition", None)
+if cls:
+    def compatibility(self, tree):
+        connections = []
+        for child in tree.childNodes:
+            if child.nodeName == "connection":
+                connections.append(child)
+        if len(connections) > 0:
+            node = CreateNode("connectionPointIn")
+            relPosition = CreateNode("relPosition")
+            NodeSetAttr(relPosition, "x", "0")
+            NodeSetAttr(relPosition, "y", "0")
+            node.childNodes.append(relPosition)
+            node.childNodes.extend(connections)
+            tree.childNodes = [node]
+    setattr(cls, "compatibility", compatibility)
+
+cls = _initElementClass("transition", "sfcObjects_transition", "single")
+if cls:
+    def getinfos(self):
+        infos = _getelementinfos(self)
+        infos["type"] = "transition"
+        specific_values = infos["specific_values"]
+        priority = self.getpriority()
+        if priority is None:
+            priority = 0
+        specific_values["priority"] = priority
+        condition = self.getconditionContent()
+        specific_values["condition_type"] = condition["type"]
+        if specific_values["condition_type"] == "connection":
+            specific_values["connection"] = _getconnectioninfos(self, condition["value"], True)
+        else:
+            specific_values["condition"] = condition["value"]
+        infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
+        infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
+        return infos
+    setattr(cls, "getinfos", getinfos)
+
+    def setconditionContent(self, type, value):
+        if not self.condition:
+            self.addcondition()
+        if type == "reference":
+            condition = PLCOpenClasses["condition_reference"]()
+            condition.setname(value)
+        elif type == "inline":
+            condition = PLCOpenClasses["condition_inline"]()
+            condition.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
+            condition.settext(value)
+        elif type == "connection":
+            type = "connectionPointIn"
+            condition = PLCOpenClasses["connectionPointIn"]()
+        self.condition.setcontent({"name" : type, "value" : condition})
+    setattr(cls, "setconditionContent", setconditionContent)
+        
+    def getconditionContent(self):
+        if self.condition:
+            content = self.condition.getcontent()
+            values = {"type" : content["name"]}
+            if values["type"] == "reference":
+                values["value"] = content["value"].getname()
+            elif values["type"] == "inline":
+                values["value"] = content["value"].gettext()
+            elif values["type"] == "connectionPointIn":
+                values["type"] = "connection"
+                values["value"] = content["value"]
+            return values
+        return ""
+    setattr(cls, "getconditionContent", getconditionContent)
+
+    def updateElementName(self, old_name, new_name):
+        if self.condition:
+            content = self.condition.getcontent()
+            if content["name"] == "reference":
+                if content["value"].getname() == old_name:
+                    content["value"].setname(new_name)
+            elif content["name"] == "inline":
+                content["value"].updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        if self.condition:
+            content = self.condition.getcontent()
+            if content["name"] == "reference":
+                content["value"].setname(update_address(content["value"].getname(), address_model, new_leading))
+            elif content["name"] == "inline":
+                content["value"].updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def getconnections(self):
+        if self.condition:
+            content = self.condition.getcontent()
+            if content["name"] == "connectionPointIn":
+                return content["value"].getconnections()
+    setattr(cls, "getconnections", getconnections)
+    
+    def Search(self, criteria, parent_infos=[]):
+        parent_infos = parent_infos + ["transition", self.getlocalId()]
+        search_result = []
+        content = self.condition.getcontent()
+        if content["name"] == "reference":
+            search_result.extend(_Search([("reference", content["value"].getname())], criteria, parent_infos))
+        elif content["name"] == "inline":
+            search_result.extend(content["value"].Search(criteria, parent_infos + ["inline"]))
+        return search_result
+    setattr(cls, "Search", Search)
+    
+cls = _initElementClass("selectionDivergence", "sfcObjects_selectionDivergence", "single")
+if cls:
+    setattr(cls, "getinfos", _getdivergenceinfosFunction(True, False))
+
+cls = _initElementClass("selectionConvergence", "sfcObjects_selectionConvergence", "multiple")
+if cls:
+    setattr(cls, "getinfos", _getdivergenceinfosFunction(False, False))
+
+cls = _initElementClass("simultaneousDivergence", "sfcObjects_simultaneousDivergence", "single")
+if cls:
+    setattr(cls, "getinfos", _getdivergenceinfosFunction(True, True))
+
+cls = _initElementClass("simultaneousConvergence", "sfcObjects_simultaneousConvergence", "multiple")
+if cls:
+    setattr(cls, "getinfos", _getdivergenceinfosFunction(False, True))
+
+cls = _initElementClass("jumpStep", "sfcObjects_jumpStep", "single")
+if cls:
+    def getinfos(self):
+        infos = _getelementinfos(self)
+        infos["type"] = "jump"
+        infos["specific_values"]["target"] = self.gettargetName()
+        infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
+        return infos
+    setattr(cls, "getinfos", getinfos)
+
+    def Search(self, criteria, parent_infos):
+        return _Search([("target", self.gettargetName())], criteria, parent_infos + ["jump", self.getlocalId()])
+    setattr(cls, "Search", Search)
+
+cls = PLCOpenClasses.get("actionBlock_action", None)
+if cls:
+    def compatibility(self, tree):
+        relPosition = reduce(lambda x, y: x | (y.nodeName == "relPosition"), tree.childNodes, False)
+        if not tree.hasAttribute("localId"):
+            NodeSetAttr(tree, "localId", "0")
+        if not relPosition:
+            node = CreateNode("relPosition")
+            NodeSetAttr(node, "x", "0")
+            NodeSetAttr(node, "y", "0")
+            tree.childNodes.insert(0, node)
+    setattr(cls, "compatibility", compatibility)
+    
+    def setreferenceName(self, name):
+        if self.reference:
+            self.reference.setname(name)
+    setattr(cls, "setreferenceName", setreferenceName)
+    
+    def getreferenceName(self):
+        if self.reference:
+            return self.reference.getname()
+        return None
+    setattr(cls, "getreferenceName", getreferenceName)
+
+    def setinlineContent(self, content):
+        if self.inline:
+            self.inline.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
+            self.inline.settext(content)
+    setattr(cls, "setinlineContent", setinlineContent)
+    
+    def getinlineContent(self):
+        if self.inline:
+            return self.inline.gettext()
+        return None
+    setattr(cls, "getinlineContent", getinlineContent)
+
+    def updateElementName(self, old_name, new_name):
+        if self.reference and self.reference.getname() == old_name:
+            self.reference.setname(new_name)
+        if self.inline:
+            self.inline.updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        if self.reference:
+            self.reference.setname(update_address(self.reference.getname(), address_model, new_leading))
+        if self.inline:
+            self.inline.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def Search(self, criteria, parent_infos=[]):
+        qualifier = self.getqualifier()
+        if qualifier is None:
+            qualifier = "N"
+        return _Search([("inline", self.getinlineContent()),
+                        ("reference", self.getreferenceName()), 
+                        ("qualifier", qualifier),
+                        ("duration", self.getduration()),
+                        ("indicator", self.getindicator())],
+                       criteria, parent_infos)
+    setattr(cls, "Search", Search)
+
+cls = _initElementClass("actionBlock", "commonObjects_actionBlock", "single")
+if cls:
+    def compatibility(self, tree):
+        for child in tree.childNodes[:]:
+            if child.nodeName == "connectionPointOut":
+                tree.childNodes.remove(child)
+    setattr(cls, "compatibility", compatibility)
+    
+    def getinfos(self):
+        infos = _getelementinfos(self)
+        infos["type"] = "actionBlock"
+        infos["specific_values"]["actions"] = self.getactions()
+        infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
+        return infos
+    setattr(cls, "getinfos", getinfos)
+    
+    def setactions(self, actions):
+        self.action = []
+        for params in actions:
+            action = PLCOpenClasses["actionBlock_action"]()
+            action.setqualifier(params["qualifier"])
+            if params["type"] == "reference":
+                action.addreference()
+                action.setreferenceName(params["value"])
+            else:
+                action.addinline()
+                action.setinlineContent(params["value"])
+            if params.has_key("duration"):
+                action.setduration(params["duration"])
+            if params.has_key("indicator"):
+                action.setindicator(params["indicator"])
+            self.action.append(action)
+    setattr(cls, "setactions", setactions)
+
+    def getactions(self):
+        actions = []
+        for action in self.action:
+            params = {}
+            params["qualifier"] = action.getqualifier()
+            if params["qualifier"] is None:
+                params["qualifier"] = "N"
+            if action.getreference():
+                params["type"] = "reference"
+                params["value"] = action.getreferenceName()
+            elif action.getinline():
+                params["type"] = "inline"
+                params["value"] = action.getinlineContent()
+            duration = action.getduration()
+            if duration:
+                params["duration"] = duration
+            indicator = action.getindicator()
+            if indicator:
+                params["indicator"] = indicator
+            actions.append(params)
+        return actions
+    setattr(cls, "getactions", getactions)
+
+    def updateElementName(self, old_name, new_name):
+        for action in self.action:
+            action.updateElementName(old_name, new_name)
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        for action in self.action:
+            action.updateElementAddress(address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    def Search(self, criteria, parent_infos=[]):
+        parent_infos = parent_infos + ["action_block", self.getlocalId()]
+        search_result = []
+        for idx, action in enumerate(self.action):
+            search_result.extend(action.Search(criteria, parent_infos + ["action", idx]))
+        return search_result
+    setattr(cls, "Search", Search)
+
+def _SearchInIOVariable(self, criteria, parent_infos=[]):
+    return _Search([("expression", self.getexpression())], criteria, parent_infos + ["io_variable", self.getlocalId()])
+
+cls = _initElementClass("inVariable", "fbdObjects_inVariable")
+if cls:
+    setattr(cls, "getinfos", _getvariableinfosFunction("input", False, True))
+    
+    def updateElementName(self, old_name, new_name):
+        if self.expression == old_name:
+            self.expression = new_name
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        self.expression = update_address(self.expression, address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    setattr(cls, "Search", _SearchInIOVariable)
+
+cls = _initElementClass("outVariable", "fbdObjects_outVariable", "single")
+if cls:
+    setattr(cls, "getinfos", _getvariableinfosFunction("output", True, False))
+    
+    def updateElementName(self, old_name, new_name):
+        if self.expression == old_name:
+            self.expression = new_name
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        self.expression = update_address(self.expression, address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    setattr(cls, "Search", _SearchInIOVariable)
+
+cls = _initElementClass("inOutVariable", "fbdObjects_inOutVariable", "single")
+if cls:
+    setattr(cls, "getinfos", _getvariableinfosFunction("inout", True, True))
+    
+    def updateElementName(self, old_name, new_name):
+        if self.expression == old_name:
+            self.expression = new_name
+    setattr(cls, "updateElementName", updateElementName)
+
+    def updateElementAddress(self, address_model, new_leading):
+        self.expression = update_address(self.expression, address_model, new_leading)
+    setattr(cls, "updateElementAddress", updateElementAddress)
+
+    setattr(cls, "Search", _SearchInIOVariable)
+
+
+def _SearchInConnector(self, criteria, parent_infos=[]):
+    return _Search([("name", self.getname())], criteria, parent_infos + ["connector", self.getlocalId()])
+
+cls = _initElementClass("continuation", "commonObjects_continuation")
+if cls:
+    setattr(cls, "getinfos", _getconnectorinfosFunction("continuation"))
+    setattr(cls, "Search", _SearchInConnector)
+
+    def updateElementName(self, old_name, new_name):
+        if self.name == old_name:
+            self.name = new_name
+    setattr(cls, "updateElementName", updateElementName)
+
+cls = _initElementClass("connector", "commonObjects_connector", "single")
+if cls:
+    setattr(cls, "getinfos", _getconnectorinfosFunction("connector"))
+    setattr(cls, "Search", _SearchInConnector)
+
+    def updateElementName(self, old_name, new_name):
+        if self.name == old_name:
+            self.name = new_name
+    setattr(cls, "updateElementName", updateElementName)
+
+cls = PLCOpenClasses.get("connection", None)
+if cls:
+    def setpoints(self, points):
+        self.position = []
+        for point in points:
+            position = PLCOpenClasses["position"]()
+            position.setx(point.x)
+            position.sety(point.y)
+            self.position.append(position)
+    setattr(cls, "setpoints", setpoints)
+
+    def getpoints(self):
+        points = []
+        for position in self.position:
+            points.append((position.getx(),position.gety()))
+        return points
+    setattr(cls, "getpoints", getpoints)
+
+cls = PLCOpenClasses.get("connectionPointIn", None)
+if cls:
+    def setrelPositionXY(self, x, y):
+        self.relPosition = PLCOpenClasses["position"]()
+        self.relPosition.setx(x)
+        self.relPosition.sety(y)
+    setattr(cls, "setrelPositionXY", setrelPositionXY)
+
+    def getrelPositionXY(self):
+        if self.relPosition:
+            return self.relPosition.getx(), self.relPosition.gety()
+        else:
+            return self.relPosition
+    setattr(cls, "getrelPositionXY", getrelPositionXY)
+
+    def addconnection(self):
+        if not self.content:
+            self.content = {"name" : "connection", "value" : [PLCOpenClasses["connection"]()]}
+        else:
+            self.content["value"].append(PLCOpenClasses["connection"]())
+    setattr(cls, "addconnection", addconnection)
+
+    def removeconnection(self, idx):
+        if self.content:
+            self.content["value"].pop(idx)
+        if len(self.content["value"]) == 0:
+            self.content = None
+    setattr(cls, "removeconnection", removeconnection)
+
+    def removeconnections(self):
+        if self.content:
+            self.content = None
+    setattr(cls, "removeconnections", removeconnections)
+    
+    def getconnections(self):
+        if self.content:
+            return self.content["value"]
+    setattr(cls, "getconnections", getconnections)
+    
+    def setconnectionId(self, idx, id):
+        if self.content:
+            self.content["value"][idx].setrefLocalId(id)
+    setattr(cls, "setconnectionId", setconnectionId)
+    
+    def getconnectionId(self, idx):
+        if self.content:
+            return self.content["value"][idx].getrefLocalId()
+        return None
+    setattr(cls, "getconnectionId", getconnectionId)
+    
+    def setconnectionPoints(self, idx, points):
+        if self.content:
+            self.content["value"][idx].setpoints(points)
+    setattr(cls, "setconnectionPoints", setconnectionPoints)
+
+    def getconnectionPoints(self, idx):
+        if self.content:
+            return self.content["value"][idx].getpoints()
+        return None
+    setattr(cls, "getconnectionPoints", getconnectionPoints)
+
+    def setconnectionParameter(self, idx, parameter):
+        if self.content:
+            self.content["value"][idx].setformalParameter(parameter)
+    setattr(cls, "setconnectionParameter", setconnectionParameter)
+    
+    def getconnectionParameter(self, idx):
+        if self.content:
+            return self.content["value"][idx].getformalParameter()
+        return None
+    setattr(cls, "getconnectionParameter", getconnectionParameter)
+
+cls = PLCOpenClasses.get("connectionPointOut", None)
+if cls:
+    def setrelPositionXY(self, x, y):
+        self.relPosition = PLCOpenClasses["position"]()
+        self.relPosition.setx(x)
+        self.relPosition.sety(y)
+    setattr(cls, "setrelPositionXY", setrelPositionXY)
+
+    def getrelPositionXY(self):
+        if self.relPosition:
+            return self.relPosition.getx(), self.relPosition.gety()
+        return self.relPosition
+    setattr(cls, "getrelPositionXY", getrelPositionXY)
+
+cls = PLCOpenClasses.get("value", None)
+if cls:
+    def setvalue(self, value):
+        value = value.strip()
+        if value.startswith("[") and value.endswith("]"):
+            arrayValue = PLCOpenClasses["value_arrayValue"]()
+            self.content = {"name" : "arrayValue", "value" : arrayValue}
+        elif value.startswith("(") and value.endswith(")"):
+            structValue = PLCOpenClasses["value_structValue"]()
+            self.content = {"name" : "structValue", "value" : structValue}
+        else:
+            simpleValue = PLCOpenClasses["value_simpleValue"]()
+            self.content = {"name" : "simpleValue", "value": simpleValue}
+        self.content["value"].setvalue(value)
+    setattr(cls, "setvalue", setvalue)
+    
+    def getvalue(self):
+        return self.content["value"].getvalue()
+    setattr(cls, "getvalue", getvalue)
+
+def extractValues(values):
+    items = values.split(",")
+    i = 1
+    while i < len(items):
+        opened = items[i - 1].count("(") + items[i - 1].count("[")
+        closed = items[i - 1].count(")") + items[i - 1].count("]")
+        if opened > closed:
+            items[i - 1] = ','.join([items[i - 1], items.pop(i)])
+        elif opened == closed:
+            i += 1
+        else:
+            raise ValueError, _("\"%s\" is an invalid value!")%value
+    return items
+
+cls = PLCOpenClasses.get("value_arrayValue", None)
+if cls:
+    arrayValue_model = re.compile("([0-9]*)\((.*)\)$")
+    
+    def setvalue(self, value):
+        self.value = []
+        for item in extractValues(value[1:-1]):
+            item = item.strip()
+            element = PLCOpenClasses["arrayValue_value"]()
+            result = arrayValue_model.match(item)
+            if result is not None:
+                groups = result.groups()
+                element.setrepetitionValue(groups[0])
+                element.setvalue(groups[1].strip())
+            else:
+                element.setvalue(item)
+            self.value.append(element)
+    setattr(cls, "setvalue", setvalue)
+    
+    def getvalue(self):
+        values = []
+        for element in self.value:
+            repetition = element.getrepetitionValue()
+            if repetition is not None and int(repetition) > 1:
+                value = element.getvalue()
+                if value is None:
+                    value = ""
+                values.append("%s(%s)"%(repetition, value))
+            else:
+                values.append(element.getvalue())
+        return "[%s]"%", ".join(values)
+    setattr(cls, "getvalue", getvalue)
+
+cls = PLCOpenClasses.get("value_structValue", None)
+if cls:
+    structValue_model = re.compile("(.*):=(.*)")
+    
+    def setvalue(self, value):
+        self.value = []
+        for item in extractValues(value[1:-1]):
+            result = structValue_model.match(item)
+            if result is not None:
+                groups = result.groups()
+                element = PLCOpenClasses["structValue_value"]()
+                element.setmember(groups[0].strip())
+                element.setvalue(groups[1].strip())
+                self.value.append(element)
+    setattr(cls, "setvalue", setvalue)
+    
+    def getvalue(self):
+        values = []
+        for element in self.value:
+            values.append("%s := %s"%(element.getmember(), element.getvalue()))
+        return "(%s)"%", ".join(values)
+    setattr(cls, "getvalue", getvalue)