123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- #!/usr/bin/env/python
- # -*- coding: utf-8 -*-
- ###
- ### Author: Chris Iatrou (ichrispa@core-vector.net)
- ### Version: rev 13
- ###
- ### This program was created for educational purposes and has been
- ### contributed to the open62541 project by the author. All licensing
- ### terms for this source is inherited by the terms and conditions
- ### specified for by the open62541 project (see the projects readme
- ### file for more information on the LGPL terms and restrictions).
- ###
- ### This program is not meant to be used in a production environment. The
- ### author is not liable for any complications arising due to the use of
- ### this program.
- ###
- import sys
- import logging
- from sets import Set
- from datatypes import *
- from constants import *
- logger = logging.getLogger(__name__)
- if sys.version_info[0] >= 3:
- # strings are already parsed to unicode
- def unicode(s):
- return s
- class Reference(object):
- # all either nodeids or strings with an alias
- def __init__(self, source, referenceType, target, isForward = True, hidden = False):
- self.source = source
- self.referenceType = referenceType
- self.target = target
- self.isForward = isForward
- self.hidden = hidden # the reference is part of a nodeset that already exists
- def __str__(self):
- retval = str(self.source)
- if not self.isForward:
- retval = retval + "<"
- retval = retval + "--[" + str(self.referenceType) + "]--"
- if self.isForward:
- retval = retval + ">"
- return retval + str(self.target)
- def __repr__(self):
- return str(self)
- def __eq__(self, other):
- return str(self) == str(other)
- def __hash__(self):
- return hash(str(self))
- class Node(object):
- def __init__(self):
- self.id = NodeId()
- self.nodeClass = NODE_CLASS_GENERERIC
- self.browseName = QualifiedName()
- self.displayName = LocalizedText()
- self.description = LocalizedText()
- self.writeMask = 0
- self.userWriteMask = 0
- self.references = Set()
- self.inverseReferences = Set()
- self.hidden = False
- def __str__(self):
- return self.__class__.__name__ + "(" + str(self.id) + ")"
- def __repr__(self):
- return str(self)
- def sanitize(self):
- pass
- def parseXML(self, xmlelement):
- for idname in ['NodeId', 'NodeID', 'nodeid']:
- if xmlelement.hasAttribute(idname):
- self.id = NodeId(xmlelement.getAttribute(idname))
- for (at, av) in xmlelement.attributes.items():
- if at == "BrowseName":
- self.browseName = QualifiedName(av)
- elif at == "DisplayName":
- self.displayName = LocalizedText(av)
- elif at == "Description":
- self.description = LocalizedText(av)
- elif at == "WriteMask":
- self.writeMask = int(av)
- elif at == "UserWriteMask":
- self.userWriteMask = int(av)
- elif at == "EventNotifier":
- self.eventNotifier = int(av)
- for x in xmlelement.childNodes:
- if x.nodeType != x.ELEMENT_NODE:
- continue
- if x.firstChild:
- if x.tagName == "BrowseName":
- self.browseName = QualifiedName(x.firstChild.data)
- elif x.tagName == "DisplayName":
- self.displayName = LocalizedText(x.firstChild.data)
- elif x.tagName == "Description":
- self.description = LocalizedText(x.firstChild.data)
- elif x.tagName == "WriteMask":
- self.writeMask = int(unicode(x.firstChild.data))
- elif x.tagName == "UserWriteMask":
- self.userWriteMask = int(unicode(x.firstChild.data))
- if x.tagName == "References":
- self.parseXMLReferences(x)
- def parseXMLReferences(self, xmlelement):
- for ref in xmlelement.childNodes:
- if ref.nodeType != ref.ELEMENT_NODE:
- continue
- source = NodeId(str(self.id)) # deep-copy of the nodeid
- target = NodeId(ref.firstChild.data)
- reftype = None
- forward = True
- for (at, av) in ref.attributes.items():
- if at == "ReferenceType":
- if '=' in av:
- reftype = NodeId(av)
- else:
- reftype = av # alias, such as "HasSubType"
- elif at == "IsForward":
- forward = not "false" in av.lower()
- if forward:
- self.references.add(Reference(source, reftype, target, forward))
- else:
- self.inverseReferences.add(Reference(source, reftype, target, forward))
- def replaceAliases(self, aliases):
- if str(self.id) in aliases:
- self.id = NodeId(aliases[self.id])
- new_refs = set()
- for ref in self.references:
- if str(ref.source) in aliases:
- ref.source = NodeId(aliases[ref.source])
- if str(ref.target) in aliases:
- ref.target = NodeId(aliases[ref.target])
- if str(ref.referenceType) in aliases:
- ref.referenceType = NodeId(aliases[ref.referenceType])
- new_refs.add(ref)
- self.references = new_refs
- new_inv_refs = set()
- for ref in self.inverseReferences:
- if str(ref.source) in aliases:
- ref.source = NodeId(aliases[ref.source])
- if str(ref.target) in aliases:
- ref.target = NodeId(aliases[ref.target])
- if str(ref.referenceType) in aliases:
- ref.referenceType = NodeId(aliases[ref.referenceType])
- new_inv_refs.add(ref)
- self.inverseReferences = new_inv_refs
- def replaceNamespaces(self, nsMapping):
- self.id.ns = nsMapping[self.id.ns]
- self.browseName.ns = nsMapping[self.browseName.ns]
- new_refs = set()
- for ref in self.references:
- ref.source.ns = nsMapping[ref.source.ns]
- ref.target.ns = nsMapping[ref.target.ns]
- ref.referenceType.ns = nsMapping[ref.referenceType.ns]
- new_refs.add(ref)
- self.references = new_refs
- new_inv_refs = set()
- for ref in self.inverseReferences:
- ref.source.ns = nsMapping[ref.source.ns]
- ref.target.ns = nsMapping[ref.target.ns]
- ref.referenceType.ns = nsMapping[ref.referenceType.ns]
- new_inv_refs.add(ref)
- self.inverseReferences = new_inv_refs
- class ReferenceTypeNode(Node):
- def __init__(self, xmlelement = None):
- Node.__init__(self)
- self.nodeClass = NODE_CLASS_REFERENCETYPE
- self.isAbstract = False
- self.symmetric = False
- self.inverseName = ""
- if xmlelement:
- self.parseXML(xmlelement)
- def parseXML(self, xmlelement):
- Node.parseXML(self, xmlelement)
- for (at, av) in xmlelement.attributes.items():
- if at == "Symmetric":
- self.symmetric = "false" not in av.lower()
- elif at == "InverseName":
- self.inverseName = str(av)
- elif at == "IsAbstract":
- self.isAbstract = "false" not in av.lower()
- for x in xmlelement.childNodes:
- if x.nodeType == x.ELEMENT_NODE:
- if x.tagName == "InverseName" and x.firstChild:
- self.inverseName = str(unicode(x.firstChild.data))
- class ObjectNode(Node):
- def __init__(self, xmlelement = None):
- Node.__init__(self)
- self.nodeClass = NODE_CLASS_OBJECT
- self.eventNotifier = 0
- if xmlelement:
- self.parseXML(xmlelement)
- def parseXML(self, xmlelement):
- Node.parseXML(self, xmlelement)
- for (at, av) in xmlelement.attributes.items():
- if at == "EventNotifier":
- self.eventNotifier = int(av)
- class VariableNode(Node):
- def __init__(self, xmlelement = None):
- Node.__init__(self)
- self.nodeClass = NODE_CLASS_VARIABLE
- self.dataType = NodeId()
- self.valueRank = -1
- self.arrayDimensions = []
- self.accessLevel = 0
- self.userAccessLevel = 0
- self.minimumSamplingInterval = 0.0
- self.historizing = False
- self.value = None
- self.xmlValueDef = None
- if xmlelement:
- self.parseXML(xmlelement)
- def parseXML(self, xmlelement):
- Node.parseXML(self, xmlelement)
- for (at, av) in xmlelement.attributes.items():
- if at == "ValueRank":
- self.valueRank = int(av)
- elif at == "AccessLevel":
- self.accessLevel = int(av)
- elif at == "UserAccessLevel":
- self.userAccessLevel = int(av)
- elif at == "MinimumSamplingInterval":
- self.minimumSamplingInterval = float(av)
- elif at == "DataType":
- if "=" in av:
- self.dataType = NodeId(av)
- else:
- self.dataType = av
- for x in xmlelement.childNodes:
- if x.nodeType != x.ELEMENT_NODE:
- continue
- if x.tagName == "Value":
- self.__xmlValueDef__ = x
- elif x.tagName == "DataType":
- self.dataType = NodeId(str(x))
- elif x.tagName == "ValueRank":
- self.valueRank = int(unicode(x.firstChild.data))
- elif x.tagName == "ArrayDimensions":
- self.arrayDimensions = int(unicode(x.firstChild.data))
- elif x.tagName == "AccessLevel":
- self.accessLevel = int(unicode(x.firstChild.data))
- elif x.tagName == "UserAccessLevel":
- self.userAccessLevel = int(unicode(x.firstChild.data))
- elif x.tagName == "MinimumSamplingInterval":
- self.minimumSamplingInterval = float(unicode(x.firstChild.data))
- elif x.tagName == "Historizing":
- self.historizing = "false" not in x.lower()
- class VariableTypeNode(VariableNode):
- def __init__(self, xmlelement = None):
- VariableNode.__init__(self)
- self.nodeClass = NODE_CLASS_VARIABLETYPE
- if xmlelement:
- self.parseXML(xmlelement)
- class MethodNode(Node):
- def __init__(self, xmlelement = None):
- Node.__init__(self)
- self.nodeClass = NODE_CLASS_METHOD
- self.executable = True
- self.userExecutable = True
- self.methodDecalaration = None
- if xmlelement:
- self.parseXML(xmlelement)
- def parseXML(self, xmlelement):
- Node.parseXML(self, xmlelement)
- for (at, av) in xmlelement.attributes.items():
- if at == "Executable":
- self.executable = "false" not in av.lower()
- if at == "UserExecutable":
- self.userExecutable = "false" not in av.lower()
- if at == "MethodDeclarationId":
- self.methodDeclaration = str(av)
- class ObjectTypeNode(Node):
- def __init__(self, xmlelement = None):
- Node.__init__(self)
- self.nodeClass = NODE_CLASS_OBJECTTYPE
- self.isAbstract = False
- if xmlelement:
- self.parseXML(xmlelement)
- def parseXML(self, xmlelement):
- Node.parseXML(self, xmlelement)
- for (at, av) in xmlelement.attributes.items():
- if at == "IsAbstract":
- self.isAbstract = "false" not in av.lower()
- class DataTypeNode(Node):
- def __init__(self, xmlelement = None):
- Node.__init__(self)
- self.nodeClass = NODE_CLASS_DATATYPE
- self.isAbstract = False
- if xmlelement:
- self.parseXML(xmlelement)
- def parseXML(self, xmlelement):
- Node.parseXML(self, xmlelement)
- for (at, av) in xmlelement.attributes.items():
- if at == "IsAbstract":
- self.isAbstract = "false" not in av.lower()
- class ViewNode(Node):
- def __init__(self, xmlelement = None):
- Node.__init__(self)
- self.nodeClass = NODE_CLASS_VIEW
- self.containsNoLoops == False
- self.eventNotifier == False
- if xmlelement:
- self.parseXML(xmlelement)
- def parseXML(self, xmlelement):
- Node.parseXML(self, xmlelement)
- for (at, av) in xmlelement.attributes.items():
- if at == "ContainsNoLoops":
- self.containsNoLoops = "false" not in av.lower()
- if at == "eventNotifier":
- self.eventNotifier = "false" not in av.lower()
|