plcopen/plcopen.py
changeset 1649 3291024e00da
parent 1629 80eee3c5a057
child 1680 6db967480b7d
equal deleted inserted replaced
1648:6431f26aa501 1649:3291024e00da
     1 #!/usr/bin/env python
     1 #!/usr/bin/env python
     2 # -*- coding: utf-8 -*-
     2 # -*- coding: utf-8 -*-
     3 
     3 
     4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
     4 # This file is part of Beremiz, a Integrated Development Environment for
     5 #based on the plcopen standard. 
     5 # programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
     6 #
     6 #
     7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     7 # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
     8 #
     8 #
     9 #See COPYING file for copyrights details.
     9 # See COPYING file for copyrights details.
    10 #
    10 #
    11 #This library is free software; you can redistribute it and/or
    11 # This program is free software; you can redistribute it and/or
    12 #modify it under the terms of the GNU General Public
    12 # modify it under the terms of the GNU General Public License
    13 #License as published by the Free Software Foundation; either
    13 # as published by the Free Software Foundation; either version 2
    14 #version 2.1 of the License, or (at your option) any later version.
    14 # of the License, or (at your option) any later version.
    15 #
    15 #
    16 #This library is distributed in the hope that it will be useful,
    16 # This program is distributed in the hope that it will be useful,
    17 #but WITHOUT ANY WARRANTY; without even the implied warranty of
    17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
    18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    19 #General Public License for more details.
    19 # GNU General Public License for more details.
    20 #
    20 #
    21 #You should have received a copy of the GNU General Public
    21 # You should have received a copy of the GNU General Public License
    22 #License along with this library; if not, write to the Free Software
    22 # along with this program; if not, write to the Free Software
    23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    24 
    24 
    25 from xmlclass import *
    25 from xmlclass import *
    26 from types import *
    26 from types import *
    27 import os, re
    27 import os, re
    28 from lxml import etree
    28 from lxml import etree
   109     if text == "":
   109     if text == "":
   110         return (0, 0)
   110         return (0, 0)
   111     lines = text.split("\n")
   111     lines = text.split("\n")
   112     return len(lines) - 1, len(lines[-1])
   112     return len(lines) - 1, len(lines[-1])
   113 
   113 
       
   114 def CompilePattern(criteria):
       
   115     flag = 0 if criteria["case_sensitive"] else re.IGNORECASE
       
   116     find_pattern = criteria["find_pattern"]
       
   117     if not criteria["regular_expression"]:
       
   118         find_pattern = re.escape(find_pattern)
       
   119     criteria["pattern"] = re.compile(find_pattern, flag)
       
   120 
   114 def TestTextElement(text, criteria):
   121 def TestTextElement(text, criteria):
   115     lines = text.splitlines()
   122     lines = text.splitlines()
   116     if not criteria["case_sensitive"]:
       
   117         text = text.upper()
       
   118     test_result = []
   123     test_result = []
   119     result = criteria["pattern"].search(text)
   124     result = criteria["pattern"].search(text)
   120     while result is not None:
   125     while result is not None:
   121         start = TextLenInRowColumn(text[:result.start()])
   126         start = TextLenInRowColumn(text[:result.start()])
   122         end = TextLenInRowColumn(text[:result.end() - 1])
   127         end = TextLenInRowColumn(text[:result.end() - 1])
   123         test_result.append((start, end, "\n".join(lines[start[0]:end[0] + 1])))
   128         test_result.append((start, end, "\n".join(lines[start[0]:end[0] + 1])))
   124         result = criteria["pattern"].search(text, result.end())
   129         result = criteria["pattern"].search(text, result.end())
   125     return test_result
   130     return test_result
       
   131 
       
   132 def TextMatched(str1, str2):
       
   133     return str1 and str2 and (str1.upper() == str2.upper())
   126 
   134 
   127 PLCOpenParser = GenerateParserFromXSD(os.path.join(os.path.split(__file__)[0], "tc6_xml_v201.xsd"))
   135 PLCOpenParser = GenerateParserFromXSD(os.path.join(os.path.split(__file__)[0], "tc6_xml_v201.xsd"))
   128 PLCOpen_XPath = lambda xpath: etree.XPath(xpath, namespaces=PLCOpenParser.NSMAP)
   136 PLCOpen_XPath = lambda xpath: etree.XPath(xpath, namespaces=PLCOpenParser.NSMAP)
   129 
   137 
   130 LOAD_POU_PROJECT_TEMPLATE = """
   138 LOAD_POU_PROJECT_TEMPLATE = """
   283 
   291 
   284 cls = PLCOpenParser.GetElementClass("formattedText")
   292 cls = PLCOpenParser.GetElementClass("formattedText")
   285 if cls:
   293 if cls:
   286     def updateElementName(self, old_name, new_name):
   294     def updateElementName(self, old_name, new_name):
   287         text = self.getanyText()
   295         text = self.getanyText()
   288         index = text.find(old_name)
   296         pattern = re.compile('\\b' + old_name + '\\b', re.IGNORECASE)
   289         while index != -1:
   297         text = pattern.sub(new_name, text)
   290             if index > 0 and (text[index - 1].isalnum() or text[index - 1] == "_"):
       
   291                 index = text.find(old_name, index + len(old_name))
       
   292             elif index < len(text) - len(old_name) and (text[index + len(old_name)].isalnum() or text[index + len(old_name)] == "_"):
       
   293                 index = text.find(old_name, index + len(old_name))
       
   294             else:
       
   295                 text = text[:index] + new_name + text[index + len(old_name):]
       
   296                 index = text.find(old_name, index + len(new_name))
       
   297         self.setanyText(text)
   298         self.setanyText(text)
   298     setattr(cls, "updateElementName", updateElementName)
   299     setattr(cls, "updateElementName", updateElementName)
   299     
   300     
   300     def updateElementAddress(self, address_model, new_leading):
   301     def updateElementAddress(self, address_model, new_leading):
   301         text = self.getanyText()
   302         text = self.getanyText()
   309             result = address_model.search(text, startpos)
   310             result = address_model.search(text, startpos)
   310         self.setanyText(text)
   311         self.setanyText(text)
   311     setattr(cls, "updateElementAddress", updateElementAddress)
   312     setattr(cls, "updateElementAddress", updateElementAddress)
   312     
   313     
   313     def hasblock(self, block_type):
   314     def hasblock(self, block_type):
   314         text = self.getanyText().upper()
   315         text = self.getanyText()        
   315         index = text.find(block_type.upper())
   316         pattern = re.compile('\\b' + block_type + '\\b', re.IGNORECASE)
   316         while index != -1:
   317         return pattern.search(text) is not None
   317             if (not (index > 0 and (text[index - 1].isalnum() or text[index - 1] == "_")) and 
       
   318                 not (index < len(text) - len(block_type) and text[index + len(block_type)] != "(")):
       
   319                 return True
       
   320             index = text.find(block_type.upper(), index + len(block_type))
       
   321         return False
       
   322     setattr(cls, "hasblock", hasblock)
   318     setattr(cls, "hasblock", hasblock)
   323     
   319     
   324     def Search(self, criteria, parent_infos):
   320     def Search(self, criteria, parent_infos):
   325         return [(tuple(parent_infos),) + result for result in TestTextElement(self.getanyText(), criteria)]
   321         return [(tuple(parent_infos),) + result for result in TestTextElement(self.getanyText(), criteria)]
   326     setattr(cls, "Search", Search)
   322     setattr(cls, "Search", Search)
   490         return None
   486         return None
   491     setattr(cls, "getconfigurationResource", getconfigurationResource)
   487     setattr(cls, "getconfigurationResource", getconfigurationResource)
   492 
   488 
   493     def addconfigurationResource(self, config_name, name):
   489     def addconfigurationResource(self, config_name, name):
   494         if self.getconfigurationResource(config_name, name) is not None:
   490         if self.getconfigurationResource(config_name, name) is not None:
   495             raise ValueError, _("\"%s\" resource already exists in \"%s\" configuration !!!") % (name, config_name)
   491             msg = _("\"{a1}\" resource already exists in \"{a2}\" configuration !!!").format(a1 = name, a2 = config_name)
       
   492             raise ValueError, msg
   496         configuration = self.getconfiguration(config_name)
   493         configuration = self.getconfiguration(config_name)
   497         if configuration is not None:
   494         if configuration is not None:
   498             new_resource = PLCOpenParser.CreateElement("resource", "configuration")
   495             new_resource = PLCOpenParser.CreateElement("resource", "configuration")
   499             new_resource.setname(name)
   496             new_resource.setname(name)
   500             configuration.appendresource(new_resource)
   497             configuration.appendresource(new_resource)
   507             resource = self.getconfigurationResource(config_name, name)
   504             resource = self.getconfigurationResource(config_name, name)
   508             if resource is not None:
   505             if resource is not None:
   509                 configuration.remove(resource)
   506                 configuration.remove(resource)
   510                 found = True
   507                 found = True
   511         if not found:
   508         if not found:
   512             raise ValueError, _("\"%s\" resource doesn't exist in \"%s\" configuration !!!")%(name, config_name)
   509             msg = _("\"{a1}\" resource doesn't exist in \"{a2}\" configuration !!!").format(a1 = name, a2 = config_name)
       
   510             raise ValueError, msg
   513     setattr(cls, "removeconfigurationResource", removeconfigurationResource)
   511     setattr(cls, "removeconfigurationResource", removeconfigurationResource)
   514 
   512 
   515     def updateElementName(self, old_name, new_name):
   513     def updateElementName(self, old_name, new_name):
   516         for datatype in self.getdataTypes():
   514         for datatype in self.getdataTypes():
   517             datatype.updateElementName(old_name, new_name)
   515             datatype.updateElementName(old_name, new_name)
   631 def _updateConfigurationResourceElementName(self, old_name, new_name):
   629 def _updateConfigurationResourceElementName(self, old_name, new_name):
   632     for varlist in self.getglobalVars():
   630     for varlist in self.getglobalVars():
   633         for var in varlist.getvariable():
   631         for var in varlist.getvariable():
   634             var_address = var.getaddress()
   632             var_address = var.getaddress()
   635             if var_address is not None:
   633             if var_address is not None:
   636                 if var_address == old_name:
   634                 if TextMatched(var_address, old_name):
   637                     var.setaddress(new_name)
   635                     var.setaddress(new_name)
   638                 if var.getname() == old_name:
   636                 if TextMatched(var.getname(), old_name):
   639                     var.setname(new_name)
   637                     var.setname(new_name)
   640 
   638 
   641 def _updateConfigurationResourceElementAddress(self, address_model, new_leading):
   639 def _updateConfigurationResourceElementAddress(self, address_model, new_leading):
   642     for varlist in self.getglobalVars():
   640     for varlist in self.getglobalVars():
   643         for var in varlist.getvariable():
   641         for var in varlist.getvariable():
   767     setattr(cls, "Search", Search)
   765     setattr(cls, "Search", Search)
   768 
   766 
   769 cls = PLCOpenParser.GetElementClass("task", "resource")
   767 cls = PLCOpenParser.GetElementClass("task", "resource")
   770 if cls:
   768 if cls:
   771     def updateElementName(self, old_name, new_name):
   769     def updateElementName(self, old_name, new_name):
   772         if self.single == old_name:
   770         if TextMatched(self.single, old_name):
   773             self.single = new_name
   771             self.single = new_name
   774         if self.interval == old_name:
   772         if TextMatched(self.interval, old_name):
   775             self.interval = new_name
   773             self.interval = new_name
   776         for instance in self.getpouInstance():
   774         for instance in self.getpouInstance():
   777             instance.updateElementName(old_name, new_name)
   775             instance.updateElementName(old_name, new_name)
   778     setattr(cls, "updateElementName", updateElementName)
   776     setattr(cls, "updateElementName", updateElementName)
   779 
   777 
   792     setattr(cls, "Search", Search)
   790     setattr(cls, "Search", Search)
   793 
   791 
   794 cls = PLCOpenParser.GetElementClass("pouInstance")
   792 cls = PLCOpenParser.GetElementClass("pouInstance")
   795 if cls:
   793 if cls:
   796     def updateElementName(self, old_name, new_name):
   794     def updateElementName(self, old_name, new_name):
   797         if self.typeName == old_name:
   795         if TextMatched(self.typeName, old_name):
   798             self.typeName = new_name
   796             self.typeName = new_name
   799     setattr(cls, "updateElementName", updateElementName)
   797     setattr(cls, "updateElementName", updateElementName)
   800 
   798 
   801     def Search(self, criteria, parent_infos=[]):
   799     def Search(self, criteria, parent_infos=[]):
   802         return _Search([("name", self.getname()), 
   800         return _Search([("name", self.getname()), 
   854     setattr(cls, "getdataTypeElements", getdataTypeElements)
   852     setattr(cls, "getdataTypeElements", getdataTypeElements)
   855     
   853     
   856     def getdataTypeElement(self, name):
   854     def getdataTypeElement(self, name):
   857         elements = self.dataTypes.getdataType()
   855         elements = self.dataTypes.getdataType()
   858         for element in elements:
   856         for element in elements:
   859             if element.getname() == name:
   857             if TextMatched(element.getname(), name):
   860                 return element
   858                 return element
   861         return None
   859         return None
   862     setattr(cls, "getdataTypeElement", getdataTypeElement)
   860     setattr(cls, "getdataTypeElement", getdataTypeElement)
   863 
   861 
   864     def appenddataTypeElement(self, name):
   862     def appenddataTypeElement(self, name):
   873     setattr(cls, "insertdataTypeElement", insertdataTypeElement)
   871     setattr(cls, "insertdataTypeElement", insertdataTypeElement)
   874     
   872     
   875     def removedataTypeElement(self, name):
   873     def removedataTypeElement(self, name):
   876         found = False
   874         found = False
   877         for element in self.dataTypes.getdataType():
   875         for element in self.dataTypes.getdataType():
   878             if element.getname() == name:
   876             if TextMatched(element.getname(), name):
   879                 self.dataTypes.remove(element)
   877                 self.dataTypes.remove(element)
   880                 found = True
   878                 found = True
   881                 break
   879                 break
   882         if not found:
   880         if not found:
   883             raise ValueError, _("\"%s\" Data Type doesn't exist !!!")%name
   881             raise ValueError, _("\"%s\" Data Type doesn't exist !!!")%name
   888     setattr(cls, "getpouElements", getpouElements)
   886     setattr(cls, "getpouElements", getpouElements)
   889     
   887     
   890     def getpouElement(self, name):
   888     def getpouElement(self, name):
   891         elements = self.pous.getpou()
   889         elements = self.pous.getpou()
   892         for element in elements:
   890         for element in elements:
   893             if element.getname() == name:
   891             if TextMatched(element.getname(), name):
   894                 return element
   892                 return element
   895         return None
   893         return None
   896     setattr(cls, "getpouElement", getpouElement)
   894     setattr(cls, "getpouElement", getpouElement)
   897 
   895 
   898     def appendpouElement(self, name, pou_type, body_type):
   896     def appendpouElement(self, name, pou_type, body_type):
   899         for element in self.pous.getpou():
   897         for element in self.pous.getpou():
   900             if element.getname() == name:
   898             if TextMatched(element.getname(), name):
   901                 raise ValueError, _("\"%s\" POU already exists !!!")%name
   899                 raise ValueError, _("\"%s\" POU already exists !!!")%name
   902         new_pou = PLCOpenParser.CreateElement("pou", "pous")
   900         new_pou = PLCOpenParser.CreateElement("pou", "pous")
   903         self.pous.appendpou(new_pou)
   901         self.pous.appendpou(new_pou)
   904         new_pou.setname(name)
   902         new_pou.setname(name)
   905         new_pou.setpouType(pou_type)
   903         new_pou.setpouType(pou_type)
   912     setattr(cls, "insertpouElement", insertpouElement)
   910     setattr(cls, "insertpouElement", insertpouElement)
   913     
   911     
   914     def removepouElement(self, name):
   912     def removepouElement(self, name):
   915         found = False
   913         found = False
   916         for element in self.pous.getpou():
   914         for element in self.pous.getpou():
   917             if element.getname() == name:
   915             if TextMatched(element.getname(), name):
   918                 self.pous.remove(element)
   916                 self.pous.remove(element)
   919                 found = True
   917                 found = True
   920                 break
   918                 break
   921         if not found:
   919         if not found:
   922             raise ValueError, _("\"%s\" POU doesn't exist !!!")%name
   920             raise ValueError, _("\"%s\" POU doesn't exist !!!")%name
   979     setattr(cls, "Search", Search)
   977     setattr(cls, "Search", Search)
   980 
   978 
   981 cls = PLCOpenParser.GetElementClass("derived", "dataType")
   979 cls = PLCOpenParser.GetElementClass("derived", "dataType")
   982 if cls:
   980 if cls:
   983     def updateElementName(self, old_name, new_name):
   981     def updateElementName(self, old_name, new_name):
   984         if self.name == old_name:
   982         if TextMatched(self.name, old_name):
   985             self.name = new_name
   983             self.name = new_name
   986     setattr(cls, "updateElementName", updateElementName)
   984     setattr(cls, "updateElementName", updateElementName)
   987     
   985     
   988     def Search(self, criteria, parent_infos=[]):
   986     def Search(self, criteria, parent_infos=[]):
   989         return [(tuple(parent_infos),) + result for result in TestTextElement(self.name, criteria)]
   987         return [(tuple(parent_infos),) + result for result in TestTextElement(self.name, criteria)]
  1224         if self.interface is not None:
  1222         if self.interface is not None:
  1225             content = self.interface.getcontent()
  1223             content = self.interface.getcontent()
  1226             for varlist in content:
  1224             for varlist in content:
  1227                 variables = varlist.getvariable()
  1225                 variables = varlist.getvariable()
  1228                 for var in variables:
  1226                 for var in variables:
  1229                     if var.getname() == old_name:
  1227                     if TextMatched(var.getname(), old_name):
  1230                         vartype_content = var.gettype().getcontent()
  1228                         vartype_content = var.gettype().getcontent()
  1231                         if vartype_content.getLocalTag() == "derived" and vartype_content.getname() == old_type:
  1229                         if vartype_content.getLocalTag() == "derived" and TextMatched(vartype_content.getname(), old_type):
  1232                             var.setname(new_name)
  1230                             var.setname(new_name)
  1233                             vartype_content.setname(new_type)
  1231                             vartype_content.setname(new_type)
  1234                             return
  1232                             return
  1235     setattr(cls, "changepouVar", changepouVar)
  1233     setattr(cls, "changepouVar", changepouVar)
  1236     
  1234     
  1237     def removepouVar(self, var_type, name):
  1235     def removepouVar(self, var_type, name):
  1238         if self.interface is not None:
  1236         if self.interface is not None:
  1239             content = self.interface.getcontent()
  1237             content = self.interface.getcontent()
  1240             for varlist in content:
  1238             for varlist in content:
  1241                 for var in varlist.getvariable():
  1239                 for var in varlist.getvariable():
  1242                     if var.getname() == name:
  1240                     if TextMatched(var.getname(), name):
  1243                         vartype_content = var.gettype().getcontent()
  1241                         vartype_content = var.gettype().getcontent()
  1244                         if vartype_content.getLocalTag() == "derived" and vartype_content.getname() == var_type:
  1242                         if vartype_content.getLocalTag() == "derived" and TextMatched(vartype_content.getname(), var_type):
  1245                             varlist.remove(var)
  1243                             varlist.remove(var)
  1246                             if len(varlist.getvariable()) == 0:
  1244                             if len(varlist.getvariable()) == 0:
  1247                                 self.interface.remove(varlist)
  1245                                 self.interface.remove(varlist)
  1248                             break
  1246                             break
  1249     setattr(cls, "removepouVar", removepouVar)
  1247     setattr(cls, "removepouVar", removepouVar)
       
  1248 
       
  1249     def hasstep(self, name=None):
       
  1250         if self.getbodyType() in ["SFC"]:
       
  1251             for instance in self.getinstances():
       
  1252                 if isinstance(instance, PLCOpenParser.GetElementClass("step", "sfcObjects")) and TextMatched(instance.getname(), name):
       
  1253                     return True         
       
  1254         return False
       
  1255     setattr(cls, "hasstep", hasstep)
  1250     
  1256     
  1251     def hasblock(self, name=None, block_type=None):
  1257     def hasblock(self, name=None, block_type=None):
  1252         if self.getbodyType() in ["FBD", "LD", "SFC"]:
  1258         if self.getbodyType() in ["FBD", "LD", "SFC"]:
  1253             for instance in self.getinstances():
  1259             for instance in self.getinstances():
  1254                 if (isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")) and 
  1260                 if (isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")) and 
  1255                     (name and instance.getinstanceName() == name or
  1261                     (TextMatched(instance.getinstanceName(), name) or TextMatched(instance.gettypeName(), block_type))):
  1256                      block_type and instance.gettypeName() == block_type)):
       
  1257                     return True
  1262                     return True
  1258             if self.transitions:
  1263             if self.transitions:
  1259                 for transition in self.transitions.gettransition():
  1264                 for transition in self.transitions.gettransition():
  1260                     result = transition.hasblock(name, block_type)
  1265                     result = transition.hasblock(name, block_type)
  1261                     if result:
  1266                     if result:
  1277         transition = PLCOpenParser.CreateElement("transition", "transitions")
  1282         transition = PLCOpenParser.CreateElement("transition", "transitions")
  1278         self.transitions.appendtransition(transition)
  1283         self.transitions.appendtransition(transition)
  1279         transition.setname(name)
  1284         transition.setname(name)
  1280         transition.setbodyType(body_type)
  1285         transition.setbodyType(body_type)
  1281         if body_type == "ST":
  1286         if body_type == "ST":
  1282             transition.setanyText(":= ;")
  1287             transition.settext(":= ;")
  1283         elif body_type == "IL":
       
  1284             transition.setanyText("\tST\t%s"%name)
       
  1285     setattr(cls, "addtransition", addtransition)
  1288     setattr(cls, "addtransition", addtransition)
  1286     
  1289     
  1287     def gettransition(self, name):
  1290     def gettransition(self, name):
  1288         if self.transitions is not None:
  1291         if self.transitions is not None:
  1289             for transition in self.transitions.gettransition():
  1292             for transition in self.transitions.gettransition():
  1290                 if transition.getname() == name:
  1293                 if TextMatched(transition.getname(), name):
  1291                     return transition
  1294                     return transition
  1292         return None
  1295         return None
  1293     setattr(cls, "gettransition", gettransition)
  1296     setattr(cls, "gettransition", gettransition)
  1294         
  1297         
  1295     def gettransitionList(self):
  1298     def gettransitionList(self):
  1300     
  1303     
  1301     def removetransition(self, name):
  1304     def removetransition(self, name):
  1302         if self.transitions is not None:
  1305         if self.transitions is not None:
  1303             removed = False
  1306             removed = False
  1304             for transition in self.transitions.gettransition():
  1307             for transition in self.transitions.gettransition():
  1305                 if transition.getname() == name:
  1308                 if TextMatched(transition.getname(), name):
  1306                     if transition.getbodyType() in ["FBD", "LD", "SFC"]:
  1309                     if transition.getbodyType() in ["FBD", "LD", "SFC"]:
  1307                         for instance in transition.getinstances():
  1310                         for instance in transition.getinstances():
  1308                             if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")):
  1311                             if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")):
  1309                                 self.removepouVar(instance.gettypeName(), 
  1312                                 self.removepouVar(instance.gettypeName(), 
  1310                                                   instance.getinstanceName())
  1313                                                   instance.getinstanceName())
  1326     setattr(cls, "addaction", addaction)
  1329     setattr(cls, "addaction", addaction)
  1327     
  1330     
  1328     def getaction(self, name):
  1331     def getaction(self, name):
  1329         if self.actions is not None:
  1332         if self.actions is not None:
  1330             for action in self.actions.getaction():
  1333             for action in self.actions.getaction():
  1331                 if action.getname() == name:
  1334                 if TextMatched(action.getname(), name):
  1332                     return action
  1335                     return action
  1333         return None
  1336         return None
  1334     setattr(cls, "getaction", getaction)
  1337     setattr(cls, "getaction", getaction)
  1335     
  1338     
  1336     def getactionList(self):
  1339     def getactionList(self):
  1341     
  1344     
  1342     def removeaction(self, name):
  1345     def removeaction(self, name):
  1343         if self.actions is not None:
  1346         if self.actions is not None:
  1344             removed = False
  1347             removed = False
  1345             for action in self.actions.getaction():
  1348             for action in self.actions.getaction():
  1346                 if action.getname() == name:
  1349                 if TextMatched(action.getname(), name):
  1347                     if action.getbodyType() in ["FBD", "LD", "SFC"]:
  1350                     if action.getbodyType() in ["FBD", "LD", "SFC"]:
  1348                         for instance in action.getinstances():
  1351                         for instance in action.getinstances():
  1349                             if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")):
  1352                             if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")):
  1350                                 self.removepouVar(instance.gettypeName(), 
  1353                                 self.removepouVar(instance.gettypeName(), 
  1351                                                   instance.getinstanceName())
  1354                                                   instance.getinstanceName())
  1360         if self.interface is not None:
  1363         if self.interface is not None:
  1361             for content in self.interface.getcontent():
  1364             for content in self.interface.getcontent():
  1362                 for var in content.getvariable():
  1365                 for var in content.getvariable():
  1363                     var_address = var.getaddress()
  1366                     var_address = var.getaddress()
  1364                     if var_address is not None:
  1367                     if var_address is not None:
  1365                         if var_address == old_name:
  1368                         if TextMatched(var_address, old_name):
  1366                             var.setaddress(new_name)
  1369                             var.setaddress(new_name)
  1367                         if var.getname() == old_name:
  1370                         if TextMatched(var.getname(), old_name):
  1368                             var.setname(new_name)
  1371                             var.setname(new_name)
  1369                     var_type_content = var.gettype().getcontent()
  1372                     var_type_content = var.gettype().getcontent()
  1370                     if var_type_content.getLocalTag() == "derived":
  1373                     if var_type_content.getLocalTag() == "derived":
  1371                         if var_type_content.getname() == old_name:
  1374                         if TextMatched(var_type_content.getname(), old_name):
  1372                             var_type_content.setname(new_name)
  1375                             var_type_content.setname(new_name)
  1373         self.body[0].updateElementName(old_name, new_name)
  1376         self.body[0].updateElementName(old_name, new_name)
  1374         for action in self.getactionList():
  1377         for action in self.getactionList():
  1375             action.updateElementName(old_name, new_name)
  1378             action.updateElementName(old_name, new_name)
  1376         for transition in self.gettransitionList():
  1379         for transition in self.gettransitionList():
  1393 
  1396 
  1394     def removeVariableByAddress(self, address):
  1397     def removeVariableByAddress(self, address):
  1395         if self.interface is not None:
  1398         if self.interface is not None:
  1396             for content in self.interface.getcontent():
  1399             for content in self.interface.getcontent():
  1397                 for variable in content.getvariable():
  1400                 for variable in content.getvariable():
  1398                     if variable.getaddress() == address:
  1401                     if TextMatched(variable.getaddress(), address):
  1399                         content.remove(variable)
  1402                         content.remove(variable)
  1400     setattr(cls, "removeVariableByAddress", removeVariableByAddress)
  1403     setattr(cls, "removeVariableByAddress", removeVariableByAddress)
  1401 
  1404 
  1402     def removeVariableByFilter(self, address_model):
  1405     def removeVariableByFilter(self, address_model):
  1403         if self.interface is not None:
  1406         if self.interface is not None:
  1412     
  1415     
  1413     def Search(self, criteria, parent_infos=[]):
  1416     def Search(self, criteria, parent_infos=[]):
  1414         search_result = []
  1417         search_result = []
  1415         filter = criteria["filter"]
  1418         filter = criteria["filter"]
  1416         if filter == "all" or self.getpouType() in filter:
  1419         if filter == "all" or self.getpouType() in filter:
  1417             parent_infos = parent_infos + ["P::%s" % self.getname()]
  1420             if parent_infos == []:
       
  1421                 parent_infos = parent_infos + ["P::%s" % self.getname()]
  1418             search_result.extend(_Search([("name", self.getname())], criteria, parent_infos))
  1422             search_result.extend(_Search([("name", self.getname())], criteria, parent_infos))
  1419             if self.interface is not None:
  1423             if self.interface is not None:
  1420                 var_number = 0
  1424                 var_number = 0
  1421                 for content in self.interface.getcontent():
  1425                 for content in self.interface.getcontent():
  1422                     variable_type = searchResultVarTypes.get(content, "var_local")
  1426                     variable_type = searchResultVarTypes.get(content, "var_local")
  1484 
  1488 
  1485 def hasblock(self, name=None, block_type=None):
  1489 def hasblock(self, name=None, block_type=None):
  1486     if self.getbodyType() in ["FBD", "LD", "SFC"]:
  1490     if self.getbodyType() in ["FBD", "LD", "SFC"]:
  1487         for instance in self.getinstances():
  1491         for instance in self.getinstances():
  1488             if (isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")) and 
  1492             if (isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")) and 
  1489                 (name and instance.getinstanceName() == name or
  1493                 (TextMatched(instance.getinstanceName(), name) or TextMatched(instance.gettypeName(), block_type))):
  1490                  block_type and instance.gettypeName() == block_type)):
       
  1491                 return True
  1494                 return True
  1492     elif block_type is not None:
  1495     elif block_type is not None:
  1493         return self.body.hasblock(block_type)
  1496         return self.body.hasblock(block_type)
  1494     return False
  1497     return False
  1495 
  1498 
  1557     setattr(cls, "Search", Search)
  1560     setattr(cls, "Search", Search)
  1558 
  1561 
  1559 cls = PLCOpenParser.GetElementClass("body")
  1562 cls = PLCOpenParser.GetElementClass("body")
  1560 if cls:
  1563 if cls:
  1561     cls.currentExecutionOrderId = 0
  1564     cls.currentExecutionOrderId = 0
  1562     
  1565     cls.checkedBlocksDict = {}
  1563     def resetcurrentExecutionOrderId(self):
  1566     def resetcurrentExecutionOrderId(self):
  1564         object.__setattr__(self, "currentExecutionOrderId", 0)
  1567         object.__setattr__(self, "currentExecutionOrderId", 0)
  1565     setattr(cls, "resetcurrentExecutionOrderId", resetcurrentExecutionOrderId)
  1568     setattr(cls, "resetcurrentExecutionOrderId", resetcurrentExecutionOrderId)
  1566     
  1569     
  1567     def getnewExecutionOrderId(self):
  1570     def getnewExecutionOrderId(self):
  1574             for element in self.content.getcontent():
  1577             for element in self.content.getcontent():
  1575                 if not isinstance(element, (PLCOpenParser.GetElementClass("comment", "commonObjects"), 
  1578                 if not isinstance(element, (PLCOpenParser.GetElementClass("comment", "commonObjects"), 
  1576                                             PLCOpenParser.GetElementClass("connector", "commonObjects"), 
  1579                                             PLCOpenParser.GetElementClass("connector", "commonObjects"), 
  1577                                             PLCOpenParser.GetElementClass("continuation", "commonObjects"))):
  1580                                             PLCOpenParser.GetElementClass("continuation", "commonObjects"))):
  1578                     element.setexecutionOrderId(0)
  1581                     element.setexecutionOrderId(0)
       
  1582             self.checkedBlocksDict.clear()
  1579         else:
  1583         else:
  1580             raise TypeError, _("Can only generate execution order on FBD networks!")
  1584             raise TypeError, _("Can only generate execution order on FBD networks!")
  1581     setattr(cls, "resetexecutionOrder", resetexecutionOrder)
  1585     setattr(cls, "resetexecutionOrder", resetexecutionOrder)
  1582     
  1586     
  1583     def compileexecutionOrder(self):
  1587     def compileexecutionOrder(self):
  1596     
  1600     
  1597     def compileelementExecutionOrder(self, link):
  1601     def compileelementExecutionOrder(self, link):
  1598         if self.content.getLocalTag() == "FBD":
  1602         if self.content.getLocalTag() == "FBD":
  1599             localid = link.getrefLocalId()
  1603             localid = link.getrefLocalId()
  1600             instance = self.getcontentInstance(localid)
  1604             instance = self.getcontentInstance(localid)
       
  1605             self.checkedBlocksDict[localid] = True
  1601             if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")) and instance.getexecutionOrderId() == 0:
  1606             if isinstance(instance, PLCOpenParser.GetElementClass("block", "fbdObjects")) and instance.getexecutionOrderId() == 0:
  1602                 for variable in instance.inputVariables.getvariable():
  1607                 for variable in instance.inputVariables.getvariable():
  1603                     connections = variable.connectionPointIn.getconnections()
  1608                     connections = variable.connectionPointIn.getconnections()
  1604                     if connections and len(connections) == 1:
  1609                     if connections and len(connections) == 1:
  1605                         self.compileelementExecutionOrder(connections[0])
  1610                         if (self.checkedBlocksDict.has_key(connections[0].getrefLocalId()) == False):
  1606                 instance.setexecutionOrderId(self.getnewExecutionOrderId())
  1611                             self.compileelementExecutionOrder(connections[0])
       
  1612                 if instance.getexecutionOrderId() == 0:
       
  1613                     instance.setexecutionOrderId(self.getnewExecutionOrderId())
  1607             elif isinstance(instance, PLCOpenParser.GetElementClass("continuation", "commonObjects")) and instance.getexecutionOrderId() == 0:
  1614             elif isinstance(instance, PLCOpenParser.GetElementClass("continuation", "commonObjects")) and instance.getexecutionOrderId() == 0:
  1608                 name = instance.getname()
       
  1609                 for tmp_instance in self.getcontentInstances():
  1615                 for tmp_instance in self.getcontentInstances():
  1610                     if isinstance(tmp_instance, PLCOpenParser.GetElementClass("connector", "commonObjects")) and tmp_instance.getname() == name and tmp_instance.getexecutionOrderId() == 0:
  1616                     if (isinstance(tmp_instance, PLCOpenParser.GetElementClass("connector", "commonObjects")) and
       
  1617                         TextMatched(tmp_instance.getname(), instance.getname()) and tmp_instance.getexecutionOrderId() == 0):
  1611                         connections = tmp_instance.connectionPointIn.getconnections()
  1618                         connections = tmp_instance.connectionPointIn.getconnections()
  1612                         if connections and len(connections) == 1:
  1619                         if connections and len(connections) == 1:
  1613                             self.compileelementExecutionOrder(connections[0])
  1620                             self.compileelementExecutionOrder(connections[0])
  1614         else:
  1621         else:
  1615             raise TypeError, _("Can only generate execution order on FBD networks!")
  1622             raise TypeError, _("Can only generate execution order on FBD networks!")
  1905             bbox.union(_getConnectionsBoundingBox(input.connectionPointIn))
  1912             bbox.union(_getConnectionsBoundingBox(input.connectionPointIn))
  1906         return bbox
  1913         return bbox
  1907     setattr(cls, "getBoundingBox", getBoundingBox)
  1914     setattr(cls, "getBoundingBox", getBoundingBox)
  1908 
  1915 
  1909     def updateElementName(self, old_name, new_name):
  1916     def updateElementName(self, old_name, new_name):
  1910         if self.typeName == old_name:
  1917         if TextMatched(self.typeName, old_name):
  1911             self.typeName = new_name
  1918             self.typeName = new_name
  1912     setattr(cls, "updateElementName", updateElementName)
  1919     setattr(cls, "updateElementName", updateElementName)
  1913 
  1920 
  1914     def filterConnections(self, connections):
  1921     def filterConnections(self, connections):
  1915         for input in self.inputVariables.getvariable():
  1922         for input in self.inputVariables.getvariable():
  1945 
  1952 
  1946 _initElementClass("leftPowerRail", "ldObjects")
  1953 _initElementClass("leftPowerRail", "ldObjects")
  1947 _initElementClass("rightPowerRail", "ldObjects", "multiple")
  1954 _initElementClass("rightPowerRail", "ldObjects", "multiple")
  1948 
  1955 
  1949 def _UpdateLDElementName(self, old_name, new_name):
  1956 def _UpdateLDElementName(self, old_name, new_name):
  1950     if self.variable == old_name:
  1957     if TextMatched(self.variable, old_name):
  1951         self.variable = new_name
  1958         self.variable = new_name
  1952 
  1959 
  1953 def _UpdateLDElementAddress(self, address_model, new_leading):
  1960 def _UpdateLDElementAddress(self, address_model, new_leading):
  1954     self.variable = update_address(self.variable, address_model, new_leading)
  1961     self.variable = update_address(self.variable, address_model, new_leading)
  1955 
  1962 
  2051     def updateElementName(self, old_name, new_name):
  2058     def updateElementName(self, old_name, new_name):
  2052         if self.condition is not None:
  2059         if self.condition is not None:
  2053             content = self.condition.getcontent()
  2060             content = self.condition.getcontent()
  2054             content_name = content.getLocalTag()
  2061             content_name = content.getLocalTag()
  2055             if content_name == "reference":
  2062             if content_name == "reference":
  2056                 if content.getname() == old_name:
  2063                 if TextMatched(content.getname(), old_name):
  2057                     content.setname(new_name)
  2064                     content.setname(new_name)
  2058             elif content_name == "inline":
  2065             elif content_name == "inline":
  2059                 content.updateElementName(old_name, new_name)
  2066                 content.updateElementName(old_name, new_name)
  2060     setattr(cls, "updateElementName", updateElementName)
  2067     setattr(cls, "updateElementName", updateElementName)
  2061 
  2068 
  2123             return self.inline.gettext()
  2130             return self.inline.gettext()
  2124         return None
  2131         return None
  2125     setattr(cls, "getinlineContent", getinlineContent)
  2132     setattr(cls, "getinlineContent", getinlineContent)
  2126 
  2133 
  2127     def updateElementName(self, old_name, new_name):
  2134     def updateElementName(self, old_name, new_name):
  2128         if self.reference is not None and self.reference.getname() == old_name:
  2135         if self.reference is not None and TextMatched(self.reference.getname(), old_name):
  2129             self.reference.setname(new_name)
  2136             self.reference.setname(new_name)
  2130         if self.inline is not None:
  2137         if self.inline is not None:
  2131             self.inline.updateElementName(old_name, new_name)
  2138             self.inline.updateElementName(old_name, new_name)
  2132     setattr(cls, "updateElementName", updateElementName)
  2139     setattr(cls, "updateElementName", updateElementName)
  2133 
  2140 
  2213 
  2220 
  2214 def _SearchInIOVariable(self, criteria, parent_infos=[]):
  2221 def _SearchInIOVariable(self, criteria, parent_infos=[]):
  2215     return _Search([("expression", self.expression)], criteria, parent_infos + ["io_variable", self.getlocalId()])
  2222     return _Search([("expression", self.expression)], criteria, parent_infos + ["io_variable", self.getlocalId()])
  2216 
  2223 
  2217 def _UpdateIOElementName(self, old_name, new_name):
  2224 def _UpdateIOElementName(self, old_name, new_name):
  2218     if self.expression == old_name:
  2225     if TextMatched(self.expression, old_name):
  2219         self.expression = new_name
  2226         self.expression = new_name
  2220 
  2227 
  2221 def _UpdateIOElementAddress(self, address_model, new_leading):
  2228 def _UpdateIOElementAddress(self, address_model, new_leading):
  2222     self.expression = update_address(self.expression, address_model, new_leading)
  2229     self.expression = update_address(self.expression, address_model, new_leading)
  2223 
  2230 
  2246 cls = _initElementClass("continuation", "commonObjects")
  2253 cls = _initElementClass("continuation", "commonObjects")
  2247 if cls:
  2254 if cls:
  2248     setattr(cls, "Search", _SearchInConnector)
  2255     setattr(cls, "Search", _SearchInConnector)
  2249 
  2256 
  2250     def updateElementName(self, old_name, new_name):
  2257     def updateElementName(self, old_name, new_name):
  2251         if self.name == old_name:
  2258         if TextMatched(self.name, old_name):
  2252             self.name = new_name
  2259             self.name = new_name
  2253     setattr(cls, "updateElementName", updateElementName)
  2260     setattr(cls, "updateElementName", updateElementName)
  2254 
  2261 
  2255 cls = _initElementClass("connector", "commonObjects", "single")
  2262 cls = _initElementClass("connector", "commonObjects", "single")
  2256 if cls:
  2263 if cls:
  2257     setattr(cls, "Search", _SearchInConnector)
  2264     setattr(cls, "Search", _SearchInConnector)
  2258 
  2265 
  2259     def updateElementName(self, old_name, new_name):
  2266     def updateElementName(self, old_name, new_name):
  2260         if self.name == old_name:
  2267         if TextMatched(self.name, old_name):
  2261             self.name = new_name
  2268             self.name = new_name
  2262     setattr(cls, "updateElementName", updateElementName)
  2269     setattr(cls, "updateElementName", updateElementName)
  2263 
  2270 
  2264 cls = PLCOpenParser.GetElementClass("connection")
  2271 cls = PLCOpenParser.GetElementClass("connection")
  2265 if cls:
  2272 if cls: