plcopen/plcopen.py
branch1.1 Korean release
changeset 968 eee7625de1f7
parent 966 dc1318160073
child 990 7f57b969caed
equal deleted inserted replaced
808:6e205c1f05a0 968:eee7625de1f7
       
     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
       
   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
       
   143     setattr(cls, "updateElementName", updateElementName)
       
   144     
       
   145     def updateElementAddress(self, address_model, new_leading):
       
   146         text = self.text
       
   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
       
   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(("OUT", var_type["value"].getname(), "none"))
       
   452                 elif var_type["name"] in ["string", "wstring"]:
       
   453                     block_infos["outputs"].append(("OUT", var_type["name"].upper(), "none"))
       
   454                 else:
       
   455                     block_infos["outputs"].append(("OUT", 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                     if transitions[i].getbodyType() in ["FBD", "LD", "SFC"]:
       
  1439                         for instance in transitions[i].getinstances():
       
  1440                             if isinstance(instance, PLCOpenClasses["fbdObjects_block"]):
       
  1441                                 self.removepouVar(instance.gettypeName(), 
       
  1442                                                   instance.getinstanceName())
       
  1443                     transitions.pop(i)
       
  1444                     removed = True
       
  1445                 i += 1
       
  1446             if not removed:
       
  1447                 raise ValueError, _("Transition with name %s doesn't exist!")%name
       
  1448     setattr(cls, "removetransition", removetransition)
       
  1449 
       
  1450     def addaction(self, name, type):
       
  1451         if not self.actions:
       
  1452             self.addactions()
       
  1453             self.actions.setaction([])
       
  1454         action = PLCOpenClasses["actions_action"]()
       
  1455         action.setname(name)
       
  1456         action.setbodyType(type)
       
  1457         self.actions.appendaction(action)
       
  1458     setattr(cls, "addaction", addaction)
       
  1459     
       
  1460     def getaction(self, name):
       
  1461         if self.actions:
       
  1462             for action in self.actions.getaction():
       
  1463                 if action.getname() == name:
       
  1464                     return action
       
  1465         return None
       
  1466     setattr(cls, "getaction", getaction)
       
  1467     
       
  1468     def getactionList(self):
       
  1469         if self.actions:
       
  1470             return self.actions.getaction()
       
  1471         return []
       
  1472     setattr(cls, "getactionList", getactionList)
       
  1473     
       
  1474     def removeaction(self, name):
       
  1475         if self.actions:
       
  1476             actions = self.actions.getaction()
       
  1477             i = 0
       
  1478             removed = False
       
  1479             while i < len(actions) and not removed:
       
  1480                 if actions[i].getname() == name:
       
  1481                     if actions[i].getbodyType() in ["FBD", "LD", "SFC"]:
       
  1482                         for instance in actions[i].getinstances():
       
  1483                             if isinstance(instance, PLCOpenClasses["fbdObjects_block"]):
       
  1484                                 self.removepouVar(instance.gettypeName(), 
       
  1485                                                   instance.getinstanceName())
       
  1486                     actions.pop(i)
       
  1487                     removed = True
       
  1488                 i += 1
       
  1489             if not removed:
       
  1490                 raise ValueError, _("Action with name %s doesn't exist!")%name
       
  1491     setattr(cls, "removeaction", removeaction)
       
  1492 
       
  1493     def updateElementName(self, old_name, new_name):
       
  1494         if self.interface:
       
  1495             for content in self.interface.getcontent():
       
  1496                 for var in content["value"].getvariable():
       
  1497                     var_address = var.getaddress()
       
  1498                     if var_address is not None:
       
  1499                         if var_address == old_name:
       
  1500                             var.setaddress(new_name)
       
  1501                         if var.getname() == old_name:
       
  1502                             var.setname(new_name)
       
  1503                     var_type_content = var.gettype().getcontent()
       
  1504                     if var_type_content["name"] == "derived":
       
  1505                         if var_type_content["value"].getname() == old_name:
       
  1506                             var_type_content["value"].setname(new_name)
       
  1507         self.body[0].updateElementName(old_name, new_name)
       
  1508         for action in self.getactionList():
       
  1509             action.updateElementName(old_name, new_name)
       
  1510         for transition in self.gettransitionList():
       
  1511             transition.updateElementName(old_name, new_name)
       
  1512     setattr(cls, "updateElementName", updateElementName)
       
  1513 
       
  1514     def updateElementAddress(self, address_model, new_leading):
       
  1515         if self.interface:
       
  1516             for content in self.interface.getcontent():
       
  1517                 for var in content["value"].getvariable():
       
  1518                     var_address = var.getaddress()
       
  1519                     if var_address is not None:
       
  1520                         var.setaddress(update_address(var_address, address_model, new_leading))
       
  1521         self.body[0].updateElementAddress(address_model, new_leading)
       
  1522         for action in self.getactionList():
       
  1523             action.updateElementAddress(address_model, new_leading)
       
  1524         for transition in self.gettransitionList():
       
  1525             transition.updateElementAddress(address_model, new_leading)
       
  1526     setattr(cls, "updateElementAddress", updateElementAddress)
       
  1527 
       
  1528     def removeVariableByAddress(self, address):
       
  1529         if self.interface:
       
  1530             for content in self.interface.getcontent():
       
  1531                 variables = content["value"].getvariable()
       
  1532                 for i in xrange(len(variables)-1, -1, -1):
       
  1533                     if variables[i].getaddress() == address:
       
  1534                         variables.pop(i)
       
  1535     setattr(cls, "removeVariableByAddress", removeVariableByAddress)
       
  1536 
       
  1537     def removeVariableByFilter(self, address_model):
       
  1538         if self.interface:
       
  1539             for content in self.interface.getcontent():
       
  1540                 variables = content["value"].getvariable()
       
  1541                 for i in xrange(len(variables)-1, -1, -1):
       
  1542                     var_address = variables[i].getaddress()
       
  1543                     if var_address is not None:
       
  1544                         result = address_model.match(var_address)
       
  1545                         if result is not None:
       
  1546                             variables.pop(i)
       
  1547     setattr(cls, "removeVariableByFilter", removeVariableByFilter)
       
  1548     
       
  1549     def Search(self, criteria, parent_infos=[]):
       
  1550         search_result = []
       
  1551         filter = criteria["filter"]
       
  1552         if filter == "all" or self.getpouType() in filter:
       
  1553             parent_infos = parent_infos + ["P::%s" % self.getname()]
       
  1554             search_result.extend(_Search([("name", self.getname())], criteria, parent_infos))
       
  1555             if self.interface is not None:
       
  1556                 var_number = 0
       
  1557                 for content in self.interface.getcontent():
       
  1558                     variable_type = searchResultVarTypes.get(content["value"], "var_local")
       
  1559                     variables = content["value"].getvariable()
       
  1560                     for modifier, has_modifier in [("constant", content["value"].getconstant()),
       
  1561                                                    ("retain", content["value"].getretain()),
       
  1562                                                    ("non_retain", content["value"].getnonretain())]:
       
  1563                         if has_modifier:
       
  1564                             for result in TestTextElement(modifier, criteria):
       
  1565                                 search_result.append((tuple(parent_infos + [variable_type, (var_number, var_number + len(variables)), modifier]),) + result)
       
  1566                             break
       
  1567                     for variable in variables:
       
  1568                         search_result.extend(variable.Search(criteria, parent_infos + [variable_type, var_number]))
       
  1569                         var_number += 1
       
  1570             if len(self.body) > 0:
       
  1571                 search_result.extend(self.body[0].Search(criteria, parent_infos))
       
  1572             for action in self.getactionList():
       
  1573                 search_result.extend(action.Search(criteria, parent_infos))
       
  1574             for transition in self.gettransitionList():
       
  1575                 search_result.extend(transition.Search(criteria, parent_infos))
       
  1576         return search_result
       
  1577     setattr(cls, "Search", Search)
       
  1578 
       
  1579 def setbodyType(self, type):
       
  1580     if type == "IL":
       
  1581         self.body.setcontent({"name" : "IL", "value" : PLCOpenClasses["formattedText"]()})
       
  1582     elif type == "ST":
       
  1583         self.body.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
       
  1584     elif type == "LD":
       
  1585         self.body.setcontent({"name" : "LD", "value" : PLCOpenClasses["body_LD"]()})
       
  1586     elif type == "FBD":
       
  1587         self.body.setcontent({"name" : "FBD", "value" : PLCOpenClasses["body_FBD"]()})
       
  1588     elif type == "SFC":
       
  1589         self.body.setcontent({"name" : "SFC", "value" : PLCOpenClasses["body_SFC"]()})
       
  1590     else:
       
  1591         raise ValueError, "%s isn't a valid body type!"%type
       
  1592 
       
  1593 def getbodyType(self):
       
  1594     return self.body.getcontent()["name"]
       
  1595 
       
  1596 def resetexecutionOrder(self):
       
  1597     self.body.resetexecutionOrder()
       
  1598 
       
  1599 def compileexecutionOrder(self):
       
  1600     self.body.compileexecutionOrder()
       
  1601 
       
  1602 def setelementExecutionOrder(self, instance, new_executionOrder):
       
  1603     self.body.setelementExecutionOrder(instance, new_executionOrder)
       
  1604 
       
  1605 def addinstance(self, name, instance):
       
  1606     self.body.appendcontentInstance(name, instance)
       
  1607 
       
  1608 def getinstances(self):
       
  1609     return self.body.getcontentInstances()
       
  1610 
       
  1611 def getinstance(self, id):
       
  1612     return self.body.getcontentInstance(id)
       
  1613 
       
  1614 def getrandomInstance(self, exclude):
       
  1615     return self.body.getcontentRandomInstance(exclude)
       
  1616 
       
  1617 def getinstanceByName(self, name):
       
  1618     return self.body.getcontentInstanceByName(name)
       
  1619 
       
  1620 def removeinstance(self, id):
       
  1621     self.body.removecontentInstance(id)
       
  1622 
       
  1623 def settext(self, text):
       
  1624     self.body.settext(text)
       
  1625 
       
  1626 def gettext(self):
       
  1627     return self.body.gettext()
       
  1628 
       
  1629 cls = PLCOpenClasses.get("transitions_transition", None)
       
  1630 if cls:
       
  1631     setattr(cls, "setbodyType", setbodyType)
       
  1632     setattr(cls, "getbodyType", getbodyType)
       
  1633     setattr(cls, "resetexecutionOrder", resetexecutionOrder)
       
  1634     setattr(cls, "compileexecutionOrder", compileexecutionOrder)
       
  1635     setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
       
  1636     setattr(cls, "addinstance", addinstance)
       
  1637     setattr(cls, "getinstances", getinstances)
       
  1638     setattr(cls, "getinstance", getinstance)
       
  1639     setattr(cls, "getrandomInstance", getrandomInstance)
       
  1640     setattr(cls, "getinstanceByName", getinstanceByName)
       
  1641     setattr(cls, "removeinstance", removeinstance)
       
  1642     setattr(cls, "settext", settext)
       
  1643     setattr(cls, "gettext", gettext)
       
  1644 
       
  1645     def updateElementName(self, old_name, new_name):
       
  1646         self.body.updateElementName(old_name, new_name)
       
  1647     setattr(cls, "updateElementName", updateElementName)
       
  1648 
       
  1649     def updateElementAddress(self, address_model, new_leading):
       
  1650         self.body.updateElementAddress(address_model, new_leading)
       
  1651     setattr(cls, "updateElementAddress", updateElementAddress)
       
  1652 
       
  1653     def hasblock(self, name):
       
  1654         if self.getbodyType() in ["FBD", "LD", "SFC"]:
       
  1655             for instance in self.getinstances():
       
  1656                 if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
       
  1657                     return True
       
  1658         return False
       
  1659     setattr(cls, "hasblock", hasblock)
       
  1660 
       
  1661     def Search(self, criteria, parent_infos):
       
  1662         search_result = []
       
  1663         parent_infos = parent_infos[:-1] + ["T::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())]
       
  1664         for result in TestTextElement(self.getname(), criteria):
       
  1665             search_result.append((tuple(parent_infos + ["name"]),) + result)
       
  1666         search_result.extend(self.body.Search(criteria, parent_infos))
       
  1667         return search_result
       
  1668     setattr(cls, "Search", Search)
       
  1669 
       
  1670 cls = PLCOpenClasses.get("actions_action", None)
       
  1671 if cls:
       
  1672     setattr(cls, "setbodyType", setbodyType)
       
  1673     setattr(cls, "getbodyType", getbodyType)
       
  1674     setattr(cls, "resetexecutionOrder", resetexecutionOrder)
       
  1675     setattr(cls, "compileexecutionOrder", compileexecutionOrder)
       
  1676     setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
       
  1677     setattr(cls, "addinstance", addinstance)
       
  1678     setattr(cls, "getinstances", getinstances)
       
  1679     setattr(cls, "getinstance", getinstance)
       
  1680     setattr(cls, "getrandomInstance", getrandomInstance)
       
  1681     setattr(cls, "getinstanceByName", getinstanceByName)
       
  1682     setattr(cls, "removeinstance", removeinstance)
       
  1683     setattr(cls, "settext", settext)
       
  1684     setattr(cls, "gettext", gettext)
       
  1685 
       
  1686     def updateElementName(self, old_name, new_name):
       
  1687         self.body.updateElementName(old_name, new_name)
       
  1688     setattr(cls, "updateElementName", updateElementName)
       
  1689 
       
  1690     def updateElementAddress(self, address_model, new_leading):
       
  1691         self.body.updateElementAddress(address_model, new_leading)
       
  1692     setattr(cls, "updateElementAddress", updateElementAddress)
       
  1693 
       
  1694     def hasblock(self, name):
       
  1695         if self.getbodyType() in ["FBD", "LD", "SFC"]:
       
  1696             for instance in self.getinstances():
       
  1697                 if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
       
  1698                     return True
       
  1699         return False
       
  1700     setattr(cls, "hasblock", hasblock)
       
  1701 
       
  1702     def Search(self, criteria, parent_infos):
       
  1703         search_result = []
       
  1704         parent_infos = parent_infos[:-1] + ["A::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())]
       
  1705         for result in TestTextElement(self.getname(), criteria):
       
  1706             search_result.append((tuple(parent_infos + ["name"]),) + result)
       
  1707         search_result.extend(self.body.Search(criteria, parent_infos))
       
  1708         return search_result
       
  1709     setattr(cls, "Search", Search)
       
  1710 
       
  1711 cls = PLCOpenClasses.get("body", None)
       
  1712 if cls:
       
  1713     cls.currentExecutionOrderId = 0
       
  1714     
       
  1715     def resetcurrentExecutionOrderId(self):
       
  1716         object.__setattr__(self, "currentExecutionOrderId", 0)
       
  1717     setattr(cls, "resetcurrentExecutionOrderId", resetcurrentExecutionOrderId)
       
  1718     
       
  1719     def getnewExecutionOrderId(self):
       
  1720         object.__setattr__(self, "currentExecutionOrderId", self.currentExecutionOrderId + 1)
       
  1721         return self.currentExecutionOrderId
       
  1722     setattr(cls, "getnewExecutionOrderId", getnewExecutionOrderId)
       
  1723     
       
  1724     def resetexecutionOrder(self):
       
  1725         if self.content["name"] == "FBD":
       
  1726             for element in self.content["value"].getcontent():
       
  1727                 if not isinstance(element["value"], (PLCOpenClasses.get("commonObjects_comment", None), 
       
  1728                                                      PLCOpenClasses.get("commonObjects_connector", None), 
       
  1729                                                      PLCOpenClasses.get("commonObjects_continuation", None))):
       
  1730                     element["value"].setexecutionOrderId(0)
       
  1731         else:
       
  1732             raise TypeError, _("Can only generate execution order on FBD networks!")
       
  1733     setattr(cls, "resetexecutionOrder", resetexecutionOrder)
       
  1734     
       
  1735     def compileexecutionOrder(self):
       
  1736         if self.content["name"] == "FBD":
       
  1737             self.resetexecutionOrder()
       
  1738             self.resetcurrentExecutionOrderId()
       
  1739             for element in self.content["value"].getcontent():
       
  1740                 if isinstance(element["value"], PLCOpenClasses.get("fbdObjects_outVariable", None)) and element["value"].getexecutionOrderId() == 0:
       
  1741                     connections = element["value"].connectionPointIn.getconnections()
       
  1742                     if connections and len(connections) == 1:
       
  1743                         self.compileelementExecutionOrder(connections[0])
       
  1744                     element["value"].setexecutionOrderId(self.getnewExecutionOrderId())
       
  1745         else:
       
  1746             raise TypeError, _("Can only generate execution order on FBD networks!")
       
  1747     setattr(cls, "compileexecutionOrder", compileexecutionOrder)
       
  1748     
       
  1749     def compileelementExecutionOrder(self, link):
       
  1750         if self.content["name"] == "FBD":
       
  1751             localid = link.getrefLocalId()
       
  1752             instance = self.getcontentInstance(localid)
       
  1753             if isinstance(instance, PLCOpenClasses.get("fbdObjects_block", None)) and instance.getexecutionOrderId() == 0:
       
  1754                 for variable in instance.inputVariables.getvariable():
       
  1755                     connections = variable.connectionPointIn.getconnections()
       
  1756                     if connections and len(connections) == 1:
       
  1757                         self.compileelementExecutionOrder(connections[0])
       
  1758                 instance.setexecutionOrderId(self.getnewExecutionOrderId())
       
  1759             elif isinstance(instance, PLCOpenClasses.get("commonObjects_continuation", None)) and instance.getexecutionOrderId() == 0:
       
  1760                 name = instance.getname()
       
  1761                 for tmp_instance in self.getcontentInstances():
       
  1762                     if isinstance(tmp_instance, PLCOpenClasses.get("commonObjects_connector", None)) and tmp_instance.getname() == name and tmp_instance.getexecutionOrderId() == 0:
       
  1763                         connections = tmp_instance.connectionPointIn.getconnections()
       
  1764                         if connections and len(connections) == 1:
       
  1765                             self.compileelementExecutionOrder(connections[0])
       
  1766         else:
       
  1767             raise TypeError, _("Can only generate execution order on FBD networks!")
       
  1768     setattr(cls, "compileelementExecutionOrder", compileelementExecutionOrder)
       
  1769     
       
  1770     def setelementExecutionOrder(self, instance, new_executionOrder):
       
  1771         if self.content["name"] == "FBD":
       
  1772             old_executionOrder = instance.getexecutionOrderId()
       
  1773             if old_executionOrder is not None and old_executionOrder != 0 and new_executionOrder != 0:
       
  1774                 for element in self.content["value"].getcontent():
       
  1775                     if element["value"] != instance and not isinstance(element["value"], PLCOpenClasses.get("commonObjects_comment", None)):
       
  1776                         element_executionOrder = element["value"].getexecutionOrderId()
       
  1777                         if old_executionOrder <= element_executionOrder <= new_executionOrder:
       
  1778                             element["value"].setexecutionOrderId(element_executionOrder - 1)
       
  1779                         if new_executionOrder <= element_executionOrder <= old_executionOrder:
       
  1780                             element["value"].setexecutionOrderId(element_executionOrder + 1)
       
  1781             instance.setexecutionOrderId(new_executionOrder)
       
  1782         else:
       
  1783             raise TypeError, _("Can only generate execution order on FBD networks!")
       
  1784     setattr(cls, "setelementExecutionOrder", setelementExecutionOrder)
       
  1785     
       
  1786     def appendcontentInstance(self, name, instance):
       
  1787         if self.content["name"] in ["LD","FBD","SFC"]:
       
  1788             self.content["value"].appendcontent({"name" : name, "value" : instance})
       
  1789         else:
       
  1790             raise TypeError, _("%s body don't have instances!")%self.content["name"]
       
  1791     setattr(cls, "appendcontentInstance", appendcontentInstance)
       
  1792     
       
  1793     def getcontentInstances(self):
       
  1794         if self.content["name"] in ["LD","FBD","SFC"]:
       
  1795             instances = []
       
  1796             for element in self.content["value"].getcontent():
       
  1797                 instances.append(element["value"])
       
  1798             return instances
       
  1799         else:
       
  1800             raise TypeError, _("%s body don't have instances!")%self.content["name"]
       
  1801     setattr(cls, "getcontentInstances", getcontentInstances)
       
  1802 
       
  1803     def getcontentInstance(self, id):
       
  1804         if self.content["name"] in ["LD","FBD","SFC"]:
       
  1805             for element in self.content["value"].getcontent():
       
  1806                 if element["value"].getlocalId() == id:
       
  1807                     return element["value"]
       
  1808             return None
       
  1809         else:
       
  1810             raise TypeError, _("%s body don't have instances!")%self.content["name"]
       
  1811     setattr(cls, "getcontentInstance", getcontentInstance)
       
  1812     
       
  1813     def getcontentRandomInstance(self, exclude):
       
  1814         if self.content["name"] in ["LD","FBD","SFC"]:
       
  1815             for element in self.content["value"].getcontent():
       
  1816                 if element["value"].getlocalId() not in exclude:
       
  1817                     return element["value"]
       
  1818             return None
       
  1819         else:
       
  1820             raise TypeError, _("%s body don't have instances!")%self.content["name"]
       
  1821     setattr(cls, "getcontentRandomInstance", getcontentRandomInstance)
       
  1822     
       
  1823     def getcontentInstanceByName(self, name):
       
  1824         if self.content["name"] in ["LD","FBD","SFC"]:
       
  1825             for element in self.content["value"].getcontent():
       
  1826                 if isinstance(element["value"], PLCOpenClasses.get("fbdObjects_block", None)) and element["value"].getinstanceName() == name:
       
  1827                     return element["value"]
       
  1828         else:
       
  1829             raise TypeError, _("%s body don't have instances!")%self.content["name"]
       
  1830     setattr(cls, "getcontentInstanceByName", getcontentInstanceByName)
       
  1831     
       
  1832     def removecontentInstance(self, id):
       
  1833         if self.content["name"] in ["LD","FBD","SFC"]:
       
  1834             i = 0
       
  1835             removed = False
       
  1836             elements = self.content["value"].getcontent()
       
  1837             while i < len(elements) and not removed:
       
  1838                 if elements[i]["value"].getlocalId() == id:
       
  1839                     self.content["value"].removecontent(i)
       
  1840                     removed = True
       
  1841                 i += 1
       
  1842             if not removed:
       
  1843                 raise ValueError, _("Instance with id %d doesn't exist!")%id
       
  1844         else:
       
  1845             raise TypeError, "%s body don't have instances!"%self.content["name"]
       
  1846     setattr(cls, "removecontentInstance", removecontentInstance)
       
  1847     
       
  1848     def settext(self, text):
       
  1849         if self.content["name"] in ["IL","ST"]:
       
  1850             self.content["value"].settext(text)
       
  1851         else:
       
  1852             raise TypeError, _("%s body don't have text!")%self.content["name"]
       
  1853     setattr(cls, "settext", settext)
       
  1854 
       
  1855     def gettext(self):
       
  1856         if self.content["name"] in ["IL","ST"]:
       
  1857             return self.content["value"].gettext()
       
  1858         else:
       
  1859             raise TypeError, _("%s body don't have text!")%self.content["name"]
       
  1860     setattr(cls, "gettext", gettext)
       
  1861     
       
  1862     def updateElementName(self, old_name, new_name):
       
  1863         if self.content["name"] in ["IL", "ST"]:
       
  1864             self.content["value"].updateElementName(old_name, new_name)
       
  1865         else:
       
  1866             for element in self.content["value"].getcontent():
       
  1867                 element["value"].updateElementName(old_name, new_name)
       
  1868     setattr(cls, "updateElementName", updateElementName)
       
  1869 
       
  1870     def updateElementAddress(self, address_model, new_leading):
       
  1871         if self.content["name"] in ["IL", "ST"]:
       
  1872             self.content["value"].updateElementAddress(address_model, new_leading)
       
  1873         else:
       
  1874             for element in self.content["value"].getcontent():
       
  1875                 element["value"].updateElementAddress(address_model, new_leading)
       
  1876     setattr(cls, "updateElementAddress", updateElementAddress)
       
  1877 
       
  1878     def Search(self, criteria, parent_infos=[]):
       
  1879         if self.content["name"] in ["IL", "ST"]:
       
  1880             search_result = self.content["value"].Search(criteria, parent_infos + ["body", 0])
       
  1881         else:
       
  1882             search_result = []
       
  1883             for element in self.content["value"].getcontent():
       
  1884                 search_result.extend(element["value"].Search(criteria, parent_infos))
       
  1885         return search_result
       
  1886     setattr(cls, "Search", Search)
       
  1887 
       
  1888 def getx(self):
       
  1889     return self.position.getx()
       
  1890 
       
  1891 def gety(self):
       
  1892     return self.position.gety()
       
  1893 
       
  1894 def setx(self, x):
       
  1895     self.position.setx(x)
       
  1896     
       
  1897 def sety(self, y):
       
  1898     self.position.sety(y)
       
  1899 
       
  1900 def _getBoundingBox(self):
       
  1901     return rect(self.getx(), self.gety(), self.getwidth(), self.getheight())
       
  1902 
       
  1903 def _getConnectionsBoundingBox(connectionPointIn):
       
  1904     bbox = rect()
       
  1905     connections = connectionPointIn.getconnections()
       
  1906     if connections is not None:
       
  1907         for connection in connections:
       
  1908             for x, y in connection.getpoints():
       
  1909                 bbox.update(x, y)
       
  1910     return bbox
       
  1911 
       
  1912 def _getBoundingBoxSingle(self):
       
  1913     bbox = _getBoundingBox(self)
       
  1914     if self.connectionPointIn is not None:
       
  1915         bbox.union(_getConnectionsBoundingBox(self.connectionPointIn))
       
  1916     return bbox
       
  1917 
       
  1918 def _getBoundingBoxMultiple(self):
       
  1919     bbox = _getBoundingBox(self)
       
  1920     for connectionPointIn in self.getconnectionPointIn():
       
  1921         bbox.union(_getConnectionsBoundingBox(connectionPointIn))
       
  1922     return bbox
       
  1923 
       
  1924 def _filterConnections(connectionPointIn, localId, connections):
       
  1925     in_connections = connectionPointIn.getconnections()
       
  1926     if in_connections is not None:
       
  1927         to_delete = []
       
  1928         for i, connection in enumerate(in_connections):
       
  1929             connected = connection.getrefLocalId()
       
  1930             if not connections.has_key((localId, connected)) and \
       
  1931                not connections.has_key((connected, localId)):
       
  1932                 to_delete.append(i)
       
  1933         to_delete.reverse()
       
  1934         for i in to_delete:
       
  1935             connectionPointIn.removeconnection(i)
       
  1936 
       
  1937 def _filterConnectionsSingle(self, connections):
       
  1938     if self.connectionPointIn is not None:
       
  1939         _filterConnections(self.connectionPointIn, self.localId, connections)
       
  1940 
       
  1941 def _filterConnectionsMultiple(self, connections):
       
  1942     for connectionPointIn in self.getconnectionPointIn():
       
  1943         _filterConnections(connectionPointIn, self.localId, connections)
       
  1944 
       
  1945 def _getconnectionsdefinition(instance, connections_end):
       
  1946     id = instance.getlocalId()
       
  1947     return dict([((id, end), True) for end in connections_end])
       
  1948 
       
  1949 def _updateConnectionsId(connectionPointIn, translation):
       
  1950     connections_end = []
       
  1951     connections = connectionPointIn.getconnections()
       
  1952     if connections is not None:
       
  1953         for connection in connections:
       
  1954             refLocalId = connection.getrefLocalId()
       
  1955             new_reflocalId = translation.get(refLocalId, refLocalId)
       
  1956             connection.setrefLocalId(new_reflocalId)
       
  1957             connections_end.append(new_reflocalId)
       
  1958     return connections_end
       
  1959 
       
  1960 def _updateConnectionsIdSingle(self, translation):
       
  1961     connections_end = []
       
  1962     if self.connectionPointIn is not None:
       
  1963         connections_end = _updateConnectionsId(self.connectionPointIn, translation)
       
  1964     return _getconnectionsdefinition(self, connections_end)
       
  1965 
       
  1966 def _updateConnectionsIdMultiple(self, translation):
       
  1967     connections_end = []
       
  1968     for connectionPointIn in self.getconnectionPointIn():
       
  1969         connections_end.extend(_updateConnectionsId(connectionPointIn, translation))
       
  1970     return _getconnectionsdefinition(self, connections_end)
       
  1971 
       
  1972 def _translate(self, dx, dy):
       
  1973     self.setx(self.getx() + dx)
       
  1974     self.sety(self.gety() + dy)
       
  1975     
       
  1976 def _translateConnections(connectionPointIn, dx, dy):
       
  1977     connections = connectionPointIn.getconnections()
       
  1978     if connections is not None:
       
  1979         for connection in connections:
       
  1980             for position in connection.getposition():
       
  1981                 position.setx(position.getx() + dx)
       
  1982                 position.sety(position.gety() + dy)
       
  1983 
       
  1984 def _translateSingle(self, dx, dy):
       
  1985     _translate(self, dx, dy)
       
  1986     if self.connectionPointIn is not None:
       
  1987         _translateConnections(self.connectionPointIn, dx, dy)
       
  1988 
       
  1989 def _translateMultiple(self, dx, dy):
       
  1990     _translate(self, dx, dy)
       
  1991     for connectionPointIn in self.getconnectionPointIn():
       
  1992         _translateConnections(connectionPointIn, dx, dy)
       
  1993 
       
  1994 def _updateElementName(self, old_name, new_name):
       
  1995     pass
       
  1996 
       
  1997 def _updateElementAddress(self, address_model, new_leading):
       
  1998     pass
       
  1999 
       
  2000 def _SearchInElement(self, criteria, parent_infos=[]):
       
  2001     return []
       
  2002 
       
  2003 _connectionsFunctions = {
       
  2004     "bbox": {"none": _getBoundingBox,
       
  2005              "single": _getBoundingBoxSingle,
       
  2006              "multiple": _getBoundingBoxMultiple},
       
  2007     "translate": {"none": _translate,
       
  2008                "single": _translateSingle,
       
  2009                "multiple": _translateMultiple},
       
  2010     "filter": {"none": lambda self, connections: None,
       
  2011                "single": _filterConnectionsSingle,
       
  2012                "multiple": _filterConnectionsMultiple},
       
  2013     "update": {"none": lambda self, translation: {},
       
  2014                "single": _updateConnectionsIdSingle,
       
  2015                "multiple": _updateConnectionsIdMultiple},
       
  2016 }
       
  2017 
       
  2018 def _initElementClass(name, classname, connectionPointInType="none"):
       
  2019     ElementNameToClass[name] = classname
       
  2020     cls = PLCOpenClasses.get(classname, None)
       
  2021     if cls:
       
  2022         setattr(cls, "getx", getx)
       
  2023         setattr(cls, "gety", gety)
       
  2024         setattr(cls, "setx", setx)
       
  2025         setattr(cls, "sety", sety)
       
  2026         setattr(cls, "updateElementName", _updateElementName)
       
  2027         setattr(cls, "updateElementAddress", _updateElementAddress)
       
  2028         setattr(cls, "getBoundingBox", _connectionsFunctions["bbox"][connectionPointInType])
       
  2029         setattr(cls, "translate", _connectionsFunctions["translate"][connectionPointInType])
       
  2030         setattr(cls, "filterConnections", _connectionsFunctions["filter"][connectionPointInType])
       
  2031         setattr(cls, "updateConnectionsId", _connectionsFunctions["update"][connectionPointInType])
       
  2032         setattr(cls, "Search", _SearchInElement)
       
  2033     return cls
       
  2034 
       
  2035 def _getexecutionOrder(instance, specific_values):
       
  2036     executionOrder = instance.getexecutionOrderId()
       
  2037     if executionOrder is None:
       
  2038         executionOrder = 0
       
  2039     specific_values["executionOrder"] = executionOrder
       
  2040     
       
  2041 def _getdefaultmodifiers(instance, infos):
       
  2042     infos["negated"] = instance.getnegated()
       
  2043     infos["edge"] = instance.getedge()
       
  2044 
       
  2045 def _getinputmodifiers(instance, infos):
       
  2046     infos["negated"] = instance.getnegatedIn()
       
  2047     infos["edge"] = instance.getedgeIn()
       
  2048 
       
  2049 def _getoutputmodifiers(instance, infos):
       
  2050     infos["negated"] = instance.getnegatedOut()
       
  2051     infos["edge"] = instance.getedgeOut()
       
  2052 
       
  2053 MODIFIERS_FUNCTIONS = {"default": _getdefaultmodifiers,
       
  2054                        "input": _getinputmodifiers,
       
  2055                        "output": _getoutputmodifiers}
       
  2056 
       
  2057 def _getconnectioninfos(instance, connection, links=False, modifiers=None, parameter=False):
       
  2058     infos = {"position": connection.getrelPositionXY()}
       
  2059     if parameter:
       
  2060         infos["name"] = instance.getformalParameter()
       
  2061     MODIFIERS_FUNCTIONS.get(modifiers, lambda x, y: None)(instance, infos)
       
  2062     if links:
       
  2063         infos["links"] = []
       
  2064         connections = connection.getconnections()
       
  2065         if connections is not None:
       
  2066             for link in connections:
       
  2067                 dic = {"refLocalId": link.getrefLocalId(),
       
  2068                        "points": link.getpoints(),
       
  2069                        "formalParameter": link.getformalParameter()}
       
  2070                 infos["links"].append(dic)
       
  2071     return infos
       
  2072 
       
  2073 def _getelementinfos(instance):
       
  2074     return {"id": instance.getlocalId(),
       
  2075             "x": instance.getx(),
       
  2076             "y": instance.gety(),
       
  2077             "height": instance.getheight(),
       
  2078             "width": instance.getwidth(),
       
  2079             "specific_values": {},
       
  2080             "inputs": [],
       
  2081             "outputs": []}
       
  2082 
       
  2083 def _getvariableinfosFunction(type, input, output):
       
  2084     def getvariableinfos(self):
       
  2085         infos = _getelementinfos(self)
       
  2086         infos["type"] = type
       
  2087         specific_values = infos["specific_values"]
       
  2088         specific_values["name"] = self.getexpression()
       
  2089         _getexecutionOrder(self, specific_values)
       
  2090         if input and output:
       
  2091             infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True, "input"))
       
  2092             infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut, False, "output"))
       
  2093         elif input:
       
  2094             infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True, "default"))
       
  2095         elif output:
       
  2096             infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut, False, "default"))
       
  2097         return infos
       
  2098     return getvariableinfos
       
  2099 
       
  2100 def _getconnectorinfosFunction(type):
       
  2101     def getvariableinfos(self):
       
  2102         infos = _getelementinfos(self)
       
  2103         infos["type"] = type
       
  2104         infos["specific_values"]["name"] = self.getname()
       
  2105         if type == "connector":
       
  2106             infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2107         elif type == "continuation":
       
  2108             infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
       
  2109         return infos
       
  2110     return getvariableinfos
       
  2111 
       
  2112 def _getpowerrailinfosFunction(type):
       
  2113     def getpowerrailinfos(self):
       
  2114         infos = _getelementinfos(self)
       
  2115         infos["type"] = type
       
  2116         if type == "rightPowerRail":
       
  2117             for connectionPointIn in self.getconnectionPointIn():
       
  2118                 infos["inputs"].append(_getconnectioninfos(self, connectionPointIn, True))
       
  2119             infos["specific_values"]["connectors"] = len(infos["inputs"])
       
  2120         elif type == "leftPowerRail":
       
  2121             for connectionPointOut in self.getconnectionPointOut():
       
  2122                 infos["outputs"].append(_getconnectioninfos(self, connectionPointOut))
       
  2123             infos["specific_values"]["connectors"] = len(infos["outputs"])
       
  2124         return infos
       
  2125     return getpowerrailinfos
       
  2126 
       
  2127 def _getldelementinfosFunction(type):
       
  2128     def getldelementinfos(self):
       
  2129         infos = _getelementinfos(self)
       
  2130         infos["type"] = type
       
  2131         specific_values = infos["specific_values"]
       
  2132         specific_values["name"] = self.getvariable()
       
  2133         _getexecutionOrder(self, specific_values)
       
  2134         specific_values["negated"] = self.getnegated()
       
  2135         specific_values["edge"] = self.getedge()
       
  2136         if type == "coil":
       
  2137             specific_values["storage"] = self.getstorage()
       
  2138         infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2139         infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
       
  2140         return infos
       
  2141     return getldelementinfos
       
  2142 
       
  2143 DIVERGENCE_TYPES = {(True, True): "simultaneousDivergence",
       
  2144                     (True, False): "selectionDivergence",
       
  2145                     (False, True): "simultaneousConvergence",
       
  2146                     (False, False): "selectionConvergence"}
       
  2147 
       
  2148 def _getdivergenceinfosFunction(divergence, simultaneous):
       
  2149     def getdivergenceinfos(self):
       
  2150         infos = _getelementinfos(self)
       
  2151         infos["type"] = DIVERGENCE_TYPES[(divergence, simultaneous)]
       
  2152         if divergence:
       
  2153             infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2154             for connectionPointOut in self.getconnectionPointOut():
       
  2155                 infos["outputs"].append(_getconnectioninfos(self, connectionPointOut))
       
  2156             infos["specific_values"]["connectors"] = len(infos["outputs"])
       
  2157         else:
       
  2158             for connectionPointIn in self.getconnectionPointIn():
       
  2159                 infos["inputs"].append(_getconnectioninfos(self, connectionPointIn, True))
       
  2160             infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
       
  2161             infos["specific_values"]["connectors"] = len(infos["inputs"])
       
  2162         return infos
       
  2163     return getdivergenceinfos
       
  2164 
       
  2165 cls = _initElementClass("comment", "commonObjects_comment")
       
  2166 if cls:
       
  2167     def getinfos(self):
       
  2168         infos = _getelementinfos(self)
       
  2169         infos["type"] = "comment"
       
  2170         infos["specific_values"]["content"] = self.getcontentText()
       
  2171         return infos
       
  2172     setattr(cls, "getinfos", getinfos)
       
  2173     
       
  2174     def setcontentText(self, text):
       
  2175         self.content.settext(text)
       
  2176     setattr(cls, "setcontentText", setcontentText)
       
  2177         
       
  2178     def getcontentText(self):
       
  2179         return self.content.gettext()
       
  2180     setattr(cls, "getcontentText", getcontentText)
       
  2181     
       
  2182     def updateElementName(self, old_name, new_name):
       
  2183         self.content.updateElementName(old_name, new_name)
       
  2184     setattr(cls, "updateElementName", updateElementName)
       
  2185 
       
  2186     def updateElementAddress(self, address_model, new_leading):
       
  2187         self.content.updateElementAddress(address_model, new_leading)
       
  2188     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2189 
       
  2190     def Search(self, criteria, parent_infos=[]):
       
  2191         return self.content.Search(criteria, parent_infos + ["comment", self.getlocalId(), "content"])
       
  2192     setattr(cls, "Search", Search)
       
  2193 
       
  2194 cls = _initElementClass("block", "fbdObjects_block")
       
  2195 if cls:
       
  2196     def getBoundingBox(self):
       
  2197         bbox = _getBoundingBox(self)
       
  2198         for input in self.inputVariables.getvariable():
       
  2199             bbox.union(_getConnectionsBoundingBox(input.connectionPointIn))
       
  2200         return bbox
       
  2201     setattr(cls, "getBoundingBox", getBoundingBox)
       
  2202 
       
  2203     def getinfos(self):
       
  2204         infos = _getelementinfos(self)
       
  2205         infos["type"] = self.gettypeName()
       
  2206         specific_values = infos["specific_values"]
       
  2207         specific_values["name"] = self.getinstanceName()
       
  2208         _getexecutionOrder(self, specific_values)
       
  2209         for variable in self.inputVariables.getvariable():
       
  2210             infos["inputs"].append(_getconnectioninfos(variable, variable.connectionPointIn, True, "default", True))
       
  2211         for variable in self.outputVariables.getvariable():
       
  2212             infos["outputs"].append(_getconnectioninfos(variable, variable.connectionPointOut, False, "default", True))
       
  2213         return infos
       
  2214     setattr(cls, "getinfos", getinfos)
       
  2215 
       
  2216     def updateElementName(self, old_name, new_name):
       
  2217         if self.typeName == old_name:
       
  2218             self.typeName = new_name
       
  2219     setattr(cls, "updateElementName", updateElementName)
       
  2220 
       
  2221     def filterConnections(self, connections):
       
  2222         for input in self.inputVariables.getvariable():
       
  2223             _filterConnections(input.connectionPointIn, self.localId, connections)
       
  2224     setattr(cls, "filterConnections", filterConnections)
       
  2225 
       
  2226     def updateConnectionsId(self, translation):
       
  2227         connections_end = []
       
  2228         for input in self.inputVariables.getvariable():
       
  2229             connections_end.extend(_updateConnectionsId(input.connectionPointIn, translation))
       
  2230         return _getconnectionsdefinition(self, connections_end)
       
  2231     setattr(cls, "updateConnectionsId", updateConnectionsId)
       
  2232 
       
  2233     def translate(self, dx, dy):
       
  2234         _translate(self, dx, dy)
       
  2235         for input in self.inputVariables.getvariable():
       
  2236             _translateConnections(input.connectionPointIn, dx, dy)
       
  2237     setattr(cls, "translate", translate)
       
  2238 
       
  2239     def Search(self, criteria, parent_infos=[]):
       
  2240         parent_infos = parent_infos + ["block", self.getlocalId()]
       
  2241         search_result = _Search([("name", self.getinstanceName()),
       
  2242                                  ("type", self.gettypeName())],
       
  2243                                 criteria, parent_infos)
       
  2244         for i, variable in enumerate(self.inputVariables.getvariable()):
       
  2245             for result in TestTextElement(variable.getformalParameter(), criteria):
       
  2246                 search_result.append((tuple(parent_infos + ["input", i]),) + result)
       
  2247         for i, variable in enumerate(self.outputVariables.getvariable()):
       
  2248             for result in TestTextElement(variable.getformalParameter(), criteria):
       
  2249                 search_result.append((tuple(parent_infos + ["output", i]),) + result)
       
  2250         return search_result
       
  2251     setattr(cls, "Search", Search)
       
  2252 
       
  2253 cls = _initElementClass("leftPowerRail", "ldObjects_leftPowerRail")
       
  2254 if cls:
       
  2255     setattr(cls, "getinfos", _getpowerrailinfosFunction("leftPowerRail"))
       
  2256 
       
  2257 cls = _initElementClass("rightPowerRail", "ldObjects_rightPowerRail", "multiple")
       
  2258 if cls:
       
  2259     setattr(cls, "getinfos", _getpowerrailinfosFunction("rightPowerRail"))
       
  2260 
       
  2261 cls = _initElementClass("contact", "ldObjects_contact", "single")
       
  2262 if cls:
       
  2263     setattr(cls, "getinfos", _getldelementinfosFunction("contact"))
       
  2264     
       
  2265     def updateElementName(self, old_name, new_name):
       
  2266         if self.variable == old_name:
       
  2267             self.variable = new_name
       
  2268     setattr(cls, "updateElementName", updateElementName)
       
  2269     
       
  2270     def updateElementAddress(self, address_model, new_leading):
       
  2271         self.variable = update_address(self.variable, address_model, new_leading)
       
  2272     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2273     
       
  2274     def Search(self, criteria, parent_infos=[]):
       
  2275         return _Search([("reference", self.getvariable())], criteria, parent_infos + ["contact", self.getlocalId()])
       
  2276     setattr(cls, "Search", Search)
       
  2277 
       
  2278 cls = _initElementClass("coil", "ldObjects_coil", "single")
       
  2279 if cls:
       
  2280     setattr(cls, "getinfos", _getldelementinfosFunction("coil"))
       
  2281     
       
  2282     def updateElementName(self, old_name, new_name):
       
  2283         if self.variable == old_name:
       
  2284             self.variable = new_name
       
  2285     setattr(cls, "updateElementName", updateElementName)
       
  2286 
       
  2287     def updateElementAddress(self, address_model, new_leading):
       
  2288         self.variable = update_address(self.variable, address_model, new_leading)
       
  2289     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2290 
       
  2291     def Search(self, criteria, parent_infos=[]):
       
  2292         return _Search([("reference", self.getvariable())], criteria, parent_infos + ["coil", self.getlocalId()])
       
  2293     setattr(cls, "Search", Search)
       
  2294 
       
  2295 cls = _initElementClass("step", "sfcObjects_step", "single")
       
  2296 if cls:
       
  2297     def getinfos(self):
       
  2298         infos = _getelementinfos(self)
       
  2299         infos["type"] = "step"
       
  2300         specific_values = infos["specific_values"]
       
  2301         specific_values["name"] = self.getname()
       
  2302         specific_values["initial"] = self.getinitialStep()
       
  2303         if self.connectionPointIn:
       
  2304             infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2305         if self.connectionPointOut:
       
  2306             infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
       
  2307         if self.connectionPointOutAction:
       
  2308             specific_values["action"] = _getconnectioninfos(self, self.connectionPointOutAction)
       
  2309         return infos
       
  2310     setattr(cls, "getinfos", getinfos)
       
  2311 
       
  2312     def Search(self, criteria, parent_infos=[]):
       
  2313         return _Search([("name", self.getname())], criteria, parent_infos + ["step", self.getlocalId()])
       
  2314     setattr(cls, "Search", Search)
       
  2315 
       
  2316 cls = PLCOpenClasses.get("transition_condition", None)
       
  2317 if cls:
       
  2318     def compatibility(self, tree):
       
  2319         connections = []
       
  2320         for child in tree.childNodes:
       
  2321             if child.nodeName == "connection":
       
  2322                 connections.append(child)
       
  2323         if len(connections) > 0:
       
  2324             node = CreateNode("connectionPointIn")
       
  2325             relPosition = CreateNode("relPosition")
       
  2326             NodeSetAttr(relPosition, "x", "0")
       
  2327             NodeSetAttr(relPosition, "y", "0")
       
  2328             node.childNodes.append(relPosition)
       
  2329             node.childNodes.extend(connections)
       
  2330             tree.childNodes = [node]
       
  2331     setattr(cls, "compatibility", compatibility)
       
  2332 
       
  2333 cls = _initElementClass("transition", "sfcObjects_transition")
       
  2334 if cls:
       
  2335     def getinfos(self):
       
  2336         infos = _getelementinfos(self)
       
  2337         infos["type"] = "transition"
       
  2338         specific_values = infos["specific_values"]
       
  2339         priority = self.getpriority()
       
  2340         if priority is None:
       
  2341             priority = 0
       
  2342         specific_values["priority"] = priority
       
  2343         condition = self.getconditionContent()
       
  2344         specific_values["condition_type"] = condition["type"]
       
  2345         if specific_values["condition_type"] == "connection":
       
  2346             specific_values["connection"] = _getconnectioninfos(self, condition["value"], True)
       
  2347         else:
       
  2348             specific_values["condition"] = condition["value"]
       
  2349         infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2350         infos["outputs"].append(_getconnectioninfos(self, self.connectionPointOut))
       
  2351         return infos
       
  2352     setattr(cls, "getinfos", getinfos)
       
  2353 
       
  2354     def setconditionContent(self, type, value):
       
  2355         if not self.condition:
       
  2356             self.addcondition()
       
  2357         if type == "reference":
       
  2358             condition = PLCOpenClasses["condition_reference"]()
       
  2359             condition.setname(value)
       
  2360         elif type == "inline":
       
  2361             condition = PLCOpenClasses["condition_inline"]()
       
  2362             condition.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
       
  2363             condition.settext(value)
       
  2364         elif type == "connection":
       
  2365             type = "connectionPointIn"
       
  2366             condition = PLCOpenClasses["connectionPointIn"]()
       
  2367         self.condition.setcontent({"name" : type, "value" : condition})
       
  2368     setattr(cls, "setconditionContent", setconditionContent)
       
  2369         
       
  2370     def getconditionContent(self):
       
  2371         if self.condition:
       
  2372             content = self.condition.getcontent()
       
  2373             values = {"type" : content["name"]}
       
  2374             if values["type"] == "reference":
       
  2375                 values["value"] = content["value"].getname()
       
  2376             elif values["type"] == "inline":
       
  2377                 values["value"] = content["value"].gettext()
       
  2378             elif values["type"] == "connectionPointIn":
       
  2379                 values["type"] = "connection"
       
  2380                 values["value"] = content["value"]
       
  2381             return values
       
  2382         return ""
       
  2383     setattr(cls, "getconditionContent", getconditionContent)
       
  2384 
       
  2385     def getconditionConnection(self):
       
  2386         if self.condition:
       
  2387             content = self.condition.getcontent()
       
  2388             if content["name"] == "connectionPointIn":
       
  2389                 return content["value"]
       
  2390         return None
       
  2391     setattr(cls, "getconditionConnection", getconditionConnection)
       
  2392 
       
  2393     def getBoundingBox(self):
       
  2394         bbox = _getBoundingBoxSingle(self)
       
  2395         condition_connection = self.getconditionConnection()
       
  2396         if condition_connection:
       
  2397             bbox.union(_getConnectionsBoundingBox(condition_connection))
       
  2398         return bbox
       
  2399     setattr(cls, "getBoundingBox", getBoundingBox)
       
  2400     
       
  2401     def translate(self, dx, dy):
       
  2402         _translateSingle(self, dx, dy)
       
  2403         condition_connection = self.getconditionConnection()
       
  2404         if condition_connection:
       
  2405             _translateConnections(condition_connection, dx, dy)
       
  2406     setattr(cls, "translate", translate)
       
  2407     
       
  2408     def filterConnections(self, connections):
       
  2409         _filterConnectionsSingle(self, connections)
       
  2410         condition_connection = self.getconditionConnection()
       
  2411         if condition_connection:
       
  2412             _filterConnections(condition_connection, self.localId, connections)
       
  2413     setattr(cls, "filterConnections", filterConnections)
       
  2414     
       
  2415     def updateConnectionsId(self, translation):
       
  2416         connections_end = []
       
  2417         if self.connectionPointIn is not None:
       
  2418             connections_end = _updateConnectionsId(self.connectionPointIn, translation)
       
  2419         condition_connection = self.getconditionConnection()
       
  2420         if condition_connection:
       
  2421             connections_end.extend(_updateConnectionsId(condition_connection, translation))
       
  2422         return _getconnectionsdefinition(self, connections_end)
       
  2423     setattr(cls, "updateConnectionsId", updateConnectionsId)
       
  2424 
       
  2425     def updateElementName(self, old_name, new_name):
       
  2426         if self.condition:
       
  2427             content = self.condition.getcontent()
       
  2428             if content["name"] == "reference":
       
  2429                 if content["value"].getname() == old_name:
       
  2430                     content["value"].setname(new_name)
       
  2431             elif content["name"] == "inline":
       
  2432                 content["value"].updateElementName(old_name, new_name)
       
  2433     setattr(cls, "updateElementName", updateElementName)
       
  2434 
       
  2435     def updateElementAddress(self, address_model, new_leading):
       
  2436         if self.condition:
       
  2437             content = self.condition.getcontent()
       
  2438             if content["name"] == "reference":
       
  2439                 content["value"].setname(update_address(content["value"].getname(), address_model, new_leading))
       
  2440             elif content["name"] == "inline":
       
  2441                 content["value"].updateElementAddress(address_model, new_leading)
       
  2442     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2443 
       
  2444     def getconnections(self):
       
  2445         condition_connection = self.getconditionConnection()
       
  2446         if condition_connection:
       
  2447             return condition_connection.getconnections()
       
  2448         return None
       
  2449     setattr(cls, "getconnections", getconnections)
       
  2450     
       
  2451     def Search(self, criteria, parent_infos=[]):
       
  2452         parent_infos = parent_infos + ["transition", self.getlocalId()]
       
  2453         search_result = []
       
  2454         content = self.condition.getcontent()
       
  2455         if content["name"] == "reference":
       
  2456             search_result.extend(_Search([("reference", content["value"].getname())], criteria, parent_infos))
       
  2457         elif content["name"] == "inline":
       
  2458             search_result.extend(content["value"].Search(criteria, parent_infos + ["inline"]))
       
  2459         return search_result
       
  2460     setattr(cls, "Search", Search)
       
  2461     
       
  2462 cls = _initElementClass("selectionDivergence", "sfcObjects_selectionDivergence", "single")
       
  2463 if cls:
       
  2464     setattr(cls, "getinfos", _getdivergenceinfosFunction(True, False))
       
  2465 
       
  2466 cls = _initElementClass("selectionConvergence", "sfcObjects_selectionConvergence", "multiple")
       
  2467 if cls:
       
  2468     setattr(cls, "getinfos", _getdivergenceinfosFunction(False, False))
       
  2469 
       
  2470 cls = _initElementClass("simultaneousDivergence", "sfcObjects_simultaneousDivergence", "single")
       
  2471 if cls:
       
  2472     setattr(cls, "getinfos", _getdivergenceinfosFunction(True, True))
       
  2473 
       
  2474 cls = _initElementClass("simultaneousConvergence", "sfcObjects_simultaneousConvergence", "multiple")
       
  2475 if cls:
       
  2476     setattr(cls, "getinfos", _getdivergenceinfosFunction(False, True))
       
  2477 
       
  2478 cls = _initElementClass("jumpStep", "sfcObjects_jumpStep", "single")
       
  2479 if cls:
       
  2480     def getinfos(self):
       
  2481         infos = _getelementinfos(self)
       
  2482         infos["type"] = "jump"
       
  2483         infos["specific_values"]["target"] = self.gettargetName()
       
  2484         infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2485         return infos
       
  2486     setattr(cls, "getinfos", getinfos)
       
  2487 
       
  2488     def Search(self, criteria, parent_infos):
       
  2489         return _Search([("target", self.gettargetName())], criteria, parent_infos + ["jump", self.getlocalId()])
       
  2490     setattr(cls, "Search", Search)
       
  2491 
       
  2492 cls = PLCOpenClasses.get("actionBlock_action", None)
       
  2493 if cls:
       
  2494     def compatibility(self, tree):
       
  2495         relPosition = reduce(lambda x, y: x | (y.nodeName == "relPosition"), tree.childNodes, False)
       
  2496         if not tree.hasAttribute("localId"):
       
  2497             NodeSetAttr(tree, "localId", "0")
       
  2498         if not relPosition:
       
  2499             node = CreateNode("relPosition")
       
  2500             NodeSetAttr(node, "x", "0")
       
  2501             NodeSetAttr(node, "y", "0")
       
  2502             tree.childNodes.insert(0, node)
       
  2503     setattr(cls, "compatibility", compatibility)
       
  2504     
       
  2505     def setreferenceName(self, name):
       
  2506         if self.reference:
       
  2507             self.reference.setname(name)
       
  2508     setattr(cls, "setreferenceName", setreferenceName)
       
  2509     
       
  2510     def getreferenceName(self):
       
  2511         if self.reference:
       
  2512             return self.reference.getname()
       
  2513         return None
       
  2514     setattr(cls, "getreferenceName", getreferenceName)
       
  2515 
       
  2516     def setinlineContent(self, content):
       
  2517         if self.inline:
       
  2518             self.inline.setcontent({"name" : "ST", "value" : PLCOpenClasses["formattedText"]()})
       
  2519             self.inline.settext(content)
       
  2520     setattr(cls, "setinlineContent", setinlineContent)
       
  2521     
       
  2522     def getinlineContent(self):
       
  2523         if self.inline:
       
  2524             return self.inline.gettext()
       
  2525         return None
       
  2526     setattr(cls, "getinlineContent", getinlineContent)
       
  2527 
       
  2528     def updateElementName(self, old_name, new_name):
       
  2529         if self.reference and self.reference.getname() == old_name:
       
  2530             self.reference.setname(new_name)
       
  2531         if self.inline:
       
  2532             self.inline.updateElementName(old_name, new_name)
       
  2533     setattr(cls, "updateElementName", updateElementName)
       
  2534 
       
  2535     def updateElementAddress(self, address_model, new_leading):
       
  2536         if self.reference:
       
  2537             self.reference.setname(update_address(self.reference.getname(), address_model, new_leading))
       
  2538         if self.inline:
       
  2539             self.inline.updateElementAddress(address_model, new_leading)
       
  2540     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2541 
       
  2542     def Search(self, criteria, parent_infos=[]):
       
  2543         qualifier = self.getqualifier()
       
  2544         if qualifier is None:
       
  2545             qualifier = "N"
       
  2546         return _Search([("inline", self.getinlineContent()),
       
  2547                         ("reference", self.getreferenceName()), 
       
  2548                         ("qualifier", qualifier),
       
  2549                         ("duration", self.getduration()),
       
  2550                         ("indicator", self.getindicator())],
       
  2551                        criteria, parent_infos)
       
  2552     setattr(cls, "Search", Search)
       
  2553 
       
  2554 cls = _initElementClass("actionBlock", "commonObjects_actionBlock", "single")
       
  2555 if cls:
       
  2556     def compatibility(self, tree):
       
  2557         for child in tree.childNodes[:]:
       
  2558             if child.nodeName == "connectionPointOut":
       
  2559                 tree.childNodes.remove(child)
       
  2560     setattr(cls, "compatibility", compatibility)
       
  2561     
       
  2562     def getinfos(self):
       
  2563         infos = _getelementinfos(self)
       
  2564         infos["type"] = "actionBlock"
       
  2565         infos["specific_values"]["actions"] = self.getactions()
       
  2566         infos["inputs"].append(_getconnectioninfos(self, self.connectionPointIn, True))
       
  2567         return infos
       
  2568     setattr(cls, "getinfos", getinfos)
       
  2569     
       
  2570     def setactions(self, actions):
       
  2571         self.action = []
       
  2572         for params in actions:
       
  2573             action = PLCOpenClasses["actionBlock_action"]()
       
  2574             action.setqualifier(params["qualifier"])
       
  2575             if params["type"] == "reference":
       
  2576                 action.addreference()
       
  2577                 action.setreferenceName(params["value"])
       
  2578             else:
       
  2579                 action.addinline()
       
  2580                 action.setinlineContent(params["value"])
       
  2581             if params.has_key("duration"):
       
  2582                 action.setduration(params["duration"])
       
  2583             if params.has_key("indicator"):
       
  2584                 action.setindicator(params["indicator"])
       
  2585             self.action.append(action)
       
  2586     setattr(cls, "setactions", setactions)
       
  2587 
       
  2588     def getactions(self):
       
  2589         actions = []
       
  2590         for action in self.action:
       
  2591             params = {}
       
  2592             params["qualifier"] = action.getqualifier()
       
  2593             if params["qualifier"] is None:
       
  2594                 params["qualifier"] = "N"
       
  2595             if action.getreference():
       
  2596                 params["type"] = "reference"
       
  2597                 params["value"] = action.getreferenceName()
       
  2598             elif action.getinline():
       
  2599                 params["type"] = "inline"
       
  2600                 params["value"] = action.getinlineContent()
       
  2601             duration = action.getduration()
       
  2602             if duration:
       
  2603                 params["duration"] = duration
       
  2604             indicator = action.getindicator()
       
  2605             if indicator:
       
  2606                 params["indicator"] = indicator
       
  2607             actions.append(params)
       
  2608         return actions
       
  2609     setattr(cls, "getactions", getactions)
       
  2610 
       
  2611     def updateElementName(self, old_name, new_name):
       
  2612         for action in self.action:
       
  2613             action.updateElementName(old_name, new_name)
       
  2614     setattr(cls, "updateElementName", updateElementName)
       
  2615 
       
  2616     def updateElementAddress(self, address_model, new_leading):
       
  2617         for action in self.action:
       
  2618             action.updateElementAddress(address_model, new_leading)
       
  2619     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2620 
       
  2621     def Search(self, criteria, parent_infos=[]):
       
  2622         parent_infos = parent_infos + ["action_block", self.getlocalId()]
       
  2623         search_result = []
       
  2624         for idx, action in enumerate(self.action):
       
  2625             search_result.extend(action.Search(criteria, parent_infos + ["action", idx]))
       
  2626         return search_result
       
  2627     setattr(cls, "Search", Search)
       
  2628 
       
  2629 def _SearchInIOVariable(self, criteria, parent_infos=[]):
       
  2630     return _Search([("expression", self.getexpression())], criteria, parent_infos + ["io_variable", self.getlocalId()])
       
  2631 
       
  2632 cls = _initElementClass("inVariable", "fbdObjects_inVariable")
       
  2633 if cls:
       
  2634     setattr(cls, "getinfos", _getvariableinfosFunction("input", False, True))
       
  2635     
       
  2636     def updateElementName(self, old_name, new_name):
       
  2637         if self.expression == old_name:
       
  2638             self.expression = new_name
       
  2639     setattr(cls, "updateElementName", updateElementName)
       
  2640 
       
  2641     def updateElementAddress(self, address_model, new_leading):
       
  2642         self.expression = update_address(self.expression, address_model, new_leading)
       
  2643     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2644 
       
  2645     setattr(cls, "Search", _SearchInIOVariable)
       
  2646 
       
  2647 cls = _initElementClass("outVariable", "fbdObjects_outVariable", "single")
       
  2648 if cls:
       
  2649     setattr(cls, "getinfos", _getvariableinfosFunction("output", True, False))
       
  2650     
       
  2651     def updateElementName(self, old_name, new_name):
       
  2652         if self.expression == old_name:
       
  2653             self.expression = new_name
       
  2654     setattr(cls, "updateElementName", updateElementName)
       
  2655 
       
  2656     def updateElementAddress(self, address_model, new_leading):
       
  2657         self.expression = update_address(self.expression, address_model, new_leading)
       
  2658     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2659 
       
  2660     setattr(cls, "Search", _SearchInIOVariable)
       
  2661 
       
  2662 cls = _initElementClass("inOutVariable", "fbdObjects_inOutVariable", "single")
       
  2663 if cls:
       
  2664     setattr(cls, "getinfos", _getvariableinfosFunction("inout", True, True))
       
  2665     
       
  2666     def updateElementName(self, old_name, new_name):
       
  2667         if self.expression == old_name:
       
  2668             self.expression = new_name
       
  2669     setattr(cls, "updateElementName", updateElementName)
       
  2670 
       
  2671     def updateElementAddress(self, address_model, new_leading):
       
  2672         self.expression = update_address(self.expression, address_model, new_leading)
       
  2673     setattr(cls, "updateElementAddress", updateElementAddress)
       
  2674 
       
  2675     setattr(cls, "Search", _SearchInIOVariable)
       
  2676 
       
  2677 
       
  2678 def _SearchInConnector(self, criteria, parent_infos=[]):
       
  2679     return _Search([("name", self.getname())], criteria, parent_infos + ["connector", self.getlocalId()])
       
  2680 
       
  2681 cls = _initElementClass("continuation", "commonObjects_continuation")
       
  2682 if cls:
       
  2683     setattr(cls, "getinfos", _getconnectorinfosFunction("continuation"))
       
  2684     setattr(cls, "Search", _SearchInConnector)
       
  2685 
       
  2686     def updateElementName(self, old_name, new_name):
       
  2687         if self.name == old_name:
       
  2688             self.name = new_name
       
  2689     setattr(cls, "updateElementName", updateElementName)
       
  2690 
       
  2691 cls = _initElementClass("connector", "commonObjects_connector", "single")
       
  2692 if cls:
       
  2693     setattr(cls, "getinfos", _getconnectorinfosFunction("connector"))
       
  2694     setattr(cls, "Search", _SearchInConnector)
       
  2695 
       
  2696     def updateElementName(self, old_name, new_name):
       
  2697         if self.name == old_name:
       
  2698             self.name = new_name
       
  2699     setattr(cls, "updateElementName", updateElementName)
       
  2700 
       
  2701 cls = PLCOpenClasses.get("connection", None)
       
  2702 if cls:
       
  2703     def setpoints(self, points):
       
  2704         self.position = []
       
  2705         for point in points:
       
  2706             position = PLCOpenClasses["position"]()
       
  2707             position.setx(point.x)
       
  2708             position.sety(point.y)
       
  2709             self.position.append(position)
       
  2710     setattr(cls, "setpoints", setpoints)
       
  2711 
       
  2712     def getpoints(self):
       
  2713         points = []
       
  2714         for position in self.position:
       
  2715             points.append((position.getx(),position.gety()))
       
  2716         return points
       
  2717     setattr(cls, "getpoints", getpoints)
       
  2718 
       
  2719 cls = PLCOpenClasses.get("connectionPointIn", None)
       
  2720 if cls:
       
  2721     def setrelPositionXY(self, x, y):
       
  2722         self.relPosition = PLCOpenClasses["position"]()
       
  2723         self.relPosition.setx(x)
       
  2724         self.relPosition.sety(y)
       
  2725     setattr(cls, "setrelPositionXY", setrelPositionXY)
       
  2726 
       
  2727     def getrelPositionXY(self):
       
  2728         if self.relPosition:
       
  2729             return self.relPosition.getx(), self.relPosition.gety()
       
  2730         else:
       
  2731             return self.relPosition
       
  2732     setattr(cls, "getrelPositionXY", getrelPositionXY)
       
  2733 
       
  2734     def addconnection(self):
       
  2735         if not self.content:
       
  2736             self.content = {"name" : "connection", "value" : [PLCOpenClasses["connection"]()]}
       
  2737         else:
       
  2738             self.content["value"].append(PLCOpenClasses["connection"]())
       
  2739     setattr(cls, "addconnection", addconnection)
       
  2740 
       
  2741     def removeconnection(self, idx):
       
  2742         if self.content:
       
  2743             self.content["value"].pop(idx)
       
  2744         if len(self.content["value"]) == 0:
       
  2745             self.content = None
       
  2746     setattr(cls, "removeconnection", removeconnection)
       
  2747 
       
  2748     def removeconnections(self):
       
  2749         if self.content:
       
  2750             self.content = None
       
  2751     setattr(cls, "removeconnections", removeconnections)
       
  2752     
       
  2753     def getconnections(self):
       
  2754         if self.content:
       
  2755             return self.content["value"]
       
  2756     setattr(cls, "getconnections", getconnections)
       
  2757     
       
  2758     def setconnectionId(self, idx, id):
       
  2759         if self.content:
       
  2760             self.content["value"][idx].setrefLocalId(id)
       
  2761     setattr(cls, "setconnectionId", setconnectionId)
       
  2762     
       
  2763     def getconnectionId(self, idx):
       
  2764         if self.content:
       
  2765             return self.content["value"][idx].getrefLocalId()
       
  2766         return None
       
  2767     setattr(cls, "getconnectionId", getconnectionId)
       
  2768     
       
  2769     def setconnectionPoints(self, idx, points):
       
  2770         if self.content:
       
  2771             self.content["value"][idx].setpoints(points)
       
  2772     setattr(cls, "setconnectionPoints", setconnectionPoints)
       
  2773 
       
  2774     def getconnectionPoints(self, idx):
       
  2775         if self.content:
       
  2776             return self.content["value"][idx].getpoints()
       
  2777         return None
       
  2778     setattr(cls, "getconnectionPoints", getconnectionPoints)
       
  2779 
       
  2780     def setconnectionParameter(self, idx, parameter):
       
  2781         if self.content:
       
  2782             self.content["value"][idx].setformalParameter(parameter)
       
  2783     setattr(cls, "setconnectionParameter", setconnectionParameter)
       
  2784     
       
  2785     def getconnectionParameter(self, idx):
       
  2786         if self.content:
       
  2787             return self.content["value"][idx].getformalParameter()
       
  2788         return None
       
  2789     setattr(cls, "getconnectionParameter", getconnectionParameter)
       
  2790 
       
  2791 cls = PLCOpenClasses.get("connectionPointOut", None)
       
  2792 if cls:
       
  2793     def setrelPositionXY(self, x, y):
       
  2794         self.relPosition = PLCOpenClasses["position"]()
       
  2795         self.relPosition.setx(x)
       
  2796         self.relPosition.sety(y)
       
  2797     setattr(cls, "setrelPositionXY", setrelPositionXY)
       
  2798 
       
  2799     def getrelPositionXY(self):
       
  2800         if self.relPosition:
       
  2801             return self.relPosition.getx(), self.relPosition.gety()
       
  2802         return self.relPosition
       
  2803     setattr(cls, "getrelPositionXY", getrelPositionXY)
       
  2804 
       
  2805 cls = PLCOpenClasses.get("value", None)
       
  2806 if cls:
       
  2807     def setvalue(self, value):
       
  2808         value = value.strip()
       
  2809         if value.startswith("[") and value.endswith("]"):
       
  2810             arrayValue = PLCOpenClasses["value_arrayValue"]()
       
  2811             self.content = {"name" : "arrayValue", "value" : arrayValue}
       
  2812         elif value.startswith("(") and value.endswith(")"):
       
  2813             structValue = PLCOpenClasses["value_structValue"]()
       
  2814             self.content = {"name" : "structValue", "value" : structValue}
       
  2815         else:
       
  2816             simpleValue = PLCOpenClasses["value_simpleValue"]()
       
  2817             self.content = {"name" : "simpleValue", "value": simpleValue}
       
  2818         self.content["value"].setvalue(value)
       
  2819     setattr(cls, "setvalue", setvalue)
       
  2820     
       
  2821     def getvalue(self):
       
  2822         return self.content["value"].getvalue()
       
  2823     setattr(cls, "getvalue", getvalue)
       
  2824 
       
  2825 def extractValues(values):
       
  2826     items = values.split(",")
       
  2827     i = 1
       
  2828     while i < len(items):
       
  2829         opened = items[i - 1].count("(") + items[i - 1].count("[")
       
  2830         closed = items[i - 1].count(")") + items[i - 1].count("]")
       
  2831         if opened > closed:
       
  2832             items[i - 1] = ','.join([items[i - 1], items.pop(i)])
       
  2833         elif opened == closed:
       
  2834             i += 1
       
  2835         else:
       
  2836             raise ValueError, _("\"%s\" is an invalid value!")%value
       
  2837     return items
       
  2838 
       
  2839 cls = PLCOpenClasses.get("value_arrayValue", None)
       
  2840 if cls:
       
  2841     arrayValue_model = re.compile("([0-9]*)\((.*)\)$")
       
  2842     
       
  2843     def setvalue(self, value):
       
  2844         self.value = []
       
  2845         for item in extractValues(value[1:-1]):
       
  2846             item = item.strip()
       
  2847             element = PLCOpenClasses["arrayValue_value"]()
       
  2848             result = arrayValue_model.match(item)
       
  2849             if result is not None:
       
  2850                 groups = result.groups()
       
  2851                 element.setrepetitionValue(groups[0])
       
  2852                 element.setvalue(groups[1].strip())
       
  2853             else:
       
  2854                 element.setvalue(item)
       
  2855             self.value.append(element)
       
  2856     setattr(cls, "setvalue", setvalue)
       
  2857     
       
  2858     def getvalue(self):
       
  2859         values = []
       
  2860         for element in self.value:
       
  2861             repetition = element.getrepetitionValue()
       
  2862             if repetition is not None and int(repetition) > 1:
       
  2863                 value = element.getvalue()
       
  2864                 if value is None:
       
  2865                     value = ""
       
  2866                 values.append("%s(%s)"%(repetition, value))
       
  2867             else:
       
  2868                 values.append(element.getvalue())
       
  2869         return "[%s]"%", ".join(values)
       
  2870     setattr(cls, "getvalue", getvalue)
       
  2871 
       
  2872 cls = PLCOpenClasses.get("value_structValue", None)
       
  2873 if cls:
       
  2874     structValue_model = re.compile("(.*):=(.*)")
       
  2875     
       
  2876     def setvalue(self, value):
       
  2877         self.value = []
       
  2878         for item in extractValues(value[1:-1]):
       
  2879             result = structValue_model.match(item)
       
  2880             if result is not None:
       
  2881                 groups = result.groups()
       
  2882                 element = PLCOpenClasses["structValue_value"]()
       
  2883                 element.setmember(groups[0].strip())
       
  2884                 element.setvalue(groups[1].strip())
       
  2885                 self.value.append(element)
       
  2886     setattr(cls, "setvalue", setvalue)
       
  2887     
       
  2888     def getvalue(self):
       
  2889         values = []
       
  2890         for element in self.value:
       
  2891             values.append("%s := %s"%(element.getmember(), element.getvalue()))
       
  2892         return "(%s)"%", ".join(values)
       
  2893     setattr(cls, "getvalue", getvalue)