plcopen/plcopen.py
changeset 814 5743cbdff669
child 824 be669f4c51c4
equal deleted inserted replaced
813:1460273f40ed 814:5743cbdff669
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 
       
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
       
     5 #based on the plcopen standard. 
       
     6 #
       
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
       
     8 #
       
     9 #See COPYING file for copyrights details.
       
    10 #
       
    11 #This library is free software; you can redistribute it and/or
       
    12 #modify it under the terms of the GNU General Public
       
    13 #License as published by the Free Software Foundation; either
       
    14 #version 2.1 of the License, or (at your option) any later version.
       
    15 #
       
    16 #This library is distributed in the hope that it will be useful,
       
    17 #but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    19 #General Public License for more details.
       
    20 #
       
    21 #You should have received a copy of the GNU General Public
       
    22 #License along with this library; if not, write to the Free Software
       
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    24 
       
    25 from xmlclass import *
       
    26 from structures import *
       
    27 from types import *
       
    28 import os, re
       
    29 
       
    30 """
       
    31 Dictionary that makes the relation between var names in plcopen and displayed values
       
    32 """
       
    33 VarTypes = {"Local" : "localVars", "Temp" : "tempVars", "Input" : "inputVars",
       
    34             "Output" : "outputVars", "InOut" : "inOutVars", "External" : "externalVars",
       
    35             "Global" : "globalVars", "Access" : "accessVars"}
       
    36 
       
    37 searchResultVarTypes = {
       
    38     "inputVars": "var_input",
       
    39     "outputVars": "var_output",
       
    40     "inOutVars": "var_inout"
       
    41 }
       
    42 
       
    43 """
       
    44 Define in which order var types must be displayed
       
    45 """
       
    46 VarOrder = ["Local","Temp","Input","Output","InOut","External","Global","Access"]
       
    47 
       
    48 """
       
    49 Define which action qualifier must be associated with a duration 
       
    50 """
       
    51 QualifierList = {"N" : False, "R" : False, "S" : False, "L" : True, "D" : True, 
       
    52     "P" : False, "P0" : False, "P1" : False, "SD" : True, "DS" : True, "SL" : True}
       
    53 
       
    54 
       
    55 FILTER_ADDRESS_MODEL = "(%%[IQM](?:[XBWDL])?)(%s)((?:\.[0-9]+)*)" 
       
    56 
       
    57 def update_address(address, address_model, new_leading):
       
    58     result = address_model.match(address)
       
    59     if result is None:
       
    60         return address
       
    61     groups = result.groups()
       
    62     return groups[0] + new_leading + groups[2]
       
    63 
       
    64 def _init_and_compare(function, v1, v2):
       
    65     if v1 is None:
       
    66         return v2
       
    67     if v2 is not None:
       
    68         return function(v1, v2)
       
    69     return v1
       
    70 
       
    71 """
       
    72 Helper class for bounding_box calculation 
       
    73 """
       
    74 class rect:
       
    75     
       
    76     def __init__(self, x=None, y=None, width=None, height=None):
       
    77         self.x_min = x
       
    78         self.x_max = None
       
    79         self.y_min = y
       
    80         self.y_max = None
       
    81         if width is not None and x is not None:
       
    82             self.x_max = x + width
       
    83         if height is not None and y is not None:
       
    84             self.y_max = y + height
       
    85     
       
    86     def update(self, x, y):
       
    87         self.x_min = _init_and_compare(min, self.x_min, x)
       
    88         self.x_max = _init_and_compare(max, self.x_max, x)
       
    89         self.y_min = _init_and_compare(min, self.y_min, y)
       
    90         self.y_max = _init_and_compare(max, self.y_max, y)
       
    91         
       
    92     def union(self, rect):
       
    93         self.x_min = _init_and_compare(min, self.x_min, rect.x_min)
       
    94         self.x_max = _init_and_compare(max, self.x_max, rect.x_max)
       
    95         self.y_min = _init_and_compare(min, self.y_min, rect.y_min)
       
    96         self.y_max = _init_and_compare(max, self.y_max, rect.y_max)
       
    97     
       
    98     def bounding_box(self):
       
    99         width = height = None
       
   100         if self.x_min is not None and self.x_max is not None:
       
   101             width = self.x_max - self.x_min
       
   102         if self.y_min is not None and self.y_max is not None:
       
   103             height = self.y_max - self.y_min
       
   104         return self.x_min, self.y_min, width, height
       
   105 
       
   106 def TextLenInRowColumn(text):
       
   107     if text == "":
       
   108         return (0, 0)
       
   109     lines = text.split("\n")
       
   110     return len(lines) - 1, len(lines[-1])
       
   111 
       
   112 def TestTextElement(text, criteria):
       
   113     lines = text.splitlines()
       
   114     if not criteria["case_sensitive"]:
       
   115         text = text.upper()
       
   116     test_result = []
       
   117     result = criteria["pattern"].search(text)
       
   118     while result is not None:
       
   119         start = TextLenInRowColumn(text[:result.start()])
       
   120         end = TextLenInRowColumn(text[:result.end() - 1])
       
   121         test_result.append((start, end, "\n".join(lines[start[0]:end[0] + 1])))
       
   122         result = criteria["pattern"].search(text, result.end())
       
   123     return test_result
       
   124 
       
   125 PLCOpenClasses = GenerateClassesFromXSD(os.path.join(os.path.split(__file__)[0], "tc6_xml_v201.xsd"))
       
   126 
       
   127 ElementNameToClass = {}
       
   128 
       
   129 cls = PLCOpenClasses.get("formattedText", None)
       
   130 if cls:
       
   131     def updateElementName(self, old_name, new_name):
       
   132         text = self.text.decode("utf-8")
       
   133         index = text.find(old_name)
       
   134         while index != -1:
       
   135             if index > 0 and (text[index - 1].isalnum() or text[index - 1] == "_"):
       
   136                 index = text.find(old_name, index + len(old_name))
       
   137             elif index < len(text) - len(old_name) and (text[index + len(old_name)].isalnum() or text[index + len(old_name)] == "_"):
       
   138                 index = text.find(old_name, index + len(old_name))
       
   139             else:
       
   140                 text = text[:index] + new_name + text[index + len(old_name):]
       
   141                 index = text.find(old_name, index + len(new_name))
       
   142         self.text = text.encode("utf-8")
       
   143     setattr(cls, "updateElementName", updateElementName)
       
   144     
       
   145     def updateElementAddress(self, address_model, new_leading):
       
   146         text = self.text.decode("utf-8")
       
   147         startpos = 0
       
   148         result = address_model.search(text, startpos)
       
   149         while result is not None:
       
   150             groups = result.groups()
       
   151             new_address = groups[0] + new_leading + groups[2]
       
   152             text = text[:result.start()] + new_address + text[result.end():]
       
   153             startpos = result.start() + len(new_address)
       
   154             result = address_model.search(self.text, startpos)
       
   155         self.text = text.encode("utf-8")
       
   156     setattr(cls, "updateElementAddress", updateElementAddress)
       
   157     
       
   158     def Search(self, criteria, parent_infos):
       
   159         return [(tuple(parent_infos),) + result for result in TestTextElement(self.gettext(), criteria)]
       
   160     setattr(cls, "Search", Search)
       
   161     
       
   162 cls = PLCOpenClasses.get("project", None)
       
   163 if cls:
       
   164     cls.singleLineAttributes = False
       
   165     cls.EnumeratedDataTypeValues = {}
       
   166     cls.CustomDataTypeRange = {}
       
   167     cls.CustomTypeHierarchy = {}
       
   168     cls.ElementUsingTree = {}
       
   169     cls.CustomBlockTypes = []
       
   170     
       
   171     def setname(self, name):
       
   172         self.contentHeader.setname(name)
       
   173     setattr(cls, "setname", setname)
       
   174         
       
   175     def getname(self):
       
   176         return self.contentHeader.getname()
       
   177     setattr(cls, "getname", getname)
       
   178     
       
   179     def getfileHeader(self):
       
   180         fileheader = {}
       
   181         for name, value in [("companyName", self.fileHeader.getcompanyName()),
       
   182                             ("companyURL", self.fileHeader.getcompanyURL()),
       
   183                             ("productName", self.fileHeader.getproductName()),
       
   184                             ("productVersion", self.fileHeader.getproductVersion()),
       
   185                             ("productRelease", self.fileHeader.getproductRelease()),
       
   186                             ("creationDateTime", self.fileHeader.getcreationDateTime()),
       
   187                             ("contentDescription", self.fileHeader.getcontentDescription())]:
       
   188             if value is not None:
       
   189                 fileheader[name] = value
       
   190             else:
       
   191                 fileheader[name] = ""
       
   192         return fileheader
       
   193     setattr(cls, "getfileHeader", getfileHeader)
       
   194     
       
   195     def setfileHeader(self, fileheader):
       
   196         if fileheader.has_key("companyName"):
       
   197             self.fileHeader.setcompanyName(fileheader["companyName"])
       
   198         if fileheader.has_key("companyURL"):
       
   199             self.fileHeader.setcompanyURL(fileheader["companyURL"])
       
   200         if fileheader.has_key("productName"):
       
   201             self.fileHeader.setproductName(fileheader["productName"])
       
   202         if fileheader.has_key("productVersion"):
       
   203             self.fileHeader.setproductVersion(fileheader["productVersion"])
       
   204         if fileheader.has_key("productRelease"):
       
   205             self.fileHeader.setproductRelease(fileheader["productRelease"])
       
   206         if fileheader.has_key("creationDateTime"):
       
   207             self.fileHeader.setcreationDateTime(fileheader["creationDateTime"])
       
   208         if fileheader.has_key("contentDescription"):
       
   209             self.fileHeader.setcontentDescription(fileheader["contentDescription"])
       
   210     setattr(cls, "setfileHeader", setfileHeader)
       
   211     
       
   212     def getcontentHeader(self):
       
   213         contentheader = {}
       
   214         for name, value in [("projectName", self.contentHeader.getname()),
       
   215                             ("projectVersion", self.contentHeader.getversion()),
       
   216                             ("modificationDateTime", self.contentHeader.getmodificationDateTime()),
       
   217                             ("organization", self.contentHeader.getorganization()),
       
   218                             ("authorName", self.contentHeader.getauthor()),
       
   219                             ("language", self.contentHeader.getlanguage())]:
       
   220             if value is not None:
       
   221                 contentheader[name] = value
       
   222             else:
       
   223                 contentheader[name] = ""
       
   224         contentheader["pageSize"] = self.contentHeader.getpageSize()
       
   225         contentheader["scaling"] = self.contentHeader.getscaling()
       
   226         return contentheader
       
   227     setattr(cls, "getcontentHeader", getcontentHeader)
       
   228     
       
   229     def setcontentHeader(self, contentheader):
       
   230         if contentheader.has_key("projectName"):
       
   231             self.contentHeader.setname(contentheader["projectName"])
       
   232         if contentheader.has_key("projectVersion"):
       
   233             self.contentHeader.setversion(contentheader["projectVersion"])
       
   234         if contentheader.has_key("modificationDateTime"):
       
   235             self.contentHeader.setmodificationDateTime(contentheader["modificationDateTime"])
       
   236         if contentheader.has_key("organization"):
       
   237             self.contentHeader.setorganization(contentheader["organization"])
       
   238         if contentheader.has_key("authorName"):
       
   239             self.contentHeader.setauthor(contentheader["authorName"])
       
   240         if contentheader.has_key("language"):
       
   241             self.contentHeader.setlanguage(contentheader["language"])
       
   242         if contentheader.has_key("pageSize"):
       
   243             self.contentHeader.setpageSize(*contentheader["pageSize"])
       
   244         if contentheader.has_key("scaling"):
       
   245             self.contentHeader.setscaling(contentheader["scaling"])
       
   246     setattr(cls, "setcontentHeader", setcontentHeader)
       
   247     
       
   248     def getdataTypes(self):
       
   249         return self.types.getdataTypeElements()
       
   250     setattr(cls, "getdataTypes", getdataTypes)
       
   251     
       
   252     def getdataType(self, name):
       
   253         return self.types.getdataTypeElement(name)
       
   254     setattr(cls, "getdataType", getdataType)
       
   255     
       
   256     def appenddataType(self, name):
       
   257         if self.CustomTypeHierarchy.has_key(name):
       
   258             raise ValueError, "\"%s\" Data Type already exists !!!"%name
       
   259         self.types.appenddataTypeElement(name)
       
   260         self.AddCustomDataType(self.getdataType(name))
       
   261     setattr(cls, "appenddataType", appenddataType)
       
   262         
       
   263     def insertdataType(self, index, datatype):
       
   264         self.types.insertdataTypeElement(index, datatype)
       
   265         self.AddCustomDataType(datatype)
       
   266     setattr(cls, "insertdataType", insertdataType)
       
   267     
       
   268     def removedataType(self, name):
       
   269         self.types.removedataTypeElement(name)
       
   270         self.RefreshDataTypeHierarchy()
       
   271         self.RefreshElementUsingTree()
       
   272     setattr(cls, "removedataType", removedataType)
       
   273     
       
   274     def getpous(self):
       
   275         return self.types.getpouElements()
       
   276     setattr(cls, "getpous", getpous)
       
   277     
       
   278     def getpou(self, name):
       
   279         return self.types.getpouElement(name)
       
   280     setattr(cls, "getpou", getpou)
       
   281     
       
   282     def appendpou(self, name, pou_type, body_type):
       
   283         self.types.appendpouElement(name, pou_type, body_type)
       
   284         self.AddCustomBlockType(self.getpou(name))
       
   285     setattr(cls, "appendpou", appendpou)
       
   286         
       
   287     def insertpou(self, index, pou):
       
   288         self.types.insertpouElement(index, pou)
       
   289         self.AddCustomBlockType(pou)
       
   290     setattr(cls, "insertpou", insertpou)
       
   291     
       
   292     def removepou(self, name):
       
   293         self.types.removepouElement(name)
       
   294         self.RefreshCustomBlockTypes()
       
   295         self.RefreshElementUsingTree()
       
   296     setattr(cls, "removepou", removepou)
       
   297 
       
   298     def getconfigurations(self):
       
   299         configurations = self.instances.configurations.getconfiguration()
       
   300         if configurations:
       
   301             return configurations
       
   302         return []
       
   303     setattr(cls, "getconfigurations", getconfigurations)
       
   304 
       
   305     def getconfiguration(self, name):
       
   306         for configuration in self.instances.configurations.getconfiguration():
       
   307             if configuration.getname() == name:
       
   308                 return configuration
       
   309         return None
       
   310     setattr(cls, "getconfiguration", getconfiguration)
       
   311 
       
   312     def addconfiguration(self, name):
       
   313         for configuration in self.instances.configurations.getconfiguration():
       
   314             if configuration.getname() == name:
       
   315                 raise ValueError, _("\"%s\" configuration already exists !!!")%name
       
   316         new_configuration = PLCOpenClasses["configurations_configuration"]()
       
   317         new_configuration.setname(name)
       
   318         self.instances.configurations.appendconfiguration(new_configuration)
       
   319     setattr(cls, "addconfiguration", addconfiguration)    
       
   320 
       
   321     def removeconfiguration(self, name):
       
   322         found = False
       
   323         for idx, configuration in enumerate(self.instances.configurations.getconfiguration()):
       
   324             if configuration.getname() == name:
       
   325                 self.instances.configurations.removeconfiguration(idx)
       
   326                 found = True
       
   327                 break
       
   328         if not found:
       
   329             raise ValueError, ("\"%s\" configuration doesn't exist !!!")%name
       
   330     setattr(cls, "removeconfiguration", removeconfiguration)
       
   331 
       
   332     def getconfigurationResource(self, config_name, name):
       
   333         configuration = self.getconfiguration(config_name)
       
   334         if configuration:
       
   335             for resource in configuration.getresource():
       
   336                 if resource.getname() == name:
       
   337                     return resource
       
   338         return None
       
   339     setattr(cls, "getconfigurationResource", getconfigurationResource)
       
   340 
       
   341     def addconfigurationResource(self, config_name, name):
       
   342         configuration = self.getconfiguration(config_name)
       
   343         if configuration:
       
   344             for resource in configuration.getresource():
       
   345                 if resource.getname() == name:
       
   346                     raise ValueError, _("\"%s\" resource already exists in \"%s\" configuration !!!")%(name, config_name)
       
   347             new_resource = PLCOpenClasses["configuration_resource"]()
       
   348             new_resource.setname(name)
       
   349             configuration.appendresource(new_resource)
       
   350     setattr(cls, "addconfigurationResource", addconfigurationResource)
       
   351 
       
   352     def removeconfigurationResource(self, config_name, name):
       
   353         configuration = self.getconfiguration(config_name)
       
   354         if configuration:
       
   355             found = False
       
   356             for idx, resource in enumerate(configuration.getresource()):
       
   357                 if resource.getname() == name:
       
   358                     configuration.removeresource(idx)
       
   359                     found = True
       
   360                     break
       
   361             if not found:
       
   362                 raise ValueError, _("\"%s\" resource doesn't exist in \"%s\" configuration !!!")%(name, config_name)
       
   363     setattr(cls, "removeconfigurationResource", removeconfigurationResource)
       
   364 
       
   365     def updateElementName(self, old_name, new_name):
       
   366         for datatype in self.types.getdataTypeElements():
       
   367             datatype.updateElementName(old_name, new_name)
       
   368         for pou in self.types.getpouElements():
       
   369             pou.updateElementName(old_name, new_name)
       
   370         for configuration in self.instances.configurations.getconfiguration():
       
   371             configuration.updateElementName(old_name, new_name)
       
   372     setattr(cls, "updateElementName", updateElementName)
       
   373 
       
   374     def updateElementAddress(self, old_leading, new_leading):
       
   375         address_model = re.compile(FILTER_ADDRESS_MODEL % old_leading)
       
   376         for pou in self.types.getpouElements():
       
   377             pou.updateElementAddress(address_model, new_leading)
       
   378         for configuration in self.instances.configurations.getconfiguration():
       
   379             configuration.updateElementAddress(address_model, new_leading)
       
   380     setattr(cls, "updateElementAddress", updateElementAddress)
       
   381 
       
   382     def removeVariableByAddress(self, address):
       
   383         for pou in self.types.getpouElements():
       
   384             pou.removeVariableByAddress(address)
       
   385         for configuration in self.instances.configurations.getconfiguration():
       
   386             configuration.removeVariableByAddress(address)
       
   387     setattr(cls, "removeVariableByAddress", removeVariableByAddress)
       
   388 
       
   389     def removeVariableByFilter(self, leading):
       
   390         address_model = re.compile(FILTER_ADDRESS_MODEL % leading)
       
   391         for pou in self.types.getpouElements():
       
   392             pou.removeVariableByFilter(address_model)
       
   393         for configuration in self.instances.configurations.getconfiguration():
       
   394             configuration.removeVariableByFilter(address_model)
       
   395     setattr(cls, "removeVariableByFilter", removeVariableByFilter)
       
   396 
       
   397     def RefreshDataTypeHierarchy(self):
       
   398         self.EnumeratedDataTypeValues = {}
       
   399         self.CustomDataTypeRange = {}
       
   400         self.CustomTypeHierarchy = {}
       
   401         for datatype in self.getdataTypes():
       
   402             self.AddCustomDataType(datatype)
       
   403     setattr(cls, "RefreshDataTypeHierarchy", RefreshDataTypeHierarchy)
       
   404 
       
   405     def AddCustomDataType(self, datatype):
       
   406         name = datatype.getname()
       
   407         basetype_content = datatype.getbaseType().getcontent()
       
   408         if basetype_content["value"] is None:
       
   409             self.CustomTypeHierarchy[name] = basetype_content["name"]
       
   410         elif basetype_content["name"] in ["string", "wstring"]:
       
   411             self.CustomTypeHierarchy[name] = basetype_content["name"].upper()
       
   412         elif basetype_content["name"] == "derived":
       
   413             self.CustomTypeHierarchy[name] = basetype_content["value"].getname()
       
   414         elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]:
       
   415             range = (basetype_content["value"].range.getlower(), 
       
   416                      basetype_content["value"].range.getupper())
       
   417             self.CustomDataTypeRange[name] = range
       
   418             base_type = basetype_content["value"].baseType.getcontent()
       
   419             if base_type["value"] is None:
       
   420                 self.CustomTypeHierarchy[name] = base_type["name"]
       
   421             else:
       
   422                 self.CustomTypeHierarchy[name] = base_type["value"].getname()
       
   423         else:
       
   424             if basetype_content["name"] == "enum":
       
   425                 values = []
       
   426                 for value in basetype_content["value"].values.getvalue():
       
   427                     values.append(value.getname())
       
   428                 self.EnumeratedDataTypeValues[name] = values
       
   429             self.CustomTypeHierarchy[name] = "ANY_DERIVED"
       
   430     setattr(cls, "AddCustomDataType", AddCustomDataType)
       
   431 
       
   432     # Update Block types with user-defined pou added
       
   433     def RefreshCustomBlockTypes(self):
       
   434         # Reset the tree of user-defined pou cross-use
       
   435         self.CustomBlockTypes = []
       
   436         for pou in self.getpous():
       
   437             self.AddCustomBlockType(pou)
       
   438     setattr(cls, "RefreshCustomBlockTypes", RefreshCustomBlockTypes)
       
   439 
       
   440     def AddCustomBlockType(self, pou): 
       
   441         pou_name = pou.getname()
       
   442         pou_type = pou.getpouType()
       
   443         block_infos = {"name" : pou_name, "type" : pou_type, "extensible" : False,
       
   444                        "inputs" : [], "outputs" : [], "comment" : pou.getdescription(),
       
   445                        "generate" : generate_block, "initialise" : initialise_block}
       
   446         if pou.getinterface():
       
   447             return_type = pou.interface.getreturnType()
       
   448             if return_type:
       
   449                 var_type = return_type.getcontent()
       
   450                 if var_type["name"] == "derived":
       
   451                     block_infos["outputs"].append(("", var_type["value"].getname(), "none"))
       
   452                 elif var_type["name"] in ["string", "wstring"]:
       
   453                     block_infos["outputs"].append(("", var_type["name"].upper(), "none"))
       
   454                 else:
       
   455                     block_infos["outputs"].append(("", var_type["name"], "none"))
       
   456             for type, varlist in pou.getvars():
       
   457                 if type == "InOut":
       
   458                     for var in varlist.getvariable():
       
   459                         var_type = var.type.getcontent()
       
   460                         if var_type["name"] == "derived":
       
   461                             block_infos["inputs"].append((var.getname(), var_type["value"].getname(), "none"))
       
   462                             block_infos["outputs"].append((var.getname(), var_type["value"].getname(), "none"))
       
   463                         elif var_type["name"] in ["string", "wstring"]:
       
   464                             block_infos["inputs"].append((var.getname(), var_type["name"].upper(), "none"))
       
   465                             block_infos["outputs"].append((var.getname(), var_type["name"].upper(), "none"))
       
   466                         else:
       
   467                             block_infos["inputs"].append((var.getname(), var_type["name"], "none"))
       
   468                             block_infos["outputs"].append((var.getname(), var_type["name"], "none"))
       
   469                 elif type == "Input":
       
   470                     for var in varlist.getvariable():
       
   471                         var_type = var.type.getcontent()
       
   472                         if var_type["name"] == "derived":
       
   473                             block_infos["inputs"].append((var.getname(), var_type["value"].getname(), "none"))
       
   474                         elif var_type["name"] in ["string", "wstring"]:
       
   475                             block_infos["inputs"].append((var.getname(), var_type["name"].upper(), "none"))
       
   476                         else:
       
   477                             block_infos["inputs"].append((var.getname(), var_type["name"], "none"))
       
   478                 elif type == "Output":
       
   479                     for var in varlist.getvariable():
       
   480                         var_type = var.type.getcontent()
       
   481                         if var_type["name"] == "derived":
       
   482                             block_infos["outputs"].append((var.getname(), var_type["value"].getname(), "none"))
       
   483                         elif var_type["name"] in ["string", "wstring"]:
       
   484                             block_infos["outputs"].append((var.getname(), var_type["name"].upper(), "none"))
       
   485                         else:
       
   486                             block_infos["outputs"].append((var.getname(), var_type["name"], "none"))    
       
   487         block_infos["usage"] = "\n (%s) => (%s)" % (", ".join(["%s:%s" % (input[1], input[0]) for input in block_infos["inputs"]]),
       
   488                                                     ", ".join(["%s:%s" % (output[1], output[0]) for output in block_infos["outputs"]]))
       
   489         self.CustomBlockTypes.append(block_infos)
       
   490     setattr(cls, "AddCustomBlockType", AddCustomBlockType)
       
   491 
       
   492     def RefreshElementUsingTree(self):
       
   493         # Reset the tree of user-defined element cross-use
       
   494         self.ElementUsingTree = {}
       
   495         pous = self.getpous()
       
   496         datatypes = self.getdataTypes()
       
   497         # Reference all the user-defined elementu names and initialize the tree of 
       
   498         # user-defined elemnt cross-use
       
   499         elementnames = [datatype.getname() for datatype in datatypes] + \
       
   500                        [pou.getname() for pou in pous]
       
   501         for name in elementnames:
       
   502             self.ElementUsingTree[name] = []
       
   503         # Analyze each datatype
       
   504         for datatype in datatypes:
       
   505             name = datatype.getname()
       
   506             basetype_content = datatype.baseType.getcontent()
       
   507             if basetype_content["name"] == "derived":
       
   508                 typename = basetype_content["value"].getname()
       
   509                 if name in self.ElementUsingTree[typename]:
       
   510                     self.ElementUsingTree[typename].append(name)
       
   511             elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned", "array"]:
       
   512                 base_type = basetype_content["value"].baseType.getcontent()
       
   513                 if base_type["name"] == "derived":
       
   514                     typename = base_type["value"].getname()
       
   515                     if self.ElementUsingTree.has_key(typename) and name not in self.ElementUsingTree[typename]:
       
   516                         self.ElementUsingTree[typename].append(name)
       
   517             elif basetype_content["name"] == "struct":
       
   518                 for element in basetype_content["value"].getvariable():
       
   519                     type_content = element.type.getcontent()
       
   520                     if type_content["name"] == "derived":
       
   521                         typename = type_content["value"].getname()
       
   522                         if self.ElementUsingTree.has_key(typename) and name not in self.ElementUsingTree[typename]:
       
   523                             self.ElementUsingTree[typename].append(name)
       
   524         # Analyze each pou
       
   525         for pou in pous:
       
   526             name = pou.getname()
       
   527             if pou.interface:
       
   528                 # Extract variables from every varLists
       
   529                 for type, varlist in pou.getvars():
       
   530                     for var in varlist.getvariable():
       
   531                         vartype_content = var.gettype().getcontent()
       
   532                         if vartype_content["name"] == "derived":
       
   533                             typename = vartype_content["value"].getname()
       
   534                             if self.ElementUsingTree.has_key(typename) and name not in self.ElementUsingTree[typename]:
       
   535                                 self.ElementUsingTree[typename].append(name)
       
   536     setattr(cls, "RefreshElementUsingTree", RefreshElementUsingTree)
       
   537 
       
   538     def GetParentType(self, type):
       
   539         if self.CustomTypeHierarchy.has_key(type):
       
   540             return self.CustomTypeHierarchy[type]
       
   541         elif TypeHierarchy.has_key(type):
       
   542             return TypeHierarchy[type]
       
   543         return None
       
   544     setattr(cls, "GetParentType", GetParentType)
       
   545 
       
   546     def GetBaseType(self, type):
       
   547         parent_type = self.GetParentType(type)
       
   548         if parent_type is not None:
       
   549             if parent_type.startswith("ANY"):
       
   550                 return type
       
   551             else:
       
   552                 return self.GetBaseType(parent_type)
       
   553         return None
       
   554     setattr(cls, "GetBaseType", GetBaseType)
       
   555 
       
   556     def GetSubrangeBaseTypes(self, exclude):
       
   557         derived = []
       
   558         for type in self.CustomTypeHierarchy.keys():
       
   559             for base_type in DataTypeRange.keys():
       
   560                 if self.IsOfType(type, base_type) and not self.IsOfType(type, exclude):
       
   561                     derived.append(type)
       
   562                     break
       
   563         return derived
       
   564     setattr(cls, "GetSubrangeBaseTypes", GetSubrangeBaseTypes)
       
   565 
       
   566     """
       
   567     returns true if the given data type is the same that "reference" meta-type or one of its types.
       
   568     """
       
   569     def IsOfType(self, type, reference):
       
   570         if reference is None:
       
   571             return True
       
   572         elif type == reference:
       
   573             return True
       
   574         else:
       
   575             parent_type = self.GetParentType(type)
       
   576             if parent_type is not None:
       
   577                 return self.IsOfType(parent_type, reference)
       
   578         return False
       
   579     setattr(cls, "IsOfType", IsOfType)
       
   580 
       
   581     # Return if pou given by name is used by another pou
       
   582     def ElementIsUsed(self, name):
       
   583         if self.ElementUsingTree.has_key(name):
       
   584             return len(self.ElementUsingTree[name]) > 0
       
   585         return False
       
   586     setattr(cls, "ElementIsUsed", ElementIsUsed)
       
   587 
       
   588     def DataTypeIsDerived(self, name):
       
   589         return name in self.CustomTypeHierarchy.values()
       
   590     setattr(cls, "DataTypeIsDerived", DataTypeIsDerived)
       
   591 
       
   592     # Return if pou given by name is directly or undirectly used by the reference pou
       
   593     def ElementIsUsedBy(self, name, reference):
       
   594         if self.ElementUsingTree.has_key(name):
       
   595             list = self.ElementUsingTree[name]
       
   596             # Test if pou is directly used by reference
       
   597             if reference in list:
       
   598                 return True
       
   599             else:
       
   600                 # Test if pou is undirectly used by reference, by testing if pous 
       
   601                 # that directly use pou is directly or undirectly used by reference
       
   602                 used = False
       
   603                 for element in list:
       
   604                     used |= self.ElementIsUsedBy(element, reference)
       
   605                 return used
       
   606         return False
       
   607     setattr(cls, "ElementIsUsedBy", ElementIsUsedBy)
       
   608 
       
   609     def GetDataTypeRange(self, type):
       
   610         if self.CustomDataTypeRange.has_key(type):
       
   611             return self.CustomDataTypeRange[type]
       
   612         elif DataTypeRange.has_key(type):
       
   613             return DataTypeRange[type]
       
   614         else:
       
   615             parent_type = self.GetParentType(type)
       
   616             if parent_type is not None:
       
   617                 return self.GetDataTypeRange(parent_type)
       
   618         return None
       
   619     setattr(cls, "GetDataTypeRange", GetDataTypeRange)
       
   620 
       
   621     def GetEnumeratedDataTypeValues(self, type = None):
       
   622         if type is None:
       
   623             all_values = []
       
   624             for values in self.EnumeratedDataTypeValues.values():
       
   625                 all_values.extend(values)
       
   626             return all_values
       
   627         elif self.EnumeratedDataTypeValues.has_key(type):
       
   628             return self.EnumeratedDataTypeValues[type]
       
   629         return []
       
   630     setattr(cls, "GetEnumeratedDataTypeValues", GetEnumeratedDataTypeValues)
       
   631 
       
   632     # Function that returns the block definition associated to the block type given
       
   633     def GetCustomBlockType(self, type, inputs = None):
       
   634         for customblocktype in self.CustomBlockTypes:
       
   635             if inputs is not None and inputs != "undefined":
       
   636                 customblock_inputs = tuple([var_type for name, var_type, modifier in customblocktype["inputs"]])
       
   637                 same_inputs = inputs == customblock_inputs
       
   638             else:
       
   639                 same_inputs = True
       
   640             if customblocktype["name"] == type and same_inputs:
       
   641                 return customblocktype
       
   642         return None
       
   643     setattr(cls, "GetCustomBlockType", GetCustomBlockType)
       
   644 
       
   645     # Return Block types checking for recursion
       
   646     def GetCustomBlockTypes(self, exclude = "", onlyfunctions = False):
       
   647         type = None
       
   648         if exclude != "":
       
   649             pou = self.getpou(exclude)
       
   650             if pou is not None:
       
   651                 type = pou.getpouType()
       
   652         customblocktypes = []
       
   653         for customblocktype in self.CustomBlockTypes:
       
   654             if customblocktype["type"] != "program" and customblocktype["name"] != exclude and not self.ElementIsUsedBy(exclude, customblocktype["name"]) and not (onlyfunctions and customblocktype["type"] != "function"):
       
   655                 customblocktypes.append(customblocktype)
       
   656         return customblocktypes
       
   657     setattr(cls, "GetCustomBlockTypes", GetCustomBlockTypes)
       
   658 
       
   659     # Return Function Block types checking for recursion
       
   660     def GetCustomFunctionBlockTypes(self, exclude = ""):
       
   661         customblocktypes = []
       
   662         for customblocktype in self.CustomBlockTypes:
       
   663             if customblocktype["type"] == "functionBlock" and customblocktype["name"] != exclude and not self.ElementIsUsedBy(exclude, customblocktype["name"]):
       
   664                 customblocktypes.append(customblocktype["name"])
       
   665         return customblocktypes
       
   666     setattr(cls, "GetCustomFunctionBlockTypes", GetCustomFunctionBlockTypes)
       
   667 
       
   668     # Return Block types checking for recursion
       
   669     def GetCustomBlockResource(self):
       
   670         customblocktypes = []
       
   671         for customblocktype in self.CustomBlockTypes:
       
   672             if customblocktype["type"] == "program":
       
   673                 customblocktypes.append(customblocktype["name"])
       
   674         return customblocktypes
       
   675     setattr(cls, "GetCustomBlockResource", GetCustomBlockResource)
       
   676 
       
   677     # Return Data Types checking for recursion
       
   678     def GetCustomDataTypes(self, exclude = "", only_locatable = False):
       
   679         customdatatypes = []
       
   680         for customdatatype in self.getdataTypes():
       
   681             if not only_locatable or self.IsLocatableType(customdatatype):
       
   682                 customdatatype_name = customdatatype.getname()
       
   683                 if customdatatype_name != exclude and not self.ElementIsUsedBy(exclude, customdatatype_name):
       
   684                     customdatatypes.append({"name": customdatatype_name, "infos": customdatatype})
       
   685         return customdatatypes
       
   686     setattr(cls, "GetCustomDataTypes", GetCustomDataTypes)
       
   687 
       
   688     # Return if Data Type can be used for located variables
       
   689     def IsLocatableType(self, datatype):
       
   690         basetype_content = datatype.baseType.getcontent()
       
   691         if basetype_content["name"] in ["enum", "struct"]:
       
   692             return False
       
   693         elif basetype_content["name"] == "derived":
       
   694             base_type = self.getdataType(basetype_content["value"].getname())
       
   695             if base_type is not None:
       
   696                 return self.IsLocatableType(base_type)
       
   697         elif basetype_content["name"] == "array":
       
   698             array_base_type = basetype_content["value"].baseType.getcontent()
       
   699             if array_base_type["value"] is not None and array_base_type["name"] not in ["string", "wstring"]:
       
   700                 base_type = self.getdataType(array_base_type["value"].getname())
       
   701                 if base_type is not None:
       
   702                     return self.IsLocatableType(base_type)
       
   703         return True
       
   704     setattr(cls, "IsLocatableType", IsLocatableType)
       
   705 
       
   706     def Search(self, criteria, parent_infos=[]):
       
   707         result = self.types.Search(criteria, parent_infos)
       
   708         for configuration in self.instances.configurations.getconfiguration():
       
   709             result.extend(configuration.Search(criteria, parent_infos))
       
   710         return result
       
   711     setattr(cls, "Search", Search)
       
   712 
       
   713 cls = PLCOpenClasses.get("project_fileHeader", None)
       
   714 if cls:
       
   715     cls.singleLineAttributes = False
       
   716 
       
   717 cls = PLCOpenClasses.get("project_contentHeader", None)
       
   718 if cls:
       
   719     cls.singleLineAttributes = False
       
   720     
       
   721     def setpageSize(self, width, height):
       
   722         self.coordinateInfo.setpageSize(width, height)
       
   723     setattr(cls, "setpageSize", setpageSize)
       
   724     
       
   725     def getpageSize(self):
       
   726         return self.coordinateInfo.getpageSize()
       
   727     setattr(cls, "getpageSize", getpageSize)
       
   728 
       
   729     def setscaling(self, scaling):
       
   730         for language, (x, y) in scaling.items():
       
   731             self.coordinateInfo.setscaling(language, x, y)
       
   732     setattr(cls, "setscaling", setscaling)
       
   733     
       
   734     def getscaling(self):
       
   735         scaling = {}
       
   736         scaling["FBD"] = self.coordinateInfo.getscaling("FBD")
       
   737         scaling["LD"] = self.coordinateInfo.getscaling("LD")
       
   738         scaling["SFC"] = self.coordinateInfo.getscaling("SFC")
       
   739         return scaling
       
   740     setattr(cls, "getscaling", getscaling)
       
   741 
       
   742 cls = PLCOpenClasses.get("contentHeader_coordinateInfo", None)
       
   743 if cls:
       
   744     def setpageSize(self, width, height):
       
   745         if width == 0 and height == 0:
       
   746             self.deletepageSize()
       
   747         else:
       
   748             if self.pageSize is None:
       
   749                 self.addpageSize()
       
   750             self.pageSize.setx(width)
       
   751             self.pageSize.sety(height)
       
   752     setattr(cls, "setpageSize", setpageSize)
       
   753     
       
   754     def getpageSize(self):
       
   755         if self.pageSize is not None:
       
   756             return self.pageSize.getx(), self.pageSize.gety()
       
   757         return 0, 0
       
   758     setattr(cls, "getpageSize", getpageSize)
       
   759 
       
   760     def setscaling(self, language, x, y):
       
   761         if language == "FBD":
       
   762             self.fbd.scaling.setx(x)
       
   763             self.fbd.scaling.sety(y)
       
   764         elif language == "LD":
       
   765             self.ld.scaling.setx(x)
       
   766             self.ld.scaling.sety(y)
       
   767         elif language == "SFC":
       
   768             self.sfc.scaling.setx(x)
       
   769             self.sfc.scaling.sety(y)
       
   770     setattr(cls, "setscaling", setscaling)
       
   771     
       
   772     def getscaling(self, language):
       
   773         if language == "FBD":
       
   774             return self.fbd.scaling.getx(), self.fbd.scaling.gety()
       
   775         elif language == "LD":
       
   776             return self.ld.scaling.getx(), self.ld.scaling.gety()
       
   777         elif language == "SFC":
       
   778             return self.sfc.scaling.getx(), self.sfc.scaling.gety()
       
   779         return 0, 0
       
   780     setattr(cls, "getscaling", getscaling)
       
   781 
       
   782 def _Search(attributes, criteria, parent_infos):
       
   783     search_result = []
       
   784     for attr, value in attributes:
       
   785         if value is not None:
       
   786             search_result.extend([(tuple(parent_infos + [attr]),) + result for result in TestTextElement(value, criteria)])
       
   787     return search_result
       
   788 
       
   789 def _updateConfigurationResourceElementName(self, old_name, new_name):
       
   790     for varlist in self.getglobalVars():
       
   791         for var in varlist.getvariable():
       
   792             var_address = var.getaddress()
       
   793             if var_address is not None:
       
   794                 if var_address == old_name:
       
   795                     var.setaddress(new_name)
       
   796                 if var.getname() == old_name:
       
   797                     var.setname(new_name)
       
   798 
       
   799 def _updateConfigurationResourceElementAddress(self, address_model, new_leading):
       
   800     for varlist in self.getglobalVars():
       
   801         for var in varlist.getvariable():
       
   802             var_address = var.getaddress()
       
   803             if var_address is not None:
       
   804                 var.setaddress(update_address(var_address, address_model, new_leading))
       
   805 
       
   806 def _removeConfigurationResourceVariableByAddress(self, address):
       
   807     for varlist in self.getglobalVars():
       
   808         variables = varlist.getvariable()
       
   809         for i in xrange(len(variables)-1, -1, -1):
       
   810             if variables[i].getaddress() == address:
       
   811                 variables.pop(i)
       
   812 
       
   813 def _removeConfigurationResourceVariableByFilter(self, address_model):
       
   814     for varlist in self.getglobalVars():
       
   815         variables = varlist.getvariable()
       
   816         for i in xrange(len(variables)-1, -1, -1):
       
   817             var_address = variables[i].getaddress()
       
   818             if var_address is not None:
       
   819                 result = address_model.match(var_address)
       
   820                 if result is not None:
       
   821                     variables.pop(i)
       
   822 
       
   823 def _SearchInConfigurationResource(self, criteria, parent_infos=[]):
       
   824     search_result = _Search([("name", self.getname())], criteria, parent_infos)
       
   825     var_number = 0
       
   826     for varlist in self.getglobalVars():
       
   827         variable_type = searchResultVarTypes.get("globalVars", "var_local")
       
   828         variables = varlist.getvariable()
       
   829         for modifier, has_modifier in [("constant", varlist.getconstant()),
       
   830                                        ("retain", varlist.getretain()),
       
   831                                        ("non_retain", varlist.getnonretain())]:
       
   832             if has_modifier:
       
   833                 for result in TestTextElement(modifier, criteria):
       
   834                     search_result.append((tuple(parent_infos + [variable_type, (var_number, var_number + len(variables)), modifier]),) + result)
       
   835                 break
       
   836         for variable in variables:
       
   837             search_result.extend(variable.Search(criteria, parent_infos + [variable_type, var_number]))
       
   838             var_number += 1
       
   839     return search_result
       
   840 
       
   841 cls = PLCOpenClasses.get("configurations_configuration", None)
       
   842 if cls:
       
   843     def updateElementName(self, old_name, new_name):
       
   844         _updateConfigurationResourceElementName(self, old_name, new_name)
       
   845         for resource in self.getresource():
       
   846             resource.updateElementName(old_name, new_name)
       
   847     setattr(cls, "updateElementName", updateElementName)
       
   848 
       
   849     def updateElementAddress(self, address_model, new_leading):
       
   850         _updateConfigurationResourceElementAddress(self, address_model, new_leading)
       
   851         for resource in self.getresource():
       
   852             resource.updateElementAddress(address_model, new_leading)
       
   853     setattr(cls, "updateElementAddress", updateElementAddress)
       
   854 
       
   855     setattr(cls, "removeVariableByAddress", _removeConfigurationResourceVariableByAddress)
       
   856     setattr(cls, "removeVariableByFilter", _removeConfigurationResourceVariableByFilter)
       
   857 
       
   858     def Search(self, criteria, parent_infos=[]):
       
   859         search_result = []
       
   860         parent_infos = parent_infos + ["C::%s" % self.getname()]
       
   861         filter = criteria["filter"]
       
   862         if filter == "all" or "configuration" in filter:
       
   863             search_result = _SearchInConfigurationResource(self, criteria, parent_infos)
       
   864             for resource in self.getresource():
       
   865                 search_result.extend(resource.Search(criteria, parent_infos))
       
   866         return search_result
       
   867     setattr(cls, "Search", Search)
       
   868     
       
   869 cls = PLCOpenClasses.get("configuration_resource", None)
       
   870 if cls:
       
   871     def updateElementName(self, old_name, new_name):
       
   872         _updateConfigurationResourceElementName(self, old_name, new_name)
       
   873         for instance in self.getpouInstance():
       
   874             instance.updateElementName(old_name, new_name)
       
   875         for task in self.gettask():
       
   876             task.updateElementName(old_name, new_name)
       
   877     setattr(cls, "updateElementName", updateElementName)
       
   878 
       
   879     def updateElementAddress(self, address_model, new_leading):
       
   880         _updateConfigurationResourceElementAddress(self, address_model, new_leading)
       
   881         for task in self.gettask():
       
   882             task.updateElementAddress(address_model, new_leading)
       
   883     setattr(cls, "updateElementAddress", updateElementAddress)
       
   884 
       
   885     setattr(cls, "removeVariableByAddress", _removeConfigurationResourceVariableByAddress)
       
   886     setattr(cls, "removeVariableByFilter", _removeConfigurationResourceVariableByFilter)
       
   887 
       
   888     def Search(self, criteria, parent_infos=[]):
       
   889         parent_infos = parent_infos[:-1] + ["R::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())]
       
   890         search_result = _SearchInConfigurationResource(self, criteria, parent_infos)
       
   891         task_number = 0
       
   892         instance_number = 0
       
   893         for task in self.gettask():
       
   894             results = TestTextElement(task.getname(), criteria)
       
   895             for result in results:
       
   896                 search_result.append((tuple(parent_infos + ["task", task_number, "name"]),) + result)
       
   897             search_result.extend(task.Search(criteria, parent_infos + ["task", task_number]))
       
   898             task_number += 1
       
   899             for instance in task.getpouInstance():
       
   900                 search_result.extend(task.Search(criteria, parent_infos + ["instance", instance_number]))
       
   901                 for result in results:
       
   902                     search_result.append((tuple(parent_infos + ["instance", instance_number, "task"]),) + result)
       
   903                 instance_number += 1
       
   904         for instance in self.getpouInstance():
       
   905             search_result.extend(instance.Search(criteria, parent_infos + ["instance", instance_number]))
       
   906             instance_number += 1
       
   907         return search_result
       
   908     setattr(cls, "Search", Search)
       
   909 
       
   910 cls = PLCOpenClasses.get("resource_task", None)
       
   911 if cls:
       
   912     def compatibility(self, tree):
       
   913         if tree.hasAttribute("interval"):
       
   914             interval = GetAttributeValue(tree._attrs["interval"])
       
   915             result = time_model.match(interval)
       
   916             if result is not None:
       
   917                 values = result.groups()
       
   918                 time_values = [int(v) for v in values[:2]]
       
   919                 seconds = float(values[2])
       
   920                 time_values.extend([int(seconds), int((seconds % 1) * 1000000)])
       
   921                 text = "t#"
       
   922                 if time_values[0] != 0:
       
   923                     text += "%dh"%time_values[0]
       
   924                 if time_values[1] != 0:
       
   925                     text += "%dm"%time_values[1]
       
   926                 if time_values[2] != 0:
       
   927                     text += "%ds"%time_values[2]
       
   928                 if time_values[3] != 0:
       
   929                     if time_values[3] % 1000 != 0:
       
   930                         text += "%.3fms"%(float(time_values[3]) / 1000)
       
   931                     else:
       
   932                         text += "%dms"%(time_values[3] / 1000)
       
   933                 NodeSetAttr(tree, "interval", text)
       
   934     setattr(cls, "compatibility", compatibility)
       
   935     
       
   936     def updateElementName(self, old_name, new_name):
       
   937         if self.single == old_name:
       
   938             self.single = new_name
       
   939         if self.interval == old_name:
       
   940             self.interval = new_name
       
   941         for instance in self.getpouInstance():
       
   942             instance.updateElementName(old_name, new_name)
       
   943     setattr(cls, "updateElementName", updateElementName)
       
   944 
       
   945     def updateElementAddress(self, address_model, new_leading):
       
   946         if self.single is not None:
       
   947             self.single = update_address(self.single, address_model, new_leading)
       
   948         if self.interval is not None:
       
   949             self.interval = update_address(self.interval, address_model, new_leading)
       
   950     setattr(cls, "updateElementAddress", updateElementAddress)
       
   951 
       
   952     def Search(self, criteria, parent_infos=[]):
       
   953         return _Search([("single", self.getsingle()), 
       
   954                         ("interval", self.getinterval()),
       
   955                         ("priority", str(self.getpriority()))],
       
   956                        criteria, parent_infos)
       
   957     setattr(cls, "Search", Search)
       
   958 
       
   959 cls = PLCOpenClasses.get("pouInstance", None)
       
   960 if cls:
       
   961     def compatibility(self, tree):
       
   962         if tree.hasAttribute("type"):
       
   963             NodeRenameAttr(tree, "type", "typeName")
       
   964     setattr(cls, "compatibility", compatibility)
       
   965     
       
   966     def updateElementName(self, old_name, new_name):
       
   967         if self.typeName == old_name:
       
   968             self.typeName = new_name
       
   969     setattr(cls, "updateElementName", updateElementName)
       
   970 
       
   971     def Search(self, criteria, parent_infos=[]):
       
   972         return _Search([("name", self.getname()), 
       
   973                         ("type", self.gettypeName())],
       
   974                        criteria, parent_infos)
       
   975     setattr(cls, "Search", Search)
       
   976 
       
   977 cls = PLCOpenClasses.get("varListPlain_variable", None)
       
   978 if cls:
       
   979     def gettypeAsText(self):
       
   980         vartype_content = self.gettype().getcontent()
       
   981         # Variable type is a user data type
       
   982         if vartype_content["name"] == "derived":
       
   983             return vartype_content["value"].getname()
       
   984         # Variable type is a string type
       
   985         elif vartype_content["name"] in ["string", "wstring"]:
       
   986             return vartype_content["name"].upper()
       
   987         # Variable type is an array
       
   988         elif vartype_content["name"] == "array":
       
   989             base_type = vartype_content["value"].baseType.getcontent()
       
   990             # Array derived directly from a user defined type 
       
   991             if base_type["name"] == "derived":
       
   992                 basetype_name = base_type["value"].getname()
       
   993             # Array derived directly from a string type 
       
   994             elif base_type["name"] in ["string", "wstring"]:
       
   995                 basetype_name = base_type["name"].upper()
       
   996             # Array derived directly from an elementary type 
       
   997             else:
       
   998                 basetype_name = base_type["name"]
       
   999             return "ARRAY [%s] OF %s" % (",".join(map(lambda x : "%s..%s" % (x.getlower(), x.getupper()), vartype_content["value"].getdimension())), basetype_name)
       
  1000         # Variable type is an elementary type
       
  1001         return vartype_content["name"]
       
  1002     setattr(cls, "gettypeAsText", gettypeAsText)
       
  1003     
       
  1004     def Search(self, criteria, parent_infos=[]):
       
  1005         search_result = _Search([("name", self.getname()), 
       
  1006                                  ("type", self.gettypeAsText()),
       
  1007                                  ("location", self.getaddress())],
       
  1008                                 criteria, parent_infos)
       
  1009         initial = self.getinitialValue()
       
  1010         if initial is not None:
       
  1011             search_result.extend(_Search([("initial value", initial.getvalue())], criteria, parent_infos))
       
  1012         doc = self.getdocumentation()
       
  1013         if doc is not None:
       
  1014             search_result.extend(doc.Search(criteria, parent_infos + ["documentation"]))
       
  1015         return search_result
       
  1016     setattr(cls, "Search", Search)
       
  1017 
       
  1018 cls = PLCOpenClasses.get("project_types", None)
       
  1019 if cls:
       
  1020     def getdataTypeElements(self):
       
  1021         return self.dataTypes.getdataType()
       
  1022     setattr(cls, "getdataTypeElements", getdataTypeElements)
       
  1023     
       
  1024     def getdataTypeElement(self, name):
       
  1025         elements = self.dataTypes.getdataType()
       
  1026         for element in elements:
       
  1027             if element.getname() == name:
       
  1028                 return element
       
  1029         return None
       
  1030     setattr(cls, "getdataTypeElement", getdataTypeElement)
       
  1031 
       
  1032     def appenddataTypeElement(self, name):
       
  1033         new_datatype = PLCOpenClasses["dataTypes_dataType"]()
       
  1034         new_datatype.setname(name)
       
  1035         new_datatype.baseType.setcontent({"name" : "BOOL", "value" : None})
       
  1036         self.dataTypes.appenddataType(new_datatype)
       
  1037     setattr(cls, "appenddataTypeElement", appenddataTypeElement)
       
  1038     
       
  1039     def insertdataTypeElement(self, index, dataType):
       
  1040         self.dataTypes.insertdataType(index, dataType)
       
  1041     setattr(cls, "insertdataTypeElement", insertdataTypeElement)
       
  1042     
       
  1043     def removedataTypeElement(self, name):
       
  1044         found = False
       
  1045         for idx, element in enumerate(self.dataTypes.getdataType()):
       
  1046             if element.getname() == name:
       
  1047                 self.dataTypes.removedataType(idx)
       
  1048                 found = True
       
  1049                 break
       
  1050         if not found:
       
  1051             raise ValueError, _("\"%s\" Data Type doesn't exist !!!")%name
       
  1052     setattr(cls, "removedataTypeElement", removedataTypeElement)
       
  1053     
       
  1054     def getpouElements(self):
       
  1055         return self.pous.getpou()
       
  1056     setattr(cls, "getpouElements", getpouElements)
       
  1057     
       
  1058     def getpouElement(self, name):
       
  1059         elements = self.pous.getpou()
       
  1060         for element in elements:
       
  1061             if element.getname() == name:
       
  1062                 return element
       
  1063         return None
       
  1064     setattr(cls, "getpouElement", getpouElement)
       
  1065 
       
  1066     def appendpouElement(self, name, pou_type, body_type):
       
  1067         for element in self.pous.getpou():
       
  1068             if element.getname() == name:
       
  1069                 raise ValueError, _("\"%s\" POU already exists !!!")%name
       
  1070         new_pou = PLCOpenClasses["pous_pou"]()
       
  1071         new_pou.setname(name)
       
  1072         new_pou.setpouType(pou_type)
       
  1073         new_pou.appendbody(PLCOpenClasses["body"]())
       
  1074         new_pou.setbodyType(body_type)
       
  1075         self.pous.appendpou(new_pou)
       
  1076     setattr(cls, "appendpouElement", appendpouElement)
       
  1077         
       
  1078     def insertpouElement(self, index, pou):
       
  1079         self.pous.insertpou(index, pou)
       
  1080     setattr(cls, "insertpouElement", insertpouElement)
       
  1081     
       
  1082     def removepouElement(self, name):
       
  1083         found = False
       
  1084         for idx, element in enumerate(self.pous.getpou()):
       
  1085             if element.getname() == name:
       
  1086                 self.pous.removepou(idx)
       
  1087                 found = True
       
  1088                 break
       
  1089         if not found:
       
  1090             raise ValueError, _("\"%s\" POU doesn't exist !!!")%name
       
  1091     setattr(cls, "removepouElement", removepouElement)
       
  1092 
       
  1093     def Search(self, criteria, parent_infos=[]):
       
  1094         search_result = []
       
  1095         filter = criteria["filter"]
       
  1096         for datatype in self.dataTypes.getdataType():
       
  1097             search_result.extend(datatype.Search(criteria, parent_infos))
       
  1098         for pou in self.pous.getpou():
       
  1099             search_result.extend(pou.Search(criteria, parent_infos))
       
  1100         return search_result
       
  1101     setattr(cls, "Search", Search)
       
  1102 
       
  1103 def _updateBaseTypeElementName(self, old_name, new_name):
       
  1104     self.baseType.updateElementName(old_name, new_name)
       
  1105 
       
  1106 cls = PLCOpenClasses.get("dataTypes_dataType", None)
       
  1107 if cls:
       
  1108     setattr(cls, "updateElementName", _updateBaseTypeElementName)
       
  1109     
       
  1110     def Search(self, criteria, parent_infos=[]):
       
  1111         search_result = []
       
  1112         filter = criteria["filter"]
       
  1113         if filter == "all" or "datatype" in filter:
       
  1114             parent_infos = parent_infos + ["D::%s" % self.getname()]
       
  1115             search_result.extend(_Search([("name", self.getname())], criteria, parent_infos))
       
  1116             search_result.extend(self.baseType.Search(criteria, parent_infos))
       
  1117             if self.initialValue is not None:
       
  1118                 search_result.extend(_Search([("initial", self.initialValue.getvalue())], criteria, parent_infos))
       
  1119         return search_result
       
  1120     setattr(cls, "Search", Search)
       
  1121 
       
  1122 cls = PLCOpenClasses.get("dataType", None)
       
  1123 if cls:
       
  1124     
       
  1125     def updateElementName(self, old_name, new_name):
       
  1126         if self.content["name"] in ["derived", "array", "subrangeSigned", "subrangeUnsigned"]:
       
  1127             self.content["value"].updateElementName(old_name, new_name)
       
  1128         elif self.content["name"] == "struct":
       
  1129             for element in self.content["value"].getvariable():
       
  1130                 element_type = element.type.updateElementName(old_name, new_name)
       
  1131     setattr(cls, "updateElementName", updateElementName)
       
  1132 
       
  1133     def Search(self, criteria, parent_infos=[]):
       
  1134         search_result = []
       
  1135         if self.content["name"] in ["derived", "array", "enum", "subrangeSigned", "subrangeUnsigned"]:
       
  1136             search_result.extend(self.content["value"].Search(criteria, parent_infos))
       
  1137         elif self.content["name"] == "struct":
       
  1138             for i, element in enumerate(self.content["value"].getvariable()):
       
  1139                 search_result.extend(element.Search(criteria, parent_infos + ["struct", i]))
       
  1140         else:
       
  1141             basetype = self.content["name"]
       
  1142             if basetype in ["string", "wstring"]:
       
  1143                 basetype = basetype.upper()
       
  1144             search_result.extend(_Search([("base", basetype)], criteria, parent_infos))
       
  1145         return search_result
       
  1146     setattr(cls, "Search", Search)
       
  1147 
       
  1148 cls = PLCOpenClasses.get("derivedTypes_array", None)
       
  1149 if cls:
       
  1150     setattr(cls, "updateElementName", _updateBaseTypeElementName)
       
  1151     
       
  1152     def Search(self, criteria, parent_infos=[]):
       
  1153         search_result = self.baseType.Search(criteria, parent_infos)
       
  1154         for i, dimension in enumerate(self.getdimension()):
       
  1155             search_result.extend(_Search([("lower", dimension.getlower()),
       
  1156                                           ("upper", dimension.getupper())],
       
  1157                                          criteria, parent_infos + ["range", i]))
       
  1158         return search_result
       
  1159     setattr(cls, "Search", Search)
       
  1160 
       
  1161 def _SearchInSubrange(self, criteria, parent_infos=[]):
       
  1162     search_result = self.baseType.Search(criteria, parent_infos)
       
  1163     search_result.extend(_Search([("lower", self.range.getlower()),
       
  1164                                   ("upper", self.range.getupper())],
       
  1165                                  criteria, parent_infos))
       
  1166     return search_result
       
  1167 
       
  1168 cls = PLCOpenClasses.get("derivedTypes_subrangeSigned", None)
       
  1169 if cls:
       
  1170     setattr(cls, "updateElementName", _updateBaseTypeElementName)
       
  1171     setattr(cls, "Search", _SearchInSubrange)
       
  1172 
       
  1173 cls = PLCOpenClasses.get("derivedTypes_subrangeUnsigned", None)
       
  1174 if cls:
       
  1175     setattr(cls, "updateElementName", _updateBaseTypeElementName)
       
  1176     setattr(cls, "Search", _SearchInSubrange)
       
  1177 
       
  1178 cls = PLCOpenClasses.get("derivedTypes_enum", None)
       
  1179 if cls:
       
  1180     
       
  1181     def updateElementName(self, old_name, new_name):
       
  1182         pass
       
  1183     setattr(cls, "updateElementName", updateElementName)
       
  1184     
       
  1185     def Search(self, criteria, parent_infos=[]):
       
  1186         search_result = []
       
  1187         for i, value in enumerate(self.values.getvalue()):
       
  1188             for result in TestTextElement(value.getname(), criteria):
       
  1189                 search_result.append((tuple(parent_infos + ["value", i]),) + result)
       
  1190         return search_result
       
  1191     setattr(cls, "Search", Search)
       
  1192 
       
  1193 cls = PLCOpenClasses.get("pous_pou", None)
       
  1194 if cls:
       
  1195     
       
  1196     def setdescription(self, description):
       
  1197         doc = self.getdocumentation()
       
  1198         if doc is None:
       
  1199             doc = PLCOpenClasses["formattedText"]()
       
  1200             self.setdocumentation(doc)
       
  1201         doc.settext(description)
       
  1202     setattr(cls, "setdescription", setdescription)
       
  1203     
       
  1204     def getdescription(self):
       
  1205         doc = self.getdocumentation()
       
  1206         if doc is not None:
       
  1207             return doc.gettext()
       
  1208         return ""
       
  1209     setattr(cls, "getdescription", getdescription)
       
  1210     
       
  1211     def setbodyType(self, type):
       
  1212         if len(self.body) > 0:
       
  1213             if type == "IL":
       
  1214                 self.body[0].setcontent({"name" : "IL", "value" : PLCOpenClasses["formattedText"]()})
       
  1215             elif type == "ST":
       
  1216                 self.body[0].setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
       
  1217             elif type == "LD":
       
  1218                 self.body[0].setcontent({"name" : "LD", "value" : PLCOpenClasses["body_LD"]()})
       
  1219             elif type == "FBD":
       
  1220                 self.body[0].setcontent({"name" : "FBD", "value" : PLCOpenClasses["body_FBD"]()})
       
  1221             elif type == "SFC":
       
  1222                 self.body[0].setcontent({"name" : "SFC", "value" : PLCOpenClasses["body_SFC"]()})
       
  1223             else:
       
  1224                 raise ValueError, "%s isn't a valid body type!"%type
       
  1225     setattr(cls, "setbodyType", setbodyType)
       
  1226     
       
  1227     def getbodyType(self):
       
  1228         if len(self.body) > 0:
       
  1229             return self.body[0].getcontent()["name"]
       
  1230     setattr(cls, "getbodyType", getbodyType)
       
  1231     
       
  1232     def resetexecutionOrder(self):
       
  1233         if len(self.body) > 0:
       
  1234             self.body[0].resetexecutionOrder()
       
  1235     setattr(cls, "resetexecutionOrder", resetexecutionOrder)
       
  1236     
       
  1237     def compileexecutionOrder(self):
       
  1238         if len(self.body) > 0:
       
  1239             self.body[0].compileexecutionOrder()
       
  1240     setattr(cls, "compileexecutionOrder", compileexecutionOrder)
       
  1241     
       
  1242     def setelementExecutionOrder(self, instance, new_executionOrder):
       
  1243         if len(self.body) > 0:
       
  1244             self.body[0].setelementExecutionOrder(instance, new_executionOrder)
       
  1245     setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
       
  1246     
       
  1247     def addinstance(self, name, instance):
       
  1248         if len(self.body) > 0:
       
  1249             self.body[0].appendcontentInstance(name, instance)
       
  1250     setattr(cls, "addinstance", addinstance)
       
  1251     
       
  1252     def getinstances(self):
       
  1253         if len(self.body) > 0:
       
  1254             return self.body[0].getcontentInstances()
       
  1255         return []
       
  1256     setattr(cls, "getinstances", getinstances)
       
  1257     
       
  1258     def getinstance(self, id):
       
  1259         if len(self.body) > 0:
       
  1260             return self.body[0].getcontentInstance(id)
       
  1261         return None
       
  1262     setattr(cls, "getinstance", getinstance)
       
  1263     
       
  1264     def getrandomInstance(self, exclude):
       
  1265         if len(self.body) > 0:
       
  1266             return self.body[0].getcontentRandomInstance(exclude)
       
  1267         return None
       
  1268     setattr(cls, "getrandomInstance", getrandomInstance)
       
  1269     
       
  1270     def getinstanceByName(self, name):
       
  1271         if len(self.body) > 0:
       
  1272             return self.body[0].getcontentInstanceByName(name)
       
  1273         return None
       
  1274     setattr(cls, "getinstanceByName", getinstanceByName)
       
  1275     
       
  1276     def removeinstance(self, id):
       
  1277         if len(self.body) > 0:
       
  1278             self.body[0].removecontentInstance(id)
       
  1279     setattr(cls, "removeinstance", removeinstance)
       
  1280     
       
  1281     def settext(self, text):
       
  1282         if len(self.body) > 0:
       
  1283             self.body[0].settext(text)
       
  1284     setattr(cls, "settext", settext)
       
  1285     
       
  1286     def gettext(self):
       
  1287         if len(self.body) > 0:
       
  1288             return self.body[0].gettext()
       
  1289         return ""
       
  1290     setattr(cls, "gettext", gettext)
       
  1291 
       
  1292     def getvars(self):
       
  1293         vars = []
       
  1294         if self.interface is not None:
       
  1295             reverse_types = {}
       
  1296             for name, value in VarTypes.items():
       
  1297                 reverse_types[value] = name
       
  1298             for varlist in self.interface.getcontent():
       
  1299                 vars.append((reverse_types[varlist["name"]], varlist["value"]))
       
  1300         return vars
       
  1301     setattr(cls, "getvars", getvars)
       
  1302     
       
  1303     def setvars(self, vars):
       
  1304         if self.interface is None:
       
  1305             self.interface = PLCOpenClasses["pou_interface"]()
       
  1306         self.interface.setcontent([])
       
  1307         for vartype, varlist in vars:
       
  1308             self.interface.appendcontent({"name" : VarTypes[vartype], "value" : varlist})
       
  1309     setattr(cls, "setvars", setvars)
       
  1310     
       
  1311     def addpouLocalVar(self, type, name, location="", description=""):
       
  1312         self.addpouVar(type, name, location=location, description=description)
       
  1313     setattr(cls, "addpouLocalVar", addpouLocalVar)
       
  1314         
       
  1315     def addpouExternalVar(self, type, name):
       
  1316         self.addpouVar(type, name, "externalVars")
       
  1317     setattr(cls, "addpouExternalVar", addpouExternalVar)
       
  1318     
       
  1319     def addpouVar(self, type, name, var_class="localVars", location="", description=""):
       
  1320         if self.interface is None:
       
  1321             self.interface = PLCOpenClasses["pou_interface"]()
       
  1322         content = self.interface.getcontent()
       
  1323         if len(content) == 0 or content[-1]["name"] != var_class:
       
  1324             content.append({"name" : var_class, "value" : PLCOpenClasses["interface_%s" % var_class]()})
       
  1325         else:
       
  1326             varlist = content[-1]["value"]
       
  1327             variables = varlist.getvariable()
       
  1328             if varlist.getconstant() or varlist.getretain() or len(variables) > 0 and variables[0].getaddress():
       
  1329                 content.append({"name" : var_class, "value" : PLCOpenClasses["interface_%s" % var_class]()})
       
  1330         var = PLCOpenClasses["varListPlain_variable"]()
       
  1331         var.setname(name)
       
  1332         var_type = PLCOpenClasses["dataType"]()
       
  1333         if type in [x for x,y in TypeHierarchy_list if not x.startswith("ANY")]:
       
  1334             if type == "STRING":
       
  1335                 var_type.setcontent({"name" : "string", "value" : PLCOpenClasses["elementaryTypes_string"]()})
       
  1336             elif type == "WSTRING":
       
  1337                 var_type.setcontent({"name" : "wstring", "value" : PLCOpenClasses["elementaryTypes_wstring"]()})
       
  1338             else:
       
  1339                 var_type.setcontent({"name" : type, "value" : None})
       
  1340         else:
       
  1341             derived_type = PLCOpenClasses["derivedTypes_derived"]()
       
  1342             derived_type.setname(type)
       
  1343             var_type.setcontent({"name" : "derived", "value" : derived_type})
       
  1344         var.settype(var_type)
       
  1345         if location != "":
       
  1346             var.setaddress(location)
       
  1347         if description != "":
       
  1348             ft = PLCOpenClasses["formattedText"]()
       
  1349             ft.settext(description)
       
  1350             var.setdocumentation(ft)
       
  1351         
       
  1352         content[-1]["value"].appendvariable(var)
       
  1353     setattr(cls, "addpouVar", addpouVar)
       
  1354     
       
  1355     def changepouVar(self, old_type, old_name, new_type, new_name):
       
  1356         if self.interface is not None:
       
  1357             content = self.interface.getcontent()
       
  1358             for varlist in content:
       
  1359                 variables = varlist["value"].getvariable()
       
  1360                 for var in variables:
       
  1361                     if var.getname() == old_name:
       
  1362                         vartype_content = var.gettype().getcontent()
       
  1363                         if vartype_content["name"] == "derived" and vartype_content["value"].getname() == old_type:
       
  1364                             var.setname(new_name)
       
  1365                             vartype_content["value"].setname(new_type)
       
  1366                             return
       
  1367     setattr(cls, "changepouVar", changepouVar)
       
  1368     
       
  1369     def removepouVar(self, type, name):
       
  1370         if self.interface is not None:
       
  1371             content = self.interface.getcontent()
       
  1372             for varlist in content:
       
  1373                 variables = varlist["value"].getvariable()
       
  1374                 for var in variables:
       
  1375                     if var.getname() == name:
       
  1376                         vartype_content = var.gettype().getcontent()
       
  1377                         if vartype_content["name"] == "derived" and vartype_content["value"].getname() == type:
       
  1378                             variables.remove(var)
       
  1379                             break
       
  1380                 if len(varlist["value"].getvariable()) == 0:
       
  1381                     content.remove(varlist)
       
  1382                     break
       
  1383     setattr(cls, "removepouVar", removepouVar)
       
  1384     
       
  1385     def hasblock(self, name):
       
  1386         if self.getbodyType() in ["FBD", "LD", "SFC"]:
       
  1387             for instance in self.getinstances():
       
  1388                 if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
       
  1389                     return True
       
  1390             if self.transitions:
       
  1391                 for transition in self.transitions.gettransition():
       
  1392                     result = transition.hasblock(name)
       
  1393                     if result:
       
  1394                         return result
       
  1395             if self.actions:
       
  1396                 for action in self.actions.getaction():
       
  1397                     result = action.hasblock(name)
       
  1398                     if result:
       
  1399                         return result
       
  1400         return False
       
  1401     setattr(cls, "hasblock", hasblock)
       
  1402     
       
  1403     def addtransition(self, name, type):
       
  1404         if not self.transitions:
       
  1405             self.addtransitions()
       
  1406             self.transitions.settransition([])
       
  1407         transition = PLCOpenClasses["transitions_transition"]()
       
  1408         transition.setname(name)
       
  1409         transition.setbodyType(type)
       
  1410         if type == "ST":
       
  1411             transition.settext(":= ;")
       
  1412         elif type == "IL":
       
  1413             transition.settext("\tST\t%s"%name)
       
  1414         self.transitions.appendtransition(transition)
       
  1415     setattr(cls, "addtransition", addtransition)
       
  1416     
       
  1417     def gettransition(self, name):
       
  1418         if self.transitions:
       
  1419             for transition in self.transitions.gettransition():
       
  1420                 if transition.getname() == name:
       
  1421                     return transition
       
  1422         return None
       
  1423     setattr(cls, "gettransition", gettransition)
       
  1424         
       
  1425     def gettransitionList(self):
       
  1426         if self.transitions:
       
  1427             return self.transitions.gettransition()
       
  1428         return []
       
  1429     setattr(cls, "gettransitionList", gettransitionList)
       
  1430     
       
  1431     def removetransition(self, name):
       
  1432         if self.transitions:
       
  1433             transitions = self.transitions.gettransition()
       
  1434             i = 0
       
  1435             removed = False
       
  1436             while i < len(transitions) and not removed:
       
  1437                 if transitions[i].getname() == name:
       
  1438                     transitions.pop(i)
       
  1439                     removed = True
       
  1440                 i += 1
       
  1441             if not removed:
       
  1442                 raise ValueError, _("Transition with name %s doesn't exist!")%name
       
  1443     setattr(cls, "removetransition", removetransition)
       
  1444 
       
  1445     def addaction(self, name, type):
       
  1446         if not self.actions:
       
  1447             self.addactions()
       
  1448             self.actions.setaction([])
       
  1449         action = PLCOpenClasses["actions_action"]()
       
  1450         action.setname(name)
       
  1451         action.setbodyType(type)
       
  1452         self.actions.appendaction(action)
       
  1453     setattr(cls, "addaction", addaction)
       
  1454     
       
  1455     def getaction(self, name):
       
  1456         if self.actions:
       
  1457             for action in self.actions.getaction():
       
  1458                 if action.getname() == name:
       
  1459                     return action
       
  1460         return None
       
  1461     setattr(cls, "getaction", getaction)
       
  1462     
       
  1463     def getactionList(self):
       
  1464         if self.actions:
       
  1465             return self.actions.getaction()
       
  1466         return []
       
  1467     setattr(cls, "getactionList", getactionList)
       
  1468         
       
  1469     def removeaction(self, name):
       
  1470         if self.actions:
       
  1471             actions = self.actions.getaction()
       
  1472             i = 0
       
  1473             removed = False
       
  1474             while i < len(actions) and not removed:
       
  1475                 if actions[i].getname() == name:
       
  1476                     actions.pop(i)
       
  1477                     removed = True
       
  1478                 i += 1
       
  1479             if not removed:
       
  1480                 raise ValueError, _("Action with name %s doesn't exist!")%name
       
  1481     setattr(cls, "removeaction", removeaction)
       
  1482 
       
  1483     def updateElementName(self, old_name, new_name):
       
  1484         if self.interface:
       
  1485             for content in self.interface.getcontent():
       
  1486                 for var in content["value"].getvariable():
       
  1487                     var_address = var.getaddress()
       
  1488                     if var_address is not None:
       
  1489                         if var_address == old_name:
       
  1490                             var.setaddress(new_name)
       
  1491                         if var.getname() == old_name:
       
  1492                             var.setname(new_name)
       
  1493                     var_type_content = var.gettype().getcontent()
       
  1494                     if var_type_content["name"] == "derived":
       
  1495                         if var_type_content["value"].getname() == old_name:
       
  1496                             var_type_content["value"].setname(new_name)
       
  1497         self.body[0].updateElementName(old_name, new_name)
       
  1498         for action in self.getactionList():
       
  1499             action.updateElementName(old_name, new_name)
       
  1500         for transition in self.gettransitionList():
       
  1501             transition.updateElementName(old_name, new_name)
       
  1502     setattr(cls, "updateElementName", updateElementName)
       
  1503 
       
  1504     def updateElementAddress(self, address_model, new_leading):
       
  1505         if self.interface:
       
  1506             for content in self.interface.getcontent():
       
  1507                 for var in content["value"].getvariable():
       
  1508                     var_address = var.getaddress()
       
  1509                     if var_address is not None:
       
  1510                         var.setaddress(update_address(var_address, address_model, new_leading))
       
  1511         self.body[0].updateElementAddress(address_model, new_leading)
       
  1512         for action in self.getactionList():
       
  1513             action.updateElementAddress(address_model, new_leading)
       
  1514         for transition in self.gettransitionList():
       
  1515             transition.updateElementAddress(address_model, new_leading)
       
  1516     setattr(cls, "updateElementAddress", updateElementAddress)
       
  1517 
       
  1518     def removeVariableByAddress(self, address):
       
  1519         if self.interface:
       
  1520             for content in self.interface.getcontent():
       
  1521                 variables = content["value"].getvariable()
       
  1522                 for i in xrange(len(variables)-1, -1, -1):
       
  1523                     if variables[i].getaddress() == address:
       
  1524                         variables.pop(i)
       
  1525     setattr(cls, "removeVariableByAddress", removeVariableByAddress)
       
  1526 
       
  1527     def removeVariableByFilter(self, address_model):
       
  1528         if self.interface:
       
  1529             for content in self.interface.getcontent():
       
  1530                 variables = content["value"].getvariable()
       
  1531                 for i in xrange(len(variables)-1, -1, -1):
       
  1532                     var_address = variables[i].getaddress()
       
  1533                     if var_address is not None:
       
  1534                         result = address_model.match(var_address)
       
  1535                         if result is not None:
       
  1536                             variables.pop(i)
       
  1537     setattr(cls, "removeVariableByFilter", removeVariableByFilter)
       
  1538     
       
  1539     def Search(self, criteria, parent_infos=[]):
       
  1540         search_result = []
       
  1541         filter = criteria["filter"]
       
  1542         if filter == "all" or self.getpouType() in filter:
       
  1543             parent_infos = parent_infos + ["P::%s" % self.getname()]
       
  1544             search_result.extend(_Search([("name", self.getname())], criteria, parent_infos))
       
  1545             if self.interface is not None:
       
  1546                 var_number = 0
       
  1547                 for content in self.interface.getcontent():
       
  1548                     variable_type = searchResultVarTypes.get(content["value"], "var_local")
       
  1549                     variables = content["value"].getvariable()
       
  1550                     for modifier, has_modifier in [("constant", content["value"].getconstant()),
       
  1551                                                    ("retain", content["value"].getretain()),
       
  1552                                                    ("non_retain", content["value"].getnonretain())]:
       
  1553                         if has_modifier:
       
  1554                             for result in TestTextElement(modifier, criteria):
       
  1555                                 search_result.append((tuple(parent_infos + [variable_type, (var_number, var_number + len(variables)), modifier]),) + result)
       
  1556                             break
       
  1557                     for variable in variables:
       
  1558                         search_result.extend(variable.Search(criteria, parent_infos + [variable_type, var_number]))
       
  1559                         var_number += 1
       
  1560             if len(self.body) > 0:
       
  1561                 search_result.extend(self.body[0].Search(criteria, parent_infos))
       
  1562             for action in self.getactionList():
       
  1563                 search_result.extend(action.Search(criteria, parent_infos))
       
  1564             for transition in self.gettransitionList():
       
  1565                 search_result.extend(transition.Search(criteria, parent_infos))
       
  1566         return search_result
       
  1567     setattr(cls, "Search", Search)
       
  1568 
       
  1569 def setbodyType(self, type):
       
  1570     if type == "IL":
       
  1571         self.body.setcontent({"name" : "IL", "value" : PLCOpenClasses["formattedText"]()})
       
  1572     elif type == "ST":
       
  1573         self.body.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
       
  1574     elif type == "LD":
       
  1575         self.body.setcontent({"name" : "LD", "value" : PLCOpenClasses["body_LD"]()})
       
  1576     elif type == "FBD":
       
  1577         self.body.setcontent({"name" : "FBD", "value" : PLCOpenClasses["body_FBD"]()})
       
  1578     elif type == "SFC":
       
  1579         self.body.setcontent({"name" : "SFC", "value" : PLCOpenClasses["body_SFC"]()})
       
  1580     else:
       
  1581         raise ValueError, "%s isn't a valid body type!"%type
       
  1582 
       
  1583 def getbodyType(self):
       
  1584     return self.body.getcontent()["name"]
       
  1585 
       
  1586 def resetexecutionOrder(self):
       
  1587     self.body.resetexecutionOrder()
       
  1588 
       
  1589 def compileexecutionOrder(self):
       
  1590     self.body.compileexecutionOrder()
       
  1591 
       
  1592 def setelementExecutionOrder(self, instance, new_executionOrder):
       
  1593     self.body.setelementExecutionOrder(instance, new_executionOrder)
       
  1594 
       
  1595 def addinstance(self, name, instance):
       
  1596     self.body.appendcontentInstance(name, instance)
       
  1597 
       
  1598 def getinstances(self):
       
  1599     return self.body.getcontentInstances()
       
  1600 
       
  1601 def getinstance(self, id):
       
  1602     return self.body.getcontentInstance(id)
       
  1603 
       
  1604 def getrandomInstance(self, exclude):
       
  1605     return self.body.getcontentRandomInstance(exclude)
       
  1606 
       
  1607 def getinstanceByName(self, name):
       
  1608     return self.body.getcontentInstanceByName(name)
       
  1609 
       
  1610 def removeinstance(self, id):
       
  1611     self.body.removecontentInstance(id)
       
  1612 
       
  1613 def settext(self, text):
       
  1614     self.body.settext(text)
       
  1615 
       
  1616 def gettext(self):
       
  1617     return self.body.gettext()
       
  1618 
       
  1619 cls = PLCOpenClasses.get("transitions_transition", None)
       
  1620 if cls:
       
  1621     setattr(cls, "setbodyType", setbodyType)
       
  1622     setattr(cls, "getbodyType", getbodyType)
       
  1623     setattr(cls, "resetexecutionOrder", resetexecutionOrder)
       
  1624     setattr(cls, "compileexecutionOrder", compileexecutionOrder)
       
  1625     setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
       
  1626     setattr(cls, "addinstance", addinstance)
       
  1627     setattr(cls, "getinstances", getinstances)
       
  1628     setattr(cls, "getinstance", getinstance)
       
  1629     setattr(cls, "getrandomInstance", getrandomInstance)
       
  1630     setattr(cls, "getinstanceByName", getinstanceByName)
       
  1631     setattr(cls, "removeinstance", removeinstance)
       
  1632     setattr(cls, "settext", settext)
       
  1633     setattr(cls, "gettext", gettext)
       
  1634 
       
  1635     def updateElementName(self, old_name, new_name):
       
  1636         self.body.updateElementName(old_name, new_name)
       
  1637     setattr(cls, "updateElementName", updateElementName)
       
  1638 
       
  1639     def updateElementAddress(self, address_model, new_leading):
       
  1640         self.body.updateElementAddress(address_model, new_leading)
       
  1641     setattr(cls, "updateElementAddress", updateElementAddress)
       
  1642 
       
  1643     def hasblock(self, name):
       
  1644         if self.getbodyType() in ["FBD", "LD", "SFC"]:
       
  1645             for instance in self.getinstances():
       
  1646                 if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
       
  1647                     return True
       
  1648         return False
       
  1649     setattr(cls, "hasblock", hasblock)
       
  1650 
       
  1651     def Search(self, criteria, parent_infos):
       
  1652         search_result = []
       
  1653         parent_infos = parent_infos[:-1] + ["T::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())]
       
  1654         for result in TestTextElement(self.getname(), criteria):
       
  1655             search_result.append((tuple(parent_infos + ["name"]),) + result)
       
  1656         search_result.extend(self.body.Search(criteria, parent_infos))
       
  1657         return search_result
       
  1658     setattr(cls, "Search", Search)
       
  1659 
       
  1660 cls = PLCOpenClasses.get("actions_action", None)
       
  1661 if cls:
       
  1662     setattr(cls, "setbodyType", setbodyType)
       
  1663     setattr(cls, "getbodyType", getbodyType)
       
  1664     setattr(cls, "resetexecutionOrder", resetexecutionOrder)
       
  1665     setattr(cls, "compileexecutionOrder", compileexecutionOrder)
       
  1666     setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
       
  1667     setattr(cls, "addinstance", addinstance)
       
  1668     setattr(cls, "getinstances", getinstances)
       
  1669     setattr(cls, "getinstance", getinstance)
       
  1670     setattr(cls, "getrandomInstance", getrandomInstance)
       
  1671     setattr(cls, "getinstanceByName", getinstanceByName)
       
  1672     setattr(cls, "removeinstance", removeinstance)
       
  1673     setattr(cls, "settext", settext)
       
  1674     setattr(cls, "gettext", gettext)
       
  1675 
       
  1676     def updateElementName(self, old_name, new_name):
       
  1677         self.body.updateElementName(old_name, new_name)
       
  1678     setattr(cls, "updateElementName", updateElementName)
       
  1679 
       
  1680     def updateElementAddress(self, address_model, new_leading):
       
  1681         self.body.updateElementAddress(address_model, new_leading)
       
  1682     setattr(cls, "updateElementAddress", updateElementAddress)
       
  1683 
       
  1684     def hasblock(self, name):
       
  1685         if self.getbodyType() in ["FBD", "LD", "SFC"]:
       
  1686             for instance in self.getinstances():
       
  1687                 if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
       
  1688                     return True
       
  1689         return False
       
  1690     setattr(cls, "hasblock", hasblock)
       
  1691 
       
  1692     def Search(self, criteria, parent_infos):
       
  1693         search_result = []
       
  1694         parent_infos = parent_infos[:-1] + ["A::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())]
       
  1695         for result in TestTextElement(self.getname(), criteria):
       
  1696             search_result.append((tuple(parent_infos + ["name"]),) + result)
       
  1697         search_result.extend(self.body.Search(criteria, parent_infos))
       
  1698         return search_result
       
  1699     setattr(cls, "Search", Search)
       
  1700 
       
  1701 cls = PLCOpenClasses.get("body", None)
       
  1702 if cls:
       
  1703     cls.currentExecutionOrderId = 0
       
  1704     
       
  1705     def resetcurrentExecutionOrderId(self):
       
  1706         object.__setattr__(self, "currentExecutionOrderId", 0)
       
  1707     setattr(cls, "resetcurrentExecutionOrderId", resetcurrentExecutionOrderId)
       
  1708     
       
  1709     def getnewExecutionOrderId(self):
       
  1710         object.__setattr__(self, "currentExecutionOrderId", self.currentExecutionOrderId + 1)
       
  1711         return self.currentExecutionOrderId
       
  1712     setattr(cls, "getnewExecutionOrderId", getnewExecutionOrderId)
       
  1713     
       
  1714     def resetexecutionOrder(self):
       
  1715         if self.content["name"] == "FBD":
       
  1716             for element in self.content["value"].getcontent():
       
  1717                 if not isinstance(element["value"], (PLCOpenClasses.get("commonObjects_comment", None), 
       
  1718                                                      PLCOpenClasses.get("commonObjects_connector", None), 
       
  1719                                                      PLCOpenClasses.get("commonObjects_continuation", None))):
       
  1720                     element["value"].setexecutionOrderId(0)
       
  1721         else:
       
  1722             raise TypeError, _("Can only generate execution order on FBD networks!")
       
  1723     setattr(cls, "resetexecutionOrder", resetexecutionOrder)
       
  1724     
       
  1725     def compileexecutionOrder(self):
       
  1726         if self.content["name"] == "FBD":
       
  1727             self.resetexecutionOrder()
       
  1728             self.resetcurrentExecutionOrderId()
       
  1729             for element in self.content["value"].getcontent():
       
  1730                 if isinstance(element["value"], PLCOpenClasses.get("fbdObjects_outVariable", None)) and element["value"].getexecutionOrderId() == 0:
       
  1731                     connections = element["value"].connectionPointIn.getconnections()
       
  1732                     if connections and len(connections) == 1:
       
  1733                         self.compileelementExecutionOrder(connections[0])
       
  1734                     element["value"].setexecutionOrderId(self.getnewExecutionOrderId())
       
  1735         else:
       
  1736             raise TypeError, _("Can only generate execution order on FBD networks!")
       
  1737     setattr(cls, "compileexecutionOrder", compileexecutionOrder)
       
  1738     
       
  1739     def compileelementExecutionOrder(self, link):
       
  1740         if self.content["name"] == "FBD":
       
  1741             localid = link.getrefLocalId()
       
  1742             instance = self.getcontentInstance(localid)
       
  1743             if isinstance(instance, PLCOpenClasses.get("fbdObjects_block", None)) and instance.getexecutionOrderId() == 0:
       
  1744                 for variable in instance.inputVariables.getvariable():
       
  1745                     connections = variable.connectionPointIn.getconnections()
       
  1746                     if connections and len(connections) == 1:
       
  1747                         self.compileelementExecutionOrder(connections[0])
       
  1748                 instance.setexecutionOrderId(self.getnewExecutionOrderId())
       
  1749             elif isinstance(instance, PLCOpenClasses.get("commonObjects_continuation", None)) and instance.getexecutionOrderId() == 0:
       
  1750                 name = instance.getname()
       
  1751                 for tmp_instance in self.getcontentInstances():
       
  1752                     if isinstance(tmp_instance, PLCOpenClasses.get("commonObjects_connector", None)) and tmp_instance.getname() == name and tmp_instance.getexecutionOrderId() == 0:
       
  1753                         connections = tmp_instance.connectionPointIn.getconnections()
       
  1754                         if connections and len(connections) == 1:
       
  1755                             self.compileelementExecutionOrder(connections[0])
       
  1756         else:
       
  1757             raise TypeError, _("Can only generate execution order on FBD networks!")
       
  1758     setattr(cls, "compileelementExecutionOrder", compileelementExecutionOrder)
       
  1759     
       
  1760     def setelementExecutionOrder(self, instance, new_executionOrder):
       
  1761         if self.content["name"] == "FBD":
       
  1762             old_executionOrder = instance.getexecutionOrderId()
       
  1763             if old_executionOrder is not None and old_executionOrder != 0 and new_executionOrder != 0:
       
  1764                 for element in self.content["value"].getcontent():
       
  1765                     if element["value"] != instance and not isinstance(element["value"], PLCOpenClasses.get("commonObjects_comment", None)):
       
  1766                         element_executionOrder = element["value"].getexecutionOrderId()
       
  1767                         if old_executionOrder <= element_executionOrder <= new_executionOrder:
       
  1768                             element["value"].setexecutionOrderId(element_executionOrder - 1)
       
  1769                         if new_executionOrder <= element_executionOrder <= old_executionOrder:
       
  1770                             element["value"].setexecutionOrderId(element_executionOrder + 1)
       
  1771             instance.setexecutionOrderId(new_executionOrder)
       
  1772         else:
       
  1773             raise TypeError, _("Can only generate execution order on FBD networks!")
       
  1774     setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
       
  1775     
       
  1776     def appendcontentInstance(self, name, instance):
       
  1777         if self.content["name"] in ["LD","FBD","SFC"]:
       
  1778             self.content["value"].appendcontent({"name" : name, "value" : instance})
       
  1779         else:
       
  1780             raise TypeError, _("%s body don't have instances!")%self.content["name"]
       
  1781     setattr(cls, "appendcontentInstance", appendcontentInstance)
       
  1782     
       
  1783     def getcontentInstances(self):
       
  1784         if self.content["name"] in ["LD","FBD","SFC"]:
       
  1785             instances = []
       
  1786             for element in self.content["value"].getcontent():
       
  1787                 instances.append(element["value"])
       
  1788             return instances
       
  1789         else:
       
  1790             raise TypeError, _("%s body don't have instances!")%self.content["name"]
       
  1791     setattr(cls, "getcontentInstances", getcontentInstances)
       
  1792 
       
  1793     def getcontentInstance(self, id):
       
  1794         if self.content["name"] in ["LD","FBD","SFC"]:
       
  1795             for element in self.content["value"].getcontent():
       
  1796                 if element["value"].getlocalId() == id:
       
  1797                     return element["value"]
       
  1798             return None
       
  1799         else:
       
  1800             raise TypeError, _("%s body don't have instances!")%self.content["name"]
       
  1801     setattr(cls, "getcontentInstance", getcontentInstance)
       
  1802     
       
  1803     def getcontentRandomInstance(self, exclude):
       
  1804         if self.content["name"] in ["LD","FBD","SFC"]:
       
  1805             for element in self.content["value"].getcontent():
       
  1806                 if element["value"].getlocalId() not in exclude:
       
  1807                     return element["value"]
       
  1808             return None
       
  1809         else:
       
  1810             raise TypeError, _("%s body don't have instances!")%self.content["name"]
       
  1811     setattr(cls, "getcontentRandomInstance", getcontentRandomInstance)
       
  1812     
       
  1813     def getcontentInstanceByName(self, name):
       
  1814         if self.content["name"] in ["LD","FBD","SFC"]:
       
  1815             for element in self.content["value"].getcontent():
       
  1816                 if isinstance(element["value"], PLCOpenClasses.get("fbdObjects_block", None)) and element["value"].getinstanceName() == name:
       
  1817                     return element["value"]
       
  1818         else:
       
  1819             raise TypeError, _("%s body don't have instances!")%self.content["name"]
       
  1820     setattr(cls, "getcontentInstanceByName", getcontentInstanceByName)
       
  1821     
       
  1822     def removecontentInstance(self, id):
       
  1823         if self.content["name"] in ["LD","FBD","SFC"]:
       
  1824             i = 0
       
  1825             removed = False
       
  1826             elements = self.content["value"].getcontent()
       
  1827             while i < len(elements) and not removed:
       
  1828                 if elements[i]["value"].getlocalId() == id:
       
  1829                     self.content["value"].removecontent(i)
       
  1830                     removed = True
       
  1831                 i += 1
       
  1832             if not removed:
       
  1833                 raise ValueError, _("Instance with id %d doesn't exist!")%id
       
  1834         else:
       
  1835             raise TypeError, "%s body don't have instances!"%self.content["name"]
       
  1836     setattr(cls, "removecontentInstance", removecontentInstance)
       
  1837     
       
  1838     def settext(self, text):
       
  1839         if self.content["name"] in ["IL","ST"]:
       
  1840             self.content["value"].settext(text)
       
  1841         else:
       
  1842             raise TypeError, _("%s body don't have text!")%self.content["name"]
       
  1843     setattr(cls, "settext", settext)
       
  1844 
       
  1845     def gettext(self):
       
  1846         if self.content["name"] in ["IL","ST"]:
       
  1847             return self.content["value"].gettext()
       
  1848         else:
       
  1849             raise TypeError, _("%s body don't have text!")%self.content["name"]
       
  1850     setattr(cls, "gettext", gettext)
       
  1851     
       
  1852     def updateElementName(self, old_name, new_name):
       
  1853         if self.content["name"] in ["IL", "ST"]:
       
  1854             self.content["value"].updateElementName(old_name, new_name)
       
  1855         else:
       
  1856             for element in self.content["value"].getcontent():
       
  1857                 element["value"].updateElementName(old_name, new_name)
       
  1858     setattr(cls, "updateElementName", updateElementName)
       
  1859 
       
  1860     def updateElementAddress(self, address_model, new_leading):
       
  1861         if self.content["name"] in ["IL", "ST"]:
       
  1862             self.content["value"].updateElementAddress(address_model, new_leading)
       
  1863         else:
       
  1864             for element in self.content["value"].getcontent():
       
  1865                 element["value"].updateElementAddress(address_model, new_leading)
       
  1866     setattr(cls, "updateElementAddress", updateElementAddress)
       
  1867 
       
  1868     def Search(self, criteria, parent_infos=[]):
       
  1869         if self.content["name"] in ["IL", "ST"]:
       
  1870             search_result = self.content["value"].Search(criteria, parent_infos + ["body", 0])
       
  1871         else:
       
  1872             search_result = []
       
  1873             for element in self.content["value"].getcontent():
       
  1874                 search_result.extend(element["value"].Search(criteria, parent_infos))
       
  1875         return search_result
       
  1876     setattr(cls, "Search", Search)
       
  1877 
       
  1878 def getx(self):
       
  1879     return self.position.getx()
       
  1880 
       
  1881 def gety(self):
       
  1882     return self.position.gety()
       
  1883 
       
  1884 def setx(self, x):
       
  1885     self.position.setx(x)
       
  1886     
       
  1887 def sety(self, y):
       
  1888     self.position.sety(y)
       
  1889 
       
  1890 def _getBoundingBox(self):
       
  1891     return rect(self.getx(), self.gety(), self.getwidth(), self.getheight())
       
  1892 
       
  1893 def _getConnectionsBoundingBox(connectionPointIn):
       
  1894     bbox = rect()
       
  1895     connections = connectionPointIn.getconnections()
       
  1896     if connections is not None:
       
  1897         for connection in connections:
       
  1898             for x, y in connection.getpoints():
       
  1899                 bbox.update(x, y)
       
  1900     return bbox
       
  1901 
       
  1902 def _getBoundingBoxSingle(self):
       
  1903     bbox = _getBoundingBox(self)
       
  1904     if self.connectionPointIn is not None:
       
  1905         bbox.union(_getConnectionsBoundingBox(self.connectionPointIn))
       
  1906     return bbox
       
  1907 
       
  1908 def _getBoundingBoxMultiple(self):
       
  1909     bbox = _getBoundingBox(self)
       
  1910     for connectionPointIn in self.getconnectionPointIn():
       
  1911         bbox.union(_getConnectionsBoundingBox(connectionPointIn))
       
  1912     return bbox
       
  1913 
       
  1914 def _filterConnections(connectionPointIn, localId, connections):
       
  1915     in_connections = connectionPointIn.getconnections()
       
  1916     if in_connections is not None:
       
  1917         to_delete = []
       
  1918         for i, connection in enumerate(in_connections):
       
  1919             connected = connection.getrefLocalId()
       
  1920             if not connections.has_key((localId, connected)) and \
       
  1921                not connections.has_key((connected, localId)):
       
  1922                 to_delete.append(i)
       
  1923         to_delete.reverse()
       
  1924         for i in to_delete:
       
  1925             connectionPointIn.removeconnection(i)
       
  1926 
       
  1927 def _filterConnectionsSingle(self, connections):
       
  1928     if self.connectionPointIn is not None:
       
  1929         _filterConnections(self.connectionPointIn, self.localId, connections)
       
  1930 
       
  1931 def _filterConnectionsMultiple(self, connections):
       
  1932     for connectionPointIn in self.getconnectionPointIn():
       
  1933         _filterConnections(connectionPointIn, self.localId, connections)
       
  1934 
       
  1935 def _getconnectionsdefinition(instance, connections_end):
       
  1936     id = instance.getlocalId()
       
  1937     return dict([((id, end), True) for end in connections_end])
       
  1938 
       
  1939 def _updateConnectionsId(connectionPointIn, translation):
       
  1940     connections_end = []
       
  1941     connections = connectionPointIn.getconnections()
       
  1942     if connections is not None:
       
  1943         for connection in connections:
       
  1944             refLocalId = connection.getrefLocalId()
       
  1945             new_reflocalId = translation.get(refLocalId, refLocalId)
       
  1946             connection.setrefLocalId(new_reflocalId)
       
  1947             connections_end.append(new_reflocalId)
       
  1948     return connections_end
       
  1949 
       
  1950 def _updateConnectionsIdSingle(self, translation):
       
  1951     connections_end = []
       
  1952     if self.connectionPointIn is not None:
       
  1953         connections_end = _updateConnectionsId(self.connectionPointIn, translation)
       
  1954     return _getconnectionsdefinition(self, connections_end)
       
  1955 
       
  1956 def _updateConnectionsIdMultiple(self, translation):
       
  1957     connections_end = []
       
  1958     for connectionPointIn in self.getconnectionPointIn():
       
  1959         connections_end.extend(_updateConnectionsId(connectionPointIn, translation))
       
  1960     return _getconnectionsdefinition(self, connections_end)
       
  1961 
       
  1962 def _translate(self, dx, dy):
       
  1963     self.setx(self.getx() + dx)
       
  1964     self.sety(self.gety() + dy)
       
  1965     
       
  1966 def _translateConnections(connectionPointIn, dx, dy):
       
  1967     connections = connectionPointIn.getconnections()
       
  1968     if connections is not None:
       
  1969         for connection in connections:
       
  1970             for position in connection.getposition():
       
  1971                 position.setx(position.getx() + dx)
       
  1972                 position.sety(position.gety() + dy)
       
  1973 
       
  1974 def _translateSingle(self, dx, dy):
       
  1975     _translate(self, dx, dy)
       
  1976     if self.connectionPointIn is not None:
       
  1977         _translateConnections(self.connectionPointIn, dx, dy)
       
  1978 
       
  1979 def _translateMultiple(self, dx, dy):
       
  1980     _translate(self, dx, dy)
       
  1981     for connectionPointIn in self.getconnectionPointIn():
       
  1982         _translateConnections(connectionPointIn, dx, dy)
       
  1983 
       
  1984 def _updateElementName(self, old_name, new_name):
       
  1985     pass
       
  1986 
       
  1987 def _updateElementAddress(self, address_model, new_leading):
       
  1988     pass
       
  1989 
       
  1990 def _SearchInElement(self, criteria, parent_infos=[]):
       
  1991     return []
       
  1992 
       
  1993 _connectionsFunctions = {
       
  1994     "bbox": {"none": _getBoundingBox,
       
  1995              "single": _getBoundingBoxSingle,
       
  1996              "multiple": _getBoundingBoxMultiple},
       
  1997     "translate": {"none": _translate,
       
  1998                "single": _translateSingle,
       
  1999                "multiple": _translateMultiple},
       
  2000     "filter": {"none": lambda self, connections: None,
       
  2001                "single": _filterConnectionsSingle,
       
  2002                "multiple": _filterConnectionsMultiple},
       
  2003     "update": {"none": lambda self, translation: {},
       
  2004                "single": _updateConnectionsIdSingle,
       
  2005                "multiple": _updateConnectionsIdMultiple},
       
  2006 }
       
  2007 
       
  2008 def _initElementClass(name, classname, connectionPointInType="none"):
       
  2009     ElementNameToClass[name] = classname
       
  2010     cls = PLCOpenClasses.get(classname, None)
       
  2011     if cls:
       
  2012         setattr(cls, "getx", getx)
       
  2013         setattr(cls, "gety", gety)
       
  2014         setattr(cls, "setx", setx)
       
  2015         setattr(cls, "sety", sety)
       
  2016         setattr(cls, "updateElementName", _updateElementName)
       
  2017         setattr(cls, "updateElementAddress", _updateElementAddress)
       
  2018         setattr(cls, "getBoundingBox", _connectionsFunctions["bbox"][connectionPointInType])
       
  2019         setattr(cls, "translate", _connectionsFunctions["translate"][connectionPointInType])
       
  2020         setattr(cls, "filterConnections", _connectionsFunctions["filter"][connectionPointInType])
       
  2021         setattr(cls, "updateConnectionsId", _connectionsFunctions["update"][connectionPointInType])
       
  2022         setattr(cls, "Search", _SearchInElement)
       
  2023     return cls
       
  2024 
       
  2025 def _getexecutionOrder(instance, specific_values):
       
  2026     executionOrder = instance.getexecutionOrderId()
       
  2027     if executionOrder is None:
       
  2028         executionOrder = 0
       
  2029     specific_values["executionOrder"] = executionOrder
       
  2030     
       
  2031 def _getdefaultmodifiers(instance, infos):
       
  2032     infos["negated"] = instance.getnegated()
       
  2033     infos["edge"] = instance.getedge()
       
  2034 
       
  2035 def _getinputmodifiers(instance, infos):
       
  2036     infos["negated"] = instance.getnegatedIn()
       
  2037     infos["edge"] = instance.getedgeIn()
       
  2038 
       
  2039 def _getoutputmodifiers(instance, infos):
       
  2040     infos["negated"] = instance.getnegatedOut()
       
  2041     infos["edge"] = instance.getedgeOut()
       
  2042 
       
  2043 MODIFIERS_FUNCTIONS = {"default": _getdefaultmodifiers,
       
  2044                        "input": _getinputmodifiers,
       
  2045                        "output": _getoutputmodifiers}
       
  2046 
       
  2047 def _getconnectioninfos(instance, connection, links=False, modifiers=None, parameter=False):
       
  2048     infos = {"position": connection.getrelPositionXY()}
       
  2049     if parameter:
       
  2050         infos["name"] = instance.getformalParameter()
       
  2051     MODIFIERS_FUNCTIONS.get(modifiers, lambda x, y: None)(instance, infos)
       
  2052     if links:
       
  2053         infos["links"] = []
       
  2054         connections = connection.getconnections()
       
  2055         if connections is not None:
       
  2056             for link in connections:
       
  2057                 dic = {"refLocalId": link.getrefLocalId(),
       
  2058                        "points": link.getpoints(),
       
  2059                        "formalParameter": link.getformalParameter()}
       
  2060                 infos["links"].append(dic)
       
  2061     return infos
       
  2062 
       
  2063 def _getelementinfos(instance):
       
  2064     return {"id": instance.getlocalId(),
       
  2065             "x": instance.getx(),
       
  2066             "y": instance.gety(),
       
  2067             "height": instance.getheight(),
       
  2068             "width": instance.getwidth(),
       
  2069             "specific_values": {},
       
  2070             "inputs": [],
       
  2071             "outputs": []}
       
  2072 
       
  2073 def _getvariableinfosFunction(type, input, output):
       
  2074     def getvariableinfos(self):
       
  2075         infos = _getelementinfos(self)
       
  2076         infos["type"] = type
       
  2077         specific_values = infos["specific_values"]
       
  2078         specific_values["name"] = self.getexpression()
       
  2079         _getexecutionOrder(self, specific_values)
       
  2080         if input and output:
       
  2081             infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True, "input"))
       
  2082             infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut, False, "output"))
       
  2083         elif input:
       
  2084             infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True, "default"))
       
  2085         elif output:
       
  2086             infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut, False, "default"))
       
  2087         return infos
       
  2088     return getvariableinfos
       
  2089 
       
  2090 def _getconnectorinfosFunction(type):
       
  2091     def getvariableinfos(self):
       
  2092         infos = _getelementinfos(self)
       
  2093         infos["type"] = type
       
  2094         infos["specific_values"]["name"] = self.getname()
       
  2095         if type == "connector":
       
  2096             infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2097         elif type == "continuation":
       
  2098             infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
       
  2099         return infos
       
  2100     return getvariableinfos
       
  2101 
       
  2102 def _getpowerrailinfosFunction(type):
       
  2103     def getpowerrailinfos(self):
       
  2104         infos = _getelementinfos(self)
       
  2105         infos["type"] = type
       
  2106         if type == "rightPowerRail":
       
  2107             for connectionPointIn in self.getconnectionPointIn():
       
  2108                 infos["inputs"].append(_getconnectioninfos(self, connectionPointIn, True))
       
  2109             infos["specific_values"]["connectors"] = len(infos["inputs"])
       
  2110         elif type == "leftPowerRail":
       
  2111             for connectionPointOut in self.getconnectionPointOut():
       
  2112                 infos["outputs"].append(_getconnectioninfos(self, connectionPointOut))
       
  2113             infos["specific_values"]["connectors"] = len(infos["outputs"])
       
  2114         return infos
       
  2115     return getpowerrailinfos
       
  2116 
       
  2117 def _getldelementinfosFunction(type):
       
  2118     def getldelementinfos(self):
       
  2119         infos = _getelementinfos(self)
       
  2120         infos["type"] = type
       
  2121         specific_values = infos["specific_values"]
       
  2122         specific_values["name"] = self.getvariable()
       
  2123         _getexecutionOrder(self, specific_values)
       
  2124         specific_values["negated"] = self.getnegated()
       
  2125         specific_values["edge"] = self.getedge()
       
  2126         if type == "coil":
       
  2127             specific_values["storage"] = self.getstorage()
       
  2128         infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2129         infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
       
  2130         return infos
       
  2131     return getldelementinfos
       
  2132 
       
  2133 DIVERGENCE_TYPES = {(True, True): "simultaneousDivergence",
       
  2134                     (True, False): "selectionDivergence",
       
  2135                     (False, True): "simultaneousConvergence",
       
  2136                     (False, False): "selectionConvergence"}
       
  2137 
       
  2138 def _getdivergenceinfosFunction(divergence, simultaneous):
       
  2139     def getdivergenceinfos(self):
       
  2140         infos = _getelementinfos(self)
       
  2141         infos["type"] = DIVERGENCE_TYPES[(divergence, simultaneous)]
       
  2142         if divergence:
       
  2143             infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2144             for connectionPointOut in self.getconnectionPointOut():
       
  2145                 infos["outputs"].append(_getconnectioninfos(self, connectionPointOut))
       
  2146             infos["specific_values"]["connectors"] = len(infos["outputs"])
       
  2147         else:
       
  2148             for connectionPointIn in self.getconnectionPointIn():
       
  2149                 infos["inputs"].append(_getconnectioninfos(self, connectionPointIn, True))
       
  2150             infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
       
  2151             infos["specific_values"]["connectors"] = len(infos["inputs"])
       
  2152         return infos
       
  2153     return getdivergenceinfos
       
  2154 
       
  2155 cls = _initElementClass("comment", "commonObjects_comment")
       
  2156 if cls:
       
  2157     def getinfos(self):
       
  2158         infos = _getelementinfos(self)
       
  2159         infos["type"] = "comment"
       
  2160         infos["specific_values"]["content"] = self.getcontentText()
       
  2161         return infos
       
  2162     setattr(cls, "getinfos", getinfos)
       
  2163     
       
  2164     def setcontentText(self, text):
       
  2165         self.content.settext(text)
       
  2166     setattr(cls, "setcontentText", setcontentText)
       
  2167         
       
  2168     def getcontentText(self):
       
  2169         return self.content.gettext()
       
  2170     setattr(cls, "getcontentText", getcontentText)
       
  2171     
       
  2172     def updateElementName(self, old_name, new_name):
       
  2173         self.content.updateElementName(old_name, new_name)
       
  2174     setattr(cls, "updateElementName", updateElementName)
       
  2175 
       
  2176     def updateElementAddress(self, address_model, new_leading):
       
  2177         self.content.updateElementAddress(address_model, new_leading)
       
  2178     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2179 
       
  2180     def Search(self, criteria, parent_infos=[]):
       
  2181         return self.content.Search(criteria, parent_infos + ["comment", self.getlocalId(), "content"])
       
  2182     setattr(cls, "Search", Search)
       
  2183 
       
  2184 cls = _initElementClass("block", "fbdObjects_block")
       
  2185 if cls:
       
  2186     def getBoundingBox(self):
       
  2187         bbox = _getBoundingBox(self)
       
  2188         for input in self.inputVariables.getvariable():
       
  2189             bbox.union(_getConnectionsBoundingBox(input.connectionPointIn))
       
  2190         return bbox
       
  2191     setattr(cls, "getBoundingBox", getBoundingBox)
       
  2192 
       
  2193     def getinfos(self):
       
  2194         infos = _getelementinfos(self)
       
  2195         infos["type"] = self.gettypeName()
       
  2196         specific_values = infos["specific_values"]
       
  2197         specific_values["name"] = self.getinstanceName()
       
  2198         _getexecutionOrder(self, specific_values)
       
  2199         for variable in self.inputVariables.getvariable():
       
  2200             infos["inputs"].append(_getconnectioninfos(variable, variable.connectionPointIn, True, "default", True))
       
  2201         for variable in self.outputVariables.getvariable():
       
  2202             infos["outputs"].append(_getconnectioninfos(variable, variable.connectionPointOut, False, "default", True))
       
  2203         return infos
       
  2204     setattr(cls, "getinfos", getinfos)
       
  2205 
       
  2206     def updateElementName(self, old_name, new_name):
       
  2207         if self.typeName == old_name:
       
  2208             self.typeName = new_name
       
  2209     setattr(cls, "updateElementName", updateElementName)
       
  2210 
       
  2211     def filterConnections(self, connections):
       
  2212         for input in self.inputVariables.getvariable():
       
  2213             _filterConnections(input.connectionPointIn, self.localId, connections)
       
  2214     setattr(cls, "filterConnections", filterConnections)
       
  2215 
       
  2216     def updateConnectionsId(self, translation):
       
  2217         connections_end = []
       
  2218         for input in self.inputVariables.getvariable():
       
  2219             connections_end.extend(_updateConnectionsId(input.connectionPointIn, translation))
       
  2220         return _getconnectionsdefinition(self, connections_end)
       
  2221     setattr(cls, "updateConnectionsId", updateConnectionsId)
       
  2222 
       
  2223     def translate(self, dx, dy):
       
  2224         _translate(self, dx, dy)
       
  2225         for input in self.inputVariables.getvariable():
       
  2226             _translateConnections(input.connectionPointIn, dx, dy)
       
  2227     setattr(cls, "translate", translate)
       
  2228 
       
  2229     def Search(self, criteria, parent_infos=[]):
       
  2230         parent_infos = parent_infos + ["block", self.getlocalId()]
       
  2231         search_result = _Search([("name", self.getinstanceName()),
       
  2232                                  ("type", self.gettypeName())],
       
  2233                                 criteria, parent_infos)
       
  2234         for i, variable in enumerate(self.inputVariables.getvariable()):
       
  2235             for result in TestTextElement(variable.getformalParameter(), criteria):
       
  2236                 search_result.append((tuple(parent_infos + ["input", i]),) + result)
       
  2237         for i, variable in enumerate(self.outputVariables.getvariable()):
       
  2238             for result in TestTextElement(variable.getformalParameter(), criteria):
       
  2239                 search_result.append((tuple(parent_infos + ["output", i]),) + result)
       
  2240         return search_result
       
  2241     setattr(cls, "Search", Search)
       
  2242 
       
  2243 cls = _initElementClass("leftPowerRail", "ldObjects_leftPowerRail")
       
  2244 if cls:
       
  2245     setattr(cls, "getinfos", _getpowerrailinfosFunction("leftPowerRail"))
       
  2246 
       
  2247 cls = _initElementClass("rightPowerRail", "ldObjects_rightPowerRail", "multiple")
       
  2248 if cls:
       
  2249     setattr(cls, "getinfos", _getpowerrailinfosFunction("rightPowerRail"))
       
  2250 
       
  2251 cls = _initElementClass("contact", "ldObjects_contact", "single")
       
  2252 if cls:
       
  2253     setattr(cls, "getinfos", _getldelementinfosFunction("contact"))
       
  2254     
       
  2255     def updateElementName(self, old_name, new_name):
       
  2256         if self.variable == old_name:
       
  2257             self.variable = new_name
       
  2258     setattr(cls, "updateElementName", updateElementName)
       
  2259     
       
  2260     def updateElementAddress(self, address_model, new_leading):
       
  2261         self.variable = update_address(self.variable, address_model, new_leading)
       
  2262     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2263     
       
  2264     def Search(self, criteria, parent_infos=[]):
       
  2265         return _Search([("reference", self.getvariable())], criteria, parent_infos + ["contact", self.getlocalId()])
       
  2266     setattr(cls, "Search", Search)
       
  2267 
       
  2268 cls = _initElementClass("coil", "ldObjects_coil", "single")
       
  2269 if cls:
       
  2270     setattr(cls, "getinfos", _getldelementinfosFunction("coil"))
       
  2271     
       
  2272     def updateElementName(self, old_name, new_name):
       
  2273         if self.variable == old_name:
       
  2274             self.variable = new_name
       
  2275     setattr(cls, "updateElementName", updateElementName)
       
  2276 
       
  2277     def updateElementAddress(self, address_model, new_leading):
       
  2278         self.variable = update_address(self.variable, address_model, new_leading)
       
  2279     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2280 
       
  2281     def Search(self, criteria, parent_infos=[]):
       
  2282         return _Search([("reference", self.getvariable())], criteria, parent_infos + ["coil", self.getlocalId()])
       
  2283     setattr(cls, "Search", Search)
       
  2284 
       
  2285 cls = _initElementClass("step", "sfcObjects_step", "single")
       
  2286 if cls:
       
  2287     def getinfos(self):
       
  2288         infos = _getelementinfos(self)
       
  2289         infos["type"] = "step"
       
  2290         specific_values = infos["specific_values"]
       
  2291         specific_values["name"] = self.getname()
       
  2292         specific_values["initial"] = self.getinitialStep()
       
  2293         if self.connectionPointIn:
       
  2294             infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2295         if self.connectionPointOut:
       
  2296             infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
       
  2297         if self.connectionPointOutAction:
       
  2298             specific_values["action"] = _getconnectioninfos(self, self.connectionPointOutAction)
       
  2299         return infos
       
  2300     setattr(cls, "getinfos", getinfos)
       
  2301 
       
  2302     def Search(self, criteria, parent_infos=[]):
       
  2303         return _Search([("name", self.getname())], criteria, parent_infos + ["step", self.getlocalId()])
       
  2304     setattr(cls, "Search", Search)
       
  2305 
       
  2306 cls = PLCOpenClasses.get("transition_condition", None)
       
  2307 if cls:
       
  2308     def compatibility(self, tree):
       
  2309         connections = []
       
  2310         for child in tree.childNodes:
       
  2311             if child.nodeName == "connection":
       
  2312                 connections.append(child)
       
  2313         if len(connections) > 0:
       
  2314             node = CreateNode("connectionPointIn")
       
  2315             relPosition = CreateNode("relPosition")
       
  2316             NodeSetAttr(relPosition, "x", "0")
       
  2317             NodeSetAttr(relPosition, "y", "0")
       
  2318             node.childNodes.append(relPosition)
       
  2319             node.childNodes.extend(connections)
       
  2320             tree.childNodes = [node]
       
  2321     setattr(cls, "compatibility", compatibility)
       
  2322 
       
  2323 cls = _initElementClass("transition", "sfcObjects_transition", "single")
       
  2324 if cls:
       
  2325     def getinfos(self):
       
  2326         infos = _getelementinfos(self)
       
  2327         infos["type"] = "transition"
       
  2328         specific_values = infos["specific_values"]
       
  2329         priority = self.getpriority()
       
  2330         if priority is None:
       
  2331             priority = 0
       
  2332         specific_values["priority"] = priority
       
  2333         condition = self.getconditionContent()
       
  2334         specific_values["condition_type"] = condition["type"]
       
  2335         if specific_values["condition_type"] == "connection":
       
  2336             specific_values["connection"] = _getconnectioninfos(self, condition["value"], True)
       
  2337         else:
       
  2338             specific_values["condition"] = condition["value"]
       
  2339         infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2340         infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
       
  2341         return infos
       
  2342     setattr(cls, "getinfos", getinfos)
       
  2343 
       
  2344     def setconditionContent(self, type, value):
       
  2345         if not self.condition:
       
  2346             self.addcondition()
       
  2347         if type == "reference":
       
  2348             condition = PLCOpenClasses["condition_reference"]()
       
  2349             condition.setname(value)
       
  2350         elif type == "inline":
       
  2351             condition = PLCOpenClasses["condition_inline"]()
       
  2352             condition.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
       
  2353             condition.settext(value)
       
  2354         elif type == "connection":
       
  2355             type = "connectionPointIn"
       
  2356             condition = PLCOpenClasses["connectionPointIn"]()
       
  2357         self.condition.setcontent({"name" : type, "value" : condition})
       
  2358     setattr(cls, "setconditionContent", setconditionContent)
       
  2359         
       
  2360     def getconditionContent(self):
       
  2361         if self.condition:
       
  2362             content = self.condition.getcontent()
       
  2363             values = {"type" : content["name"]}
       
  2364             if values["type"] == "reference":
       
  2365                 values["value"] = content["value"].getname()
       
  2366             elif values["type"] == "inline":
       
  2367                 values["value"] = content["value"].gettext()
       
  2368             elif values["type"] == "connectionPointIn":
       
  2369                 values["type"] = "connection"
       
  2370                 values["value"] = content["value"]
       
  2371             return values
       
  2372         return ""
       
  2373     setattr(cls, "getconditionContent", getconditionContent)
       
  2374 
       
  2375     def updateElementName(self, old_name, new_name):
       
  2376         if self.condition:
       
  2377             content = self.condition.getcontent()
       
  2378             if content["name"] == "reference":
       
  2379                 if content["value"].getname() == old_name:
       
  2380                     content["value"].setname(new_name)
       
  2381             elif content["name"] == "inline":
       
  2382                 content["value"].updateElementName(old_name, new_name)
       
  2383     setattr(cls, "updateElementName", updateElementName)
       
  2384 
       
  2385     def updateElementAddress(self, address_model, new_leading):
       
  2386         if self.condition:
       
  2387             content = self.condition.getcontent()
       
  2388             if content["name"] == "reference":
       
  2389                 content["value"].setname(update_address(content["value"].getname(), address_model, new_leading))
       
  2390             elif content["name"] == "inline":
       
  2391                 content["value"].updateElementAddress(address_model, new_leading)
       
  2392     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2393 
       
  2394     def getconnections(self):
       
  2395         if self.condition:
       
  2396             content = self.condition.getcontent()
       
  2397             if content["name"] == "connectionPointIn":
       
  2398                 return content["value"].getconnections()
       
  2399     setattr(cls, "getconnections", getconnections)
       
  2400     
       
  2401     def Search(self, criteria, parent_infos=[]):
       
  2402         parent_infos = parent_infos + ["transition", self.getlocalId()]
       
  2403         search_result = []
       
  2404         content = self.condition.getcontent()
       
  2405         if content["name"] == "reference":
       
  2406             search_result.extend(_Search([("reference", content["value"].getname())], criteria, parent_infos))
       
  2407         elif content["name"] == "inline":
       
  2408             search_result.extend(content["value"].Search(criteria, parent_infos + ["inline"]))
       
  2409         return search_result
       
  2410     setattr(cls, "Search", Search)
       
  2411     
       
  2412 cls = _initElementClass("selectionDivergence", "sfcObjects_selectionDivergence", "single")
       
  2413 if cls:
       
  2414     setattr(cls, "getinfos", _getdivergenceinfosFunction(True, False))
       
  2415 
       
  2416 cls = _initElementClass("selectionConvergence", "sfcObjects_selectionConvergence", "multiple")
       
  2417 if cls:
       
  2418     setattr(cls, "getinfos", _getdivergenceinfosFunction(False, False))
       
  2419 
       
  2420 cls = _initElementClass("simultaneousDivergence", "sfcObjects_simultaneousDivergence", "single")
       
  2421 if cls:
       
  2422     setattr(cls, "getinfos", _getdivergenceinfosFunction(True, True))
       
  2423 
       
  2424 cls = _initElementClass("simultaneousConvergence", "sfcObjects_simultaneousConvergence", "multiple")
       
  2425 if cls:
       
  2426     setattr(cls, "getinfos", _getdivergenceinfosFunction(False, True))
       
  2427 
       
  2428 cls = _initElementClass("jumpStep", "sfcObjects_jumpStep", "single")
       
  2429 if cls:
       
  2430     def getinfos(self):
       
  2431         infos = _getelementinfos(self)
       
  2432         infos["type"] = "jump"
       
  2433         infos["specific_values"]["target"] = self.gettargetName()
       
  2434         infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2435         return infos
       
  2436     setattr(cls, "getinfos", getinfos)
       
  2437 
       
  2438     def Search(self, criteria, parent_infos):
       
  2439         return _Search([("target", self.gettargetName())], criteria, parent_infos + ["jump", self.getlocalId()])
       
  2440     setattr(cls, "Search", Search)
       
  2441 
       
  2442 cls = PLCOpenClasses.get("actionBlock_action", None)
       
  2443 if cls:
       
  2444     def compatibility(self, tree):
       
  2445         relPosition = reduce(lambda x, y: x | (y.nodeName == "relPosition"), tree.childNodes, False)
       
  2446         if not tree.hasAttribute("localId"):
       
  2447             NodeSetAttr(tree, "localId", "0")
       
  2448         if not relPosition:
       
  2449             node = CreateNode("relPosition")
       
  2450             NodeSetAttr(node, "x", "0")
       
  2451             NodeSetAttr(node, "y", "0")
       
  2452             tree.childNodes.insert(0, node)
       
  2453     setattr(cls, "compatibility", compatibility)
       
  2454     
       
  2455     def setreferenceName(self, name):
       
  2456         if self.reference:
       
  2457             self.reference.setname(name)
       
  2458     setattr(cls, "setreferenceName", setreferenceName)
       
  2459     
       
  2460     def getreferenceName(self):
       
  2461         if self.reference:
       
  2462             return self.reference.getname()
       
  2463         return None
       
  2464     setattr(cls, "getreferenceName", getreferenceName)
       
  2465 
       
  2466     def setinlineContent(self, content):
       
  2467         if self.inline:
       
  2468             self.inline.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
       
  2469             self.inline.settext(content)
       
  2470     setattr(cls, "setinlineContent", setinlineContent)
       
  2471     
       
  2472     def getinlineContent(self):
       
  2473         if self.inline:
       
  2474             return self.inline.gettext()
       
  2475         return None
       
  2476     setattr(cls, "getinlineContent", getinlineContent)
       
  2477 
       
  2478     def updateElementName(self, old_name, new_name):
       
  2479         if self.reference and self.reference.getname() == old_name:
       
  2480             self.reference.setname(new_name)
       
  2481         if self.inline:
       
  2482             self.inline.updateElementName(old_name, new_name)
       
  2483     setattr(cls, "updateElementName", updateElementName)
       
  2484 
       
  2485     def updateElementAddress(self, address_model, new_leading):
       
  2486         if self.reference:
       
  2487             self.reference.setname(update_address(self.reference.getname(), address_model, new_leading))
       
  2488         if self.inline:
       
  2489             self.inline.updateElementAddress(address_model, new_leading)
       
  2490     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2491 
       
  2492     def Search(self, criteria, parent_infos=[]):
       
  2493         qualifier = self.getqualifier()
       
  2494         if qualifier is None:
       
  2495             qualifier = "N"
       
  2496         return _Search([("inline", self.getinlineContent()),
       
  2497                         ("reference", self.getreferenceName()), 
       
  2498                         ("qualifier", qualifier),
       
  2499                         ("duration", self.getduration()),
       
  2500                         ("indicator", self.getindicator())],
       
  2501                        criteria, parent_infos)
       
  2502     setattr(cls, "Search", Search)
       
  2503 
       
  2504 cls = _initElementClass("actionBlock", "commonObjects_actionBlock", "single")
       
  2505 if cls:
       
  2506     def compatibility(self, tree):
       
  2507         for child in tree.childNodes[:]:
       
  2508             if child.nodeName == "connectionPointOut":
       
  2509                 tree.childNodes.remove(child)
       
  2510     setattr(cls, "compatibility", compatibility)
       
  2511     
       
  2512     def getinfos(self):
       
  2513         infos = _getelementinfos(self)
       
  2514         infos["type"] = "actionBlock"
       
  2515         infos["specific_values"]["actions"] = self.getactions()
       
  2516         infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2517         return infos
       
  2518     setattr(cls, "getinfos", getinfos)
       
  2519     
       
  2520     def setactions(self, actions):
       
  2521         self.action = []
       
  2522         for params in actions:
       
  2523             action = PLCOpenClasses["actionBlock_action"]()
       
  2524             action.setqualifier(params["qualifier"])
       
  2525             if params["type"] == "reference":
       
  2526                 action.addreference()
       
  2527                 action.setreferenceName(params["value"])
       
  2528             else:
       
  2529                 action.addinline()
       
  2530                 action.setinlineContent(params["value"])
       
  2531             if params.has_key("duration"):
       
  2532                 action.setduration(params["duration"])
       
  2533             if params.has_key("indicator"):
       
  2534                 action.setindicator(params["indicator"])
       
  2535             self.action.append(action)
       
  2536     setattr(cls, "setactions", setactions)
       
  2537 
       
  2538     def getactions(self):
       
  2539         actions = []
       
  2540         for action in self.action:
       
  2541             params = {}
       
  2542             params["qualifier"] = action.getqualifier()
       
  2543             if params["qualifier"] is None:
       
  2544                 params["qualifier"] = "N"
       
  2545             if action.getreference():
       
  2546                 params["type"] = "reference"
       
  2547                 params["value"] = action.getreferenceName()
       
  2548             elif action.getinline():
       
  2549                 params["type"] = "inline"
       
  2550                 params["value"] = action.getinlineContent()
       
  2551             duration = action.getduration()
       
  2552             if duration:
       
  2553                 params["duration"] = duration
       
  2554             indicator = action.getindicator()
       
  2555             if indicator:
       
  2556                 params["indicator"] = indicator
       
  2557             actions.append(params)
       
  2558         return actions
       
  2559     setattr(cls, "getactions", getactions)
       
  2560 
       
  2561     def updateElementName(self, old_name, new_name):
       
  2562         for action in self.action:
       
  2563             action.updateElementName(old_name, new_name)
       
  2564     setattr(cls, "updateElementName", updateElementName)
       
  2565 
       
  2566     def updateElementAddress(self, address_model, new_leading):
       
  2567         for action in self.action:
       
  2568             action.updateElementAddress(address_model, new_leading)
       
  2569     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2570 
       
  2571     def Search(self, criteria, parent_infos=[]):
       
  2572         parent_infos = parent_infos + ["action_block", self.getlocalId()]
       
  2573         search_result = []
       
  2574         for idx, action in enumerate(self.action):
       
  2575             search_result.extend(action.Search(criteria, parent_infos + ["action", idx]))
       
  2576         return search_result
       
  2577     setattr(cls, "Search", Search)
       
  2578 
       
  2579 def _SearchInIOVariable(self, criteria, parent_infos=[]):
       
  2580     return _Search([("expression", self.getexpression())], criteria, parent_infos + ["io_variable", self.getlocalId()])
       
  2581 
       
  2582 cls = _initElementClass("inVariable", "fbdObjects_inVariable")
       
  2583 if cls:
       
  2584     setattr(cls, "getinfos", _getvariableinfosFunction("input", False, True))
       
  2585     
       
  2586     def updateElementName(self, old_name, new_name):
       
  2587         if self.expression == old_name:
       
  2588             self.expression = new_name
       
  2589     setattr(cls, "updateElementName", updateElementName)
       
  2590 
       
  2591     def updateElementAddress(self, address_model, new_leading):
       
  2592         self.expression = update_address(self.expression, address_model, new_leading)
       
  2593     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2594 
       
  2595     setattr(cls, "Search", _SearchInIOVariable)
       
  2596 
       
  2597 cls = _initElementClass("outVariable", "fbdObjects_outVariable", "single")
       
  2598 if cls:
       
  2599     setattr(cls, "getinfos", _getvariableinfosFunction("output", True, False))
       
  2600     
       
  2601     def updateElementName(self, old_name, new_name):
       
  2602         if self.expression == old_name:
       
  2603             self.expression = new_name
       
  2604     setattr(cls, "updateElementName", updateElementName)
       
  2605 
       
  2606     def updateElementAddress(self, address_model, new_leading):
       
  2607         self.expression = update_address(self.expression, address_model, new_leading)
       
  2608     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2609 
       
  2610     setattr(cls, "Search", _SearchInIOVariable)
       
  2611 
       
  2612 cls = _initElementClass("inOutVariable", "fbdObjects_inOutVariable", "single")
       
  2613 if cls:
       
  2614     setattr(cls, "getinfos", _getvariableinfosFunction("inout", True, True))
       
  2615     
       
  2616     def updateElementName(self, old_name, new_name):
       
  2617         if self.expression == old_name:
       
  2618             self.expression = new_name
       
  2619     setattr(cls, "updateElementName", updateElementName)
       
  2620 
       
  2621     def updateElementAddress(self, address_model, new_leading):
       
  2622         self.expression = update_address(self.expression, address_model, new_leading)
       
  2623     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2624 
       
  2625     setattr(cls, "Search", _SearchInIOVariable)
       
  2626 
       
  2627 
       
  2628 def _SearchInConnector(self, criteria, parent_infos=[]):
       
  2629     return _Search([("name", self.getname())], criteria, parent_infos + ["connector", self.getlocalId()])
       
  2630 
       
  2631 cls = _initElementClass("continuation", "commonObjects_continuation")
       
  2632 if cls:
       
  2633     setattr(cls, "getinfos", _getconnectorinfosFunction("continuation"))
       
  2634     setattr(cls, "Search", _SearchInConnector)
       
  2635 
       
  2636     def updateElementName(self, old_name, new_name):
       
  2637         if self.name == old_name:
       
  2638             self.name = new_name
       
  2639     setattr(cls, "updateElementName", updateElementName)
       
  2640 
       
  2641 cls = _initElementClass("connector", "commonObjects_connector", "single")
       
  2642 if cls:
       
  2643     setattr(cls, "getinfos", _getconnectorinfosFunction("connector"))
       
  2644     setattr(cls, "Search", _SearchInConnector)
       
  2645 
       
  2646     def updateElementName(self, old_name, new_name):
       
  2647         if self.name == old_name:
       
  2648             self.name = new_name
       
  2649     setattr(cls, "updateElementName", updateElementName)
       
  2650 
       
  2651 cls = PLCOpenClasses.get("connection", None)
       
  2652 if cls:
       
  2653     def setpoints(self, points):
       
  2654         self.position = []
       
  2655         for point in points:
       
  2656             position = PLCOpenClasses["position"]()
       
  2657             position.setx(point.x)
       
  2658             position.sety(point.y)
       
  2659             self.position.append(position)
       
  2660     setattr(cls, "setpoints", setpoints)
       
  2661 
       
  2662     def getpoints(self):
       
  2663         points = []
       
  2664         for position in self.position:
       
  2665             points.append((position.getx(),position.gety()))
       
  2666         return points
       
  2667     setattr(cls, "getpoints", getpoints)
       
  2668 
       
  2669 cls = PLCOpenClasses.get("connectionPointIn", None)
       
  2670 if cls:
       
  2671     def setrelPositionXY(self, x, y):
       
  2672         self.relPosition = PLCOpenClasses["position"]()
       
  2673         self.relPosition.setx(x)
       
  2674         self.relPosition.sety(y)
       
  2675     setattr(cls, "setrelPositionXY", setrelPositionXY)
       
  2676 
       
  2677     def getrelPositionXY(self):
       
  2678         if self.relPosition:
       
  2679             return self.relPosition.getx(), self.relPosition.gety()
       
  2680         else:
       
  2681             return self.relPosition
       
  2682     setattr(cls, "getrelPositionXY", getrelPositionXY)
       
  2683 
       
  2684     def addconnection(self):
       
  2685         if not self.content:
       
  2686             self.content = {"name" : "connection", "value" : [PLCOpenClasses["connection"]()]}
       
  2687         else:
       
  2688             self.content["value"].append(PLCOpenClasses["connection"]())
       
  2689     setattr(cls, "addconnection", addconnection)
       
  2690 
       
  2691     def removeconnection(self, idx):
       
  2692         if self.content:
       
  2693             self.content["value"].pop(idx)
       
  2694         if len(self.content["value"]) == 0:
       
  2695             self.content = None
       
  2696     setattr(cls, "removeconnection", removeconnection)
       
  2697 
       
  2698     def removeconnections(self):
       
  2699         if self.content:
       
  2700             self.content = None
       
  2701     setattr(cls, "removeconnections", removeconnections)
       
  2702     
       
  2703     def getconnections(self):
       
  2704         if self.content:
       
  2705             return self.content["value"]
       
  2706     setattr(cls, "getconnections", getconnections)
       
  2707     
       
  2708     def setconnectionId(self, idx, id):
       
  2709         if self.content:
       
  2710             self.content["value"][idx].setrefLocalId(id)
       
  2711     setattr(cls, "setconnectionId", setconnectionId)
       
  2712     
       
  2713     def getconnectionId(self, idx):
       
  2714         if self.content:
       
  2715             return self.content["value"][idx].getrefLocalId()
       
  2716         return None
       
  2717     setattr(cls, "getconnectionId", getconnectionId)
       
  2718     
       
  2719     def setconnectionPoints(self, idx, points):
       
  2720         if self.content:
       
  2721             self.content["value"][idx].setpoints(points)
       
  2722     setattr(cls, "setconnectionPoints", setconnectionPoints)
       
  2723 
       
  2724     def getconnectionPoints(self, idx):
       
  2725         if self.content:
       
  2726             return self.content["value"][idx].getpoints()
       
  2727         return None
       
  2728     setattr(cls, "getconnectionPoints", getconnectionPoints)
       
  2729 
       
  2730     def setconnectionParameter(self, idx, parameter):
       
  2731         if self.content:
       
  2732             self.content["value"][idx].setformalParameter(parameter)
       
  2733     setattr(cls, "setconnectionParameter", setconnectionParameter)
       
  2734     
       
  2735     def getconnectionParameter(self, idx):
       
  2736         if self.content:
       
  2737             return self.content["value"][idx].getformalParameter()
       
  2738         return None
       
  2739     setattr(cls, "getconnectionParameter", getconnectionParameter)
       
  2740 
       
  2741 cls = PLCOpenClasses.get("connectionPointOut", None)
       
  2742 if cls:
       
  2743     def setrelPositionXY(self, x, y):
       
  2744         self.relPosition = PLCOpenClasses["position"]()
       
  2745         self.relPosition.setx(x)
       
  2746         self.relPosition.sety(y)
       
  2747     setattr(cls, "setrelPositionXY", setrelPositionXY)
       
  2748 
       
  2749     def getrelPositionXY(self):
       
  2750         if self.relPosition:
       
  2751             return self.relPosition.getx(), self.relPosition.gety()
       
  2752         return self.relPosition
       
  2753     setattr(cls, "getrelPositionXY", getrelPositionXY)
       
  2754 
       
  2755 cls = PLCOpenClasses.get("value", None)
       
  2756 if cls:
       
  2757     def setvalue(self, value):
       
  2758         value = value.strip()
       
  2759         if value.startswith("[") and value.endswith("]"):
       
  2760             arrayValue = PLCOpenClasses["value_arrayValue"]()
       
  2761             self.content = {"name" : "arrayValue", "value" : arrayValue}
       
  2762         elif value.startswith("(") and value.endswith(")"):
       
  2763             structValue = PLCOpenClasses["value_structValue"]()
       
  2764             self.content = {"name" : "structValue", "value" : structValue}
       
  2765         else:
       
  2766             simpleValue = PLCOpenClasses["value_simpleValue"]()
       
  2767             self.content = {"name" : "simpleValue", "value": simpleValue}
       
  2768         self.content["value"].setvalue(value)
       
  2769     setattr(cls, "setvalue", setvalue)
       
  2770     
       
  2771     def getvalue(self):
       
  2772         return self.content["value"].getvalue()
       
  2773     setattr(cls, "getvalue", getvalue)
       
  2774 
       
  2775 def extractValues(values):
       
  2776     items = values.split(",")
       
  2777     i = 1
       
  2778     while i < len(items):
       
  2779         opened = items[i - 1].count("(") + items[i - 1].count("[")
       
  2780         closed = items[i - 1].count(")") + items[i - 1].count("]")
       
  2781         if opened > closed:
       
  2782             items[i - 1] = ','.join([items[i - 1], items.pop(i)])
       
  2783         elif opened == closed:
       
  2784             i += 1
       
  2785         else:
       
  2786             raise ValueError, _("\"%s\" is an invalid value!")%value
       
  2787     return items
       
  2788 
       
  2789 cls = PLCOpenClasses.get("value_arrayValue", None)
       
  2790 if cls:
       
  2791     arrayValue_model = re.compile("([0-9]*)\((.*)\)$")
       
  2792     
       
  2793     def setvalue(self, value):
       
  2794         self.value = []
       
  2795         for item in extractValues(value[1:-1]):
       
  2796             item = item.strip()
       
  2797             element = PLCOpenClasses["arrayValue_value"]()
       
  2798             result = arrayValue_model.match(item)
       
  2799             if result is not None:
       
  2800                 groups = result.groups()
       
  2801                 element.setrepetitionValue(groups[0])
       
  2802                 element.setvalue(groups[1].strip())
       
  2803             else:
       
  2804                 element.setvalue(item)
       
  2805             self.value.append(element)
       
  2806     setattr(cls, "setvalue", setvalue)
       
  2807     
       
  2808     def getvalue(self):
       
  2809         values = []
       
  2810         for element in self.value:
       
  2811             repetition = element.getrepetitionValue()
       
  2812             if repetition is not None and int(repetition) > 1:
       
  2813                 value = element.getvalue()
       
  2814                 if value is None:
       
  2815                     value = ""
       
  2816                 values.append("%s(%s)"%(repetition, value))
       
  2817             else:
       
  2818                 values.append(element.getvalue())
       
  2819         return "[%s]"%", ".join(values)
       
  2820     setattr(cls, "getvalue", getvalue)
       
  2821 
       
  2822 cls = PLCOpenClasses.get("value_structValue", None)
       
  2823 if cls:
       
  2824     structValue_model = re.compile("(.*):=(.*)")
       
  2825     
       
  2826     def setvalue(self, value):
       
  2827         self.value = []
       
  2828         for item in extractValues(value[1:-1]):
       
  2829             result = structValue_model.match(item)
       
  2830             if result is not None:
       
  2831                 groups = result.groups()
       
  2832                 element = PLCOpenClasses["structValue_value"]()
       
  2833                 element.setmember(groups[0].strip())
       
  2834                 element.setvalue(groups[1].strip())
       
  2835                 self.value.append(element)
       
  2836     setattr(cls, "setvalue", setvalue)
       
  2837     
       
  2838     def getvalue(self):
       
  2839         values = []
       
  2840         for element in self.value:
       
  2841             values.append("%s := %s"%(element.getmember(), element.getvalue()))
       
  2842         return "(%s)"%", ".join(values)
       
  2843     setattr(cls, "getvalue", getvalue)