plcopen/plcopen.py
branch1.1 Korean release
changeset 1280 72a826dfcfbb
parent 1276 29bfd39e8e7a
child 1281 47131e3388f4
--- a/plcopen/plcopen.py	Wed Mar 13 12:34:55 2013 +0900
+++ b/plcopen/plcopen.py	Wed Jul 31 10:45:07 2013 +0900
@@ -155,6 +155,17 @@
         self.text = text
     setattr(cls, "updateElementAddress", updateElementAddress)
     
+    def hasblock(self, block_type):
+        text = self.text.upper()
+        index = text.find(block_type.upper())
+        while index != -1:
+            if (not (index > 0 and (text[index - 1].isalnum() or text[index - 1] == "_")) and 
+                not (index < len(text) - len(block_type) and text[index + len(block_type)] != "(")):
+                return True
+            index = text.find(block_type.upper(), index + len(block_type))
+        return False
+    setattr(cls, "hasblock", hasblock)
+    
     def Search(self, criteria, parent_infos):
         return [(tuple(parent_infos),) + result for result in TestTextElement(self.gettext(), criteria)]
     setattr(cls, "Search", Search)
@@ -489,17 +500,19 @@
         self.CustomBlockTypes.append(block_infos)
     setattr(cls, "AddCustomBlockType", AddCustomBlockType)
 
+    def AddElementUsingTreeInstance(self, name, type_infos):
+        typename = type_infos.getname()
+        if not self.ElementUsingTree.has_key(typename):
+            self.ElementUsingTree[typename] = [name]
+        elif name not in self.ElementUsingTree[typename]:
+            self.ElementUsingTree[typename].append(name)
+    setattr(cls, "AddElementUsingTreeInstance", AddElementUsingTreeInstance)
+    
     def RefreshElementUsingTree(self):
         # Reset the tree of user-defined element cross-use
         self.ElementUsingTree = {}
         pous = self.getpous()
         datatypes = self.getdataTypes()
-        # Reference all the user-defined elementu names and initialize the tree of 
-        # user-defined elemnt cross-use
-        elementnames = [datatype.getname() for datatype in datatypes] + \
-                       [pou.getname() for pou in pous]
-        for name in elementnames:
-            self.ElementUsingTree[name] = []
         # Analyze each datatype
         for datatype in datatypes:
             name = datatype.getname()
@@ -511,16 +524,12 @@
             elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned", "array"]:
                 base_type = basetype_content["value"].baseType.getcontent()
                 if base_type["name"] == "derived":
-                    typename = base_type["value"].getname()
-                    if self.ElementUsingTree.has_key(typename) and name not in self.ElementUsingTree[typename]:
-                        self.ElementUsingTree[typename].append(name)
+                    self.AddElementUsingTreeInstance(name, base_type["value"])
             elif basetype_content["name"] == "struct":
                 for element in basetype_content["value"].getvariable():
                     type_content = element.type.getcontent()
                     if type_content["name"] == "derived":
-                        typename = type_content["value"].getname()
-                        if self.ElementUsingTree.has_key(typename) and name not in self.ElementUsingTree[typename]:
-                            self.ElementUsingTree[typename].append(name)
+                        self.AddElementUsingTreeInstance(name, type_content["value"])
         # Analyze each pou
         for pou in pous:
             name = pou.getname()
@@ -530,9 +539,11 @@
                     for var in varlist.getvariable():
                         vartype_content = var.gettype().getcontent()
                         if vartype_content["name"] == "derived":
-                            typename = vartype_content["value"].getname()
-                            if self.ElementUsingTree.has_key(typename) and name not in self.ElementUsingTree[typename]:
-                                self.ElementUsingTree[typename].append(name)
+                            self.AddElementUsingTreeInstance(name, vartype_content["value"])
+            for typename in self.ElementUsingTree.iterkeys():
+                if typename != name and pou.hasblock(block_type=typename) and name not in self.ElementUsingTree[typename]:
+                    self.ElementUsingTree[typename].append(name)
+        
     setattr(cls, "RefreshElementUsingTree", RefreshElementUsingTree)
 
     def GetParentType(self, type):
@@ -840,6 +851,35 @@
 
 cls = PLCOpenClasses.get("configurations_configuration", None)
 if cls:
+    
+    def addglobalVar(self, type, name, location="", description=""):
+        globalvars = self.getglobalVars()
+        if len(globalvars) == 0:
+            globalvars.append(PLCOpenClasses["varList"]())
+        var = PLCOpenClasses["varListPlain_variable"]()
+        var.setname(name)
+        var_type = PLCOpenClasses["dataType"]()
+        if type in [x for x,y in TypeHierarchy_list if not x.startswith("ANY")]:
+            if type == "STRING":
+                var_type.setcontent({"name" : "string", "value" : PLCOpenClasses["elementaryTypes_string"]()})
+            elif type == "WSTRING":
+                var_type.setcontent({"name" : "wstring", "value" : PLCOpenClasses["elementaryTypes_wstring"]()})
+            else:
+                var_type.setcontent({"name" : type, "value" : None})
+        else:
+            derived_type = PLCOpenClasses["derivedTypes_derived"]()
+            derived_type.setname(type)
+            var_type.setcontent({"name" : "derived", "value" : derived_type})
+        var.settype(var_type)
+        if location != "":
+            var.setaddress(location)
+        if description != "":
+            ft = PLCOpenClasses["formattedText"]()
+            ft.settext(description)
+            var.setdocumentation(ft)
+        globalvars[-1].appendvariable(var)
+    setattr(cls, "addglobalVar", addglobalVar)
+    
     def updateElementName(self, old_name, new_name):
         _updateConfigurationResourceElementName(self, old_name, new_name)
         for resource in self.getresource():
@@ -1382,21 +1422,25 @@
                     break
     setattr(cls, "removepouVar", removepouVar)
     
-    def hasblock(self, name):
+    def hasblock(self, name=None, block_type=None):
         if self.getbodyType() in ["FBD", "LD", "SFC"]:
             for instance in self.getinstances():
-                if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
+                if (isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and 
+                    (name and instance.getinstanceName() == name or
+                     block_type and instance.gettypeName() == block_type)):
                     return True
             if self.transitions:
                 for transition in self.transitions.gettransition():
-                    result = transition.hasblock(name)
+                    result = transition.hasblock(name, block_type)
                     if result:
                         return result
             if self.actions:
                 for action in self.actions.getaction():
-                    result = action.hasblock(name)
+                    result = action.hasblock(name, block_type)
                     if result:
                         return result
+        elif block_type is not None and len(self.body) > 0:
+            return self.body[0].hasblock(block_type)
         return False
     setattr(cls, "hasblock", hasblock)
     
@@ -1626,6 +1670,24 @@
 def gettext(self):
     return self.body.gettext()
 
+def hasblock(self, name=None, block_type=None):
+    if self.getbodyType() in ["FBD", "LD", "SFC"]:
+        for instance in self.getinstances():
+            if (isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and 
+                (name and instance.getinstanceName() == name or
+                 block_type and instance.gettypeName() == block_type)):
+                return True
+    elif block_type is not None:
+        return self.body.hasblock(block_type)
+    return False
+
+def updateElementName(self, old_name, new_name):
+    self.body.updateElementName(old_name, new_name)
+
+def updateElementAddress(self, address_model, new_leading):
+    self.body.updateElementAddress(address_model, new_leading)
+    
+
 cls = PLCOpenClasses.get("transitions_transition", None)
 if cls:
     setattr(cls, "setbodyType", setbodyType)
@@ -1641,23 +1703,10 @@
     setattr(cls, "removeinstance", removeinstance)
     setattr(cls, "settext", settext)
     setattr(cls, "gettext", gettext)
-
-    def updateElementName(self, old_name, new_name):
-        self.body.updateElementName(old_name, new_name)
+    setattr(cls, "hasblock", hasblock)
     setattr(cls, "updateElementName", updateElementName)
-
-    def updateElementAddress(self, address_model, new_leading):
-        self.body.updateElementAddress(address_model, new_leading)
     setattr(cls, "updateElementAddress", updateElementAddress)
-
-    def hasblock(self, name):
-        if self.getbodyType() in ["FBD", "LD", "SFC"]:
-            for instance in self.getinstances():
-                if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
-                    return True
-        return False
-    setattr(cls, "hasblock", hasblock)
-
+    
     def Search(self, criteria, parent_infos):
         search_result = []
         parent_infos = parent_infos[:-1] + ["T::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())]
@@ -1682,23 +1731,10 @@
     setattr(cls, "removeinstance", removeinstance)
     setattr(cls, "settext", settext)
     setattr(cls, "gettext", gettext)
-
-    def updateElementName(self, old_name, new_name):
-        self.body.updateElementName(old_name, new_name)
+    setattr(cls, "hasblock", hasblock)
     setattr(cls, "updateElementName", updateElementName)
-
-    def updateElementAddress(self, address_model, new_leading):
-        self.body.updateElementAddress(address_model, new_leading)
     setattr(cls, "updateElementAddress", updateElementAddress)
-
-    def hasblock(self, name):
-        if self.getbodyType() in ["FBD", "LD", "SFC"]:
-            for instance in self.getinstances():
-                if isinstance(instance, PLCOpenClasses["fbdObjects_block"]) and instance.getinstanceName() == name:
-                    return True
-        return False
-    setattr(cls, "hasblock", hasblock)
-
+    
     def Search(self, criteria, parent_infos):
         search_result = []
         parent_infos = parent_infos[:-1] + ["A::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())]
@@ -1711,6 +1747,24 @@
 cls = PLCOpenClasses.get("body", None)
 if cls:
     cls.currentExecutionOrderId = 0
+    cls.instances_dict = {}
+    
+    setattr(cls, "_init_", getattr(cls, "__init__"))
+    
+    def __init__(self, *args, **kwargs):
+        self._init_(*args, **kwargs)
+        self.instances_dict = {}
+    setattr(cls, "__init__", __init__)
+    
+    setattr(cls, "_loadXMLTree", getattr(cls, "loadXMLTree"))
+    
+    def loadXMLTree(self, *args, **kwargs):
+        self._loadXMLTree(*args, **kwargs)
+        if self.content["name"] in ["LD","FBD","SFC"]:
+            self.instances_dict = dict(
+                [(element["value"].getlocalId(), element)
+                 for element in self.content["value"].getcontent()])
+    setattr(cls, "loadXMLTree", loadXMLTree)
     
     def resetcurrentExecutionOrderId(self):
         object.__setattr__(self, "currentExecutionOrderId", 0)
@@ -1785,7 +1839,9 @@
     
     def appendcontentInstance(self, name, instance):
         if self.content["name"] in ["LD","FBD","SFC"]:
-            self.content["value"].appendcontent({"name" : name, "value" : instance})
+            element = {"name" : name, "value" : instance}
+            self.content["value"].appendcontent(element)
+            self.instances_dict[instance.getlocalId()] = element
         else:
             raise TypeError, _("%s body don't have instances!")%self.content["name"]
     setattr(cls, "appendcontentInstance", appendcontentInstance)
@@ -1802,9 +1858,9 @@
 
     def getcontentInstance(self, id):
         if self.content["name"] in ["LD","FBD","SFC"]:
-            for element in self.content["value"].getcontent():
-                if element["value"].getlocalId() == id:
-                    return element["value"]
+            instance = self.instances_dict.get(id, None)
+            if instance is not None:
+                return instance["value"]
             return None
         else:
             raise TypeError, _("%s body don't have instances!")%self.content["name"]
@@ -1812,9 +1868,9 @@
     
     def getcontentRandomInstance(self, exclude):
         if self.content["name"] in ["LD","FBD","SFC"]:
-            for element in self.content["value"].getcontent():
-                if element["value"].getlocalId() not in exclude:
-                    return element["value"]
+            ids = self.instances_dict.viewkeys() - exclude
+            if len(ids) > 0:
+                return self.instances_dict[ids.pop()]["value"]
             return None
         else:
             raise TypeError, _("%s body don't have instances!")%self.content["name"]
@@ -1831,15 +1887,10 @@
     
     def removecontentInstance(self, id):
         if self.content["name"] in ["LD","FBD","SFC"]:
-            i = 0
-            removed = False
-            elements = self.content["value"].getcontent()
-            while i < len(elements) and not removed:
-                if elements[i]["value"].getlocalId() == id:
-                    self.content["value"].removecontent(i)
-                    removed = True
-                i += 1
-            if not removed:
+            element = self.instances_dict.pop(id, None)
+            if element is not None:
+                self.content["value"].getcontent().remove(element)
+            else:
                 raise ValueError, _("Instance with id %d doesn't exist!")%id
         else:
             raise TypeError, "%s body don't have instances!"%self.content["name"]
@@ -1859,6 +1910,13 @@
             raise TypeError, _("%s body don't have text!")%self.content["name"]
     setattr(cls, "gettext", gettext)
     
+    def hasblock(self, block_type):
+        if self.content["name"] in ["IL","ST"]:
+            return self.content["value"].hasblock(block_type)
+        else:
+            raise TypeError, _("%s body don't have text!")%self.content["name"]
+    setattr(cls, "hasblock", hasblock)
+    
     def updateElementName(self, old_name, new_name):
         if self.content["name"] in ["IL", "ST"]:
             self.content["value"].updateElementName(old_name, new_name)