plcopen/plcopen.py
author lbessard
Tue, 17 Mar 2009 15:58:50 +0100
changeset 321 5b37e16f7b2a
parent 295 c6ef6d92ce16
child 348 09fdd7616a86
permissions -rw-r--r--
Adding support for adding segments on only one segment wire
Bug with wire Contextuel Menu
#!/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"}

"""
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}

PLCOpenClasses = GenerateClassesFromXSD(os.path.join(os.path.split(__file__)[0], "TC6_XML_V10_B.xsd"))

cls = PLCOpenClasses.get("formattedText", None)
if cls:
    def updateElementName(self, old_name, new_name):
        index = self.text.find(old_name)
        while index != -1:
            if index > 0 and (self.text[index - 1].isalnum() or self.text[index - 1] == "_"):
                index = self.text.find(old_name, index + len(old_name))
            elif index < len(self.text) - len(old_name) and (self.text[index + len(old_name)].isalnum() or self.text[index + len(old_name)] == "_"):
                index = self.text.find(old_name, index + len(old_name))
            else:
                self.text = self.text[:index] + new_name + self.text[index + len(old_name):]
                index = self.text.find(old_name, index + len(new_name))
    setattr(cls, "updateElementName", updateElementName)
    
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 = {}
        fileheader["companyName"] = self.fileHeader.getcompanyName()
        if self.fileHeader.getcompanyURL():
            fileheader["companyURL"] = self.fileHeader.getcompanyURL()
        fileheader["productName"] = self.fileHeader.getproductName()
        fileheader["productVersion"] = self.fileHeader.getproductVersion()
        if self.fileHeader.getproductRelease():
            fileheader["productRelease"] = self.fileHeader.getproductRelease()
        fileheader["creationDateTime"] = self.fileHeader.getcreationDateTime()
        if self.fileHeader.getcontentDescription():
            fileheader["contentDescription"] = self.fileHeader.getcontentDescription()
        return fileheader
    setattr(cls, "getfileHeader", getfileHeader)
    
    def setfileHeader(self, fileheader):
        self.fileHeader.setcompanyName(fileheader["companyName"])
        if "companyURL" in fileheader:
            self.fileHeader.setcompanyURL(fileheader["companyURL"])
        self.fileHeader.setproductName(fileheader["productName"])
        self.fileHeader.setproductVersion(fileheader["productVersion"])
        if "productRelease" in fileheader:
            self.fileHeader.setproductRelease(fileheader["productRelease"])
        self.fileHeader.setcreationDateTime(fileheader["creationDateTime"])
        if "contentDescription" in fileheader:
            self.fileHeader.setcontentDescription(fileheader["contentDescription"])
    setattr(cls, "setfileHeader", setfileHeader)
    
    def getcontentHeader(self):
        contentheader = {}
        contentheader["projectName"] = self.contentHeader.getname()
        if self.contentHeader.getversion():
            contentheader["projectVersion"] = self.contentHeader.getversion()
        if self.contentHeader.getmodificationDateTime():
            contentheader["modificationDateTime"] = self.contentHeader.getmodificationDateTime()
        if self.contentHeader.getorganization():
            contentheader["organization"] = self.contentHeader.getorganization()
        if self.contentHeader.getauthor():
            contentheader["authorName"] = self.contentHeader.getauthor()
        if self.contentHeader.getlanguage():
            contentheader["language"] = self.contentHeader.getlanguage()
        contentheader["pageSize"] = self.contentHeader.getpageSize()
        contentheader["scaling"] = self.contentHeader.getscaling()
        return contentheader
    setattr(cls, "getcontentHeader", getcontentHeader)
    
    def setcontentHeader(self, contentheader):
        self.contentHeader.setname(contentheader["projectName"])
        if "projectVersion" in contentheader:
            self.contentHeader.setversion(contentheader["projectVersion"])
        if "modificationDateTime" in contentheader:
            self.contentHeader.setmodificationDateTime(contentheader["modificationDateTime"])
        if "organization" in contentheader:
            self.contentHeader.setorganization(contentheader["organization"])
        if "authorName" in contentheader:
            self.contentHeader.setauthor(contentheader["authorName"])
        if "language" in contentheader:
            self.contentHeader.setlanguage(contentheader["language"])
        self.contentHeader.setpageSize(*contentheader["pageSize"])
        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 name in self.CustomTypeHierarchy:
            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 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 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" : "",
                       "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"))    
        if pou.getbodyType() in ["FBD","LD","SFC"]:
            for instance in pou.getinstances():
                if isinstance(instance, PLCOpenClasses.get("commonObjects_comment", None)):
                    block_infos["comment"] = instance.getcontentText()
        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 typename in elementnames and name not 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 typename in elementnames 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 typename in elementnames 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 typename in elementnames and name not in self.ElementUsingTree[typename]:
                                self.ElementUsingTree[typename].append(name)
    setattr(cls, "RefreshElementUsingTree", RefreshElementUsingTree)

    def GetParentType(self, type):
        if type in self.CustomTypeHierarchy:
            return self.CustomTypeHierarchy[type]
        elif type in TypeHierarchy:
            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 DataTypeRange.keys() + 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 name in self.ElementUsingTree:
            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 name in self.ElementUsingTree:
            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 type in self.CustomDataTypeRange:
            return self.CustomDataTypeRange[type]
        elif type in DataTypeRange:
            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 type in self.EnumeratedDataTypeValues:
            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:
                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 = ""):
        customdatatypes = []
        for customdatatype in self.getdataTypes():
            customdatatype_name = customdatatype.getname()
            if customdatatype_name != exclude and not self.ElementIsUsedBy(exclude, customdatatype_name):
                customdatatypes.append(customdatatype_name)
        return customdatatypes
    setattr(cls, "GetCustomDataTypes", GetCustomDataTypes)

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)

cls = PLCOpenClasses.get("configurations_configuration", None)
if cls:
    def updateElementName(self, old_name, new_name):
        for resource in self.getresource():
            resource.updateElementName(old_name, new_name)
    setattr(cls, "updateElementName", updateElementName)


cls = PLCOpenClasses.get("configuration_resource", None)
if cls:
    def updateElementName(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)

cls = PLCOpenClasses.get("resource_task", None)
if cls:
    def updateElementName(self, old_name, new_name):
        if self.single == old_name:
            self.single = new_name
        for instance in self.getpouInstance():
            instance.updateElementName(old_name, new_name)
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("pouInstance", None)
if cls:
    def updateElementName(self, old_name, new_name):
        if self.type == old_name:
            self.type = new_name
    setattr(cls, "updateElementName", updateElementName)

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.setbody(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 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()
setattr(cls, "gettext", gettext)

cls = PLCOpenClasses.get("pous_pou", 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 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 addpouVar(self, type, name):
        if self.interface is None:
            self.interface = PLCOpenClasses["pou_interface"]()
        content = self.interface.getcontent()
        if len(content) == 0 or content[-1]["name"] != "localVars":
            content.append({"name" : "localVars", "value" : PLCOpenClasses["interface_localVars"]()})
        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" : "localVars", "value" : PLCOpenClasses["interface_localVars"]()})
        var = PLCOpenClasses["varListPlain_variable"]()
        var.setname(name)
        var_type = PLCOpenClasses["dataType"]()
        derived_type = PLCOpenClasses["derivedTypes_derived"]()
        derived_type.setname(type)
        var_type.setcontent({"name" : "derived", "value" : derived_type})
        var.settype(var_type)
        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 exists!"%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 exists!"%name
    setattr(cls, "removeaction", removeaction)

    def updateElementName(self, old_name, new_name):
        self.body.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)

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 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)

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 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)

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 exists!"%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 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)

cls = PLCOpenClasses.get("commonObjects_comment", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)

    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)

cls = PLCOpenClasses.get("fbdObjects_block", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)

    def updateElementName(self, old_name, new_name):
        if self.typeName == old_name:
            self.typeName = new_name
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("ldObjects_leftPowerRail", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)

    def updateElementName(self, old_name, new_name):
        pass
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("ldObjects_rightPowerRail", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)
    
    def updateElementName(self, old_name, new_name):
        pass
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("ldObjects_contact", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)

    def updateElementName(self, old_name, new_name):
        if self.variable == old_name:
            self.variable = new_name
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("ldObjects_coil", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)

    def updateElementName(self, old_name, new_name):
        if self.variable == old_name:
            self.variable = new_name
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("sfcObjects_step", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)

    def updateElementName(self, old_name, new_name):
        pass
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("sfcObjects_transition", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)

    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":
            condition = [PLCOpenClasses["connection"]()]
        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()
            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 addconnection(self):
        if self.condition:
            content = self.condition.getcontent()
            if content["name"] != "connection":
                self.condition.setcontent({"name" : "connection", "value" : [PLCOpenClasses["connection"]()]})
                content = self.condition.getcontent()
            else:
                content["value"].append(PLCOpenClasses["connection"]())
    setattr(cls, "addconnection", addconnection)
    
    def removeconnection(self, idx):
        if self.condition:
            content = self.condition.getcontent()
            if content["name"] == "connection":
                content["value"].pop(idx)
        setattr(cls, "removeconnection", removeconnection)

    def removeconnections(self):
        if self.condition:
            content = self.condition.getcontent()
            if content["name"] == "connection":
                content["value"] = [PLCOpenClasses["connection"]()]
    setattr(cls, "removeconnections", removeconnections)
    
    def getconnections(self):
        if self.condition:
            content = self.condition.getcontent()
            if content["name"] == "connection":
                return content["value"]
    setattr(cls, "getconnections", getconnections)
    
    def setconnectionId(self, idx, id):
        if self.condition:
            content = self.condition.getcontent()
            if content["name"] == "connection":
                content["value"][idx].setrefLocalId(id)
    setattr(cls, "setconnectionId", setconnectionId)
    
    def getconnectionId(self, idx):
        if self.condition:
            content = self.condition.getcontent()
            if content["name"] == "connection":
                return content["value"][idx].getrefLocalId()
        return None
    setattr(cls, "getconnectionId", getconnectionId)
    
    def setconnectionPoints(self, idx, points):
        if self.condition:
            content = self.condition.getcontent()
            if content["name"] == "connection":
                content["value"][idx].setpoints(points)
    setattr(cls, "setconnectionPoints", setconnectionPoints)

    def getconnectionPoints(self, idx):
        if self.condition:
            content = self.condition.getcontent()
            if content["name"] == "connection":
                return content["value"][idx].getpoints()
        return None
    setattr(cls, "getconnectionPoints", getconnectionPoints)

    def setconnectionParameter(self, idx, parameter):
        if self.condition:
            content = self.condition.getcontent()
            if content["name"] == "connection":
                content["value"][idx].setformalParameter(parameter)
    setattr(cls, "setconnectionParameter", setconnectionParameter)
    
    def getconnectionParameter(self, idx):
        if self.condition:
            content = self.condition.getcontent()
            if content["name"] == "connection":
                return content["value"][idx].getformalParameter()
        return None
    setattr(cls, "getconnectionParameter", getconnectionParameter)

cls = PLCOpenClasses.get("sfcObjects_selectionDivergence", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)

    def updateElementName(self, old_name, new_name):
        pass
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("sfcObjects_selectionConvergence", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)
    
    def updateElementName(self, old_name, new_name):
        pass
    setattr(cls, "updateElementName", updateElementName)
    
cls = PLCOpenClasses.get("sfcObjects_simultaneousDivergence", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)
    
    def updateElementName(self, old_name, new_name):
        pass
    setattr(cls, "updateElementName", updateElementName)
    
cls = PLCOpenClasses.get("sfcObjects_simultaneousConvergence", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)
    
    def updateElementName(self, old_name, new_name):
        pass
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("sfcObjects_jumpStep", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)
    
    def updateElementName(self, old_name, new_name):
        pass
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("actionBlock_action", None)
if cls:
    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)

cls = PLCOpenClasses.get("commonObjects_actionBlock", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)

    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 "duration" in params:
                action.setduration(params["duration"])
            if "indicator" in params:
                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)

cls = PLCOpenClasses.get("fbdObjects_inVariable", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)
    
    def updateElementName(self, old_name, new_name):
        if self.expression == old_name:
            self.expression = new_name
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("fbdObjects_outVariable", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)

    def updateElementName(self, old_name, new_name):
        if self.expression == old_name:
            self.expression = new_name
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("fbdObjects_inOutVariable", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)

    def updateElementName(self, old_name, new_name):
        if self.expression == old_name:
            self.expression = new_name
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("commonObjects_continuation", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)
    
    def updateElementName(self, old_name, new_name):
        pass
    setattr(cls, "updateElementName", updateElementName)

cls = PLCOpenClasses.get("commonObjects_connector", None)
if cls:
    setattr(cls, "getx", getx)
    setattr(cls, "gety", gety)
    setattr(cls, "setx", setx)
    setattr(cls, "sety", sety)
    
    def updateElementName(self, old_name, new_name):
        pass
    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):
        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(int(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 repetition > 1:
                values.append("%d(%s)"%(repetition, element.getvalue()))
            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)