Kaynağa Gözat

Simplify node sorting rules in the nodeset compiler

Julius Pfrommer 6 yıl önce
ebeveyn
işleme
f777fe276a

+ 96 - 115
tools/nodeset_compiler/backend_open62541.py

@@ -20,7 +20,6 @@
 
 from __future__ import print_function
 import string
-from collections import deque
 from os.path import basename
 import logging
 import codecs
@@ -36,123 +35,95 @@ from nodes import *
 from nodeset import *
 from backend_open62541_nodes import generateNodeCode_begin, generateNodeCode_finish, generateReferenceCode
 
-##############
-# Sort Nodes #
-##############
-
-# Select the references that shall be generated after this node in the ordering
-# If both nodes of the reference are hidden we assume that the references between
-# those nodes are already setup. Still print if only the target node is hidden,
-# because we need that reference.
-def selectPrintRefs(nodeset, L, node):
-    printRefs = []
-    for ref in node.references:
-        targetnode = nodeset.nodes[ref.target]
-        if node.hidden and targetnode.hidden:
-            continue
-        if not targetnode.hidden and not targetnode in L:
-            continue
-        printRefs.append(ref)
-    for ref in node.inverseReferences:
-        targetnode = nodeset.nodes[ref.target]
-        if node.hidden and targetnode.hidden:
-            continue
-        if not targetnode.hidden and not targetnode in L:
-            continue
-        printRefs.append(ref)
-    return printRefs
-
-def addTypeRef(nodeset, type_refs, dataTypeId, referencedById):
-    if not dataTypeId in type_refs:
-        type_refs[dataTypeId] = [referencedById]
-    else:
-        type_refs[dataTypeId].append(referencedById)
+# Kahn's algorithm: https://algocoding.wordpress.com/2015/04/05/topological-sorting-python/
+def sortNodes(nodeset):
 
+    # Ensure that every reference has an inverse reference in the target
+    for u in nodeset.nodes.values():
+        for ref in u.references:
+            back = Reference(ref.target, ref.referenceType, ref.source, not ref.isForward)
+            nodeset.nodes[ref.target].references.add(back) # ref set does not make a duplicate entry
 
-def reorderNodesMinDependencies(nodeset):
-    # Kahn's algorithm
-    # https://algocoding.wordpress.com/2015/04/05/topological-sorting-python/
+    # reverse hastypedefinition references to treat only forward references
+    hasTypeDef = NodeId("ns=0;i=40")
+    for u in nodeset.nodes.values():
+        for ref in u.references:
+            if ref.referenceType == hasTypeDef:
+                ref.isForward = not ref.isForward
 
-    relevant_types = nodeset.getRelevantOrderingReferences()
+    # Only hierarchical types...
+    relevant_refs = nodeset.getRelevantOrderingReferences()
 
-    # determine in-degree
-    in_degree = {u.id: 0 for u in nodeset.nodes.values()}
-    dataType_refs = {}
-    hiddenCount = 0
-    for u in nodeset.nodes.values():  # of each node
-        if u.hidden:
-            hiddenCount += 1
-            continue
-        hasTypeDef = None
+    # determine in-degree of unfulfilled references
+    L = [node for node in nodeset.nodes.values() if node.hidden]  # ordered list of nodes
+    R = {node.id: node for node in nodeset.nodes.values() if not node.hidden} # remaining nodes
+    in_degree = {id: 0 for id in R.keys()}
+    for u in R.values(): # for each node
         for ref in u.references:
-            if ref.referenceType.i == 40:
-                hasTypeDef = ref.target
-            elif (ref.referenceType in relevant_types and ref.isForward) and not nodeset.nodes[ref.target].hidden:
-                in_degree[ref.target] += 1
-        if hasTypeDef is not None and not nodeset.nodes[hasTypeDef].hidden:
-            # we cannot print the node u because it first needs the variable type node
+            if not ref.referenceType in relevant_refs:
+                continue
+            if nodeset.nodes[ref.target].hidden:
+                continue
+            if ref.isForward:
+                continue
             in_degree[u.id] += 1
 
-        if isinstance(u, VariableNode) and u.dataType is not None:
-            dataTypeNode = nodeset.getDataTypeNode(u.dataType)
-            if dataTypeNode is not None and not dataTypeNode.hidden:
-                # we cannot print the node u because it first needs the data type node
-                in_degree[u.id] += 1
-                # to be able to decrement the in_degree count, we need to store it here
-                addTypeRef(nodeset, dataType_refs,dataTypeNode.id, u.id)
-
-    # collect nodes with zero in-degree
-    Q = deque()
-    for id in in_degree:
-        if in_degree[id] == 0:
-            # print referencetypenodes first
-            n = nodeset.nodes[id]
-            if isinstance(n, ReferenceTypeNode):
-                Q.append(nodeset.nodes[id])
-            else:
-                Q.appendleft(nodeset.nodes[id])
+    # Print ReferenceType and DataType nodes first. They may be required even
+    # though there is no reference to them. For example if the referencetype is
+    # used in a reference, it must exist. A Variable node may point to a
+    # DataTypeNode in the datatype attribute and not via an explicit reference.
 
-    L = []  # list for order of nodes
+    Q = {node for node in R.values() if in_degree[node.id] == 0 and
+         (isinstance(node, ReferenceTypeNode) or isinstance(node, DataTypeNode))}
     while Q:
-        u = Q.pop()  # choose node of zero in-degree
-        # decide which references to print now based on the ordering
-        u.printRefs = selectPrintRefs(nodeset, L, u)
-        if u.hidden:
-            continue
+        u = Q.pop() # choose node of zero in-degree and 'remove' it from graph
+        L.append(u)
+        del R[u.id]
+
+        for ref in u.references:
+            if not ref.referenceType in relevant_refs:
+                continue
+            if nodeset.nodes[ref.target].hidden:
+                continue
+            if not ref.isForward:
+                continue
+            in_degree[ref.target] -= 1
+            if in_degree[ref.target] == 0:
+                Q.add(R[ref.target])
 
-        L.append(u)  # and 'remove' it from graph
-
-        if isinstance(u, DataTypeNode):
-            # decrement all the nodes which depend on this datatype
-            if u.id in dataType_refs:
-                for n in dataType_refs[u.id]:
-                    if not nodeset.nodes[n].hidden:
-                        in_degree[n] -= 1
-                    if in_degree[n] == 0:
-                        Q.append(nodeset.nodes[n])
-                del dataType_refs[u.id]
-
-        for ref in u.inverseReferences:
-            if ref.referenceType.i == 40:
-                if not nodeset.nodes[ref.target].hidden:
-                    in_degree[ref.target] -= 1
-                if in_degree[ref.target] == 0:
-                    Q.append(nodeset.nodes[ref.target])
+    # Order the remaining nodes
+    Q = {node for node in R.values() if in_degree[node.id] == 0}
+    while Q:
+        u = Q.pop() # choose node of zero in-degree and 'remove' it from graph
+        L.append(u)
+        del R[u.id]
+
+        for ref in u.references:
+            if not ref.referenceType in relevant_refs:
+                continue
+            if nodeset.nodes[ref.target].hidden:
+                continue
+            if not ref.isForward:
+                continue
+            in_degree[ref.target] -= 1
+            if in_degree[ref.target] == 0:
+                Q.add(R[ref.target])
 
+    # reverse hastype references
+    for u in nodeset.nodes.values():
         for ref in u.references:
-            if (ref.referenceType in relevant_types and ref.isForward):
-                if not nodeset.nodes[ref.target].hidden:
-                    in_degree[ref.target] -= 1
-                if in_degree[ref.target] == 0:
-                    Q.append(nodeset.nodes[ref.target])
+            if ref.referenceType == hasTypeDef:
+                ref.isForward = not ref.isForward
 
-    if len(L) + hiddenCount != len(nodeset.nodes.values()):
+    if len(L) != len(nodeset.nodes.values()):
+        print(len(L))
         stillOpen = ""
         for id in in_degree:
             if in_degree[id] == 0:
                 continue
             node = nodeset.nodes[id]
-            stillOpen += node.browseName.name + "/" + str(node.id) + " = " + str(in_degree[id]) + "\r\n"
+            stillOpen += node.browseName.name + "/" + str(node.id) + " = " + str(in_degree[id]) + \
+                                                                         " " + str(node.references) + "\r\n"
         raise Exception("Node graph is circular on the specified references. Still open nodes:\r\n" + stillOpen)
     return L
 
@@ -232,7 +203,7 @@ UA_findDataTypeByBinary(const UA_NodeId *typeId);
 #ifdef __cplusplus
 extern "C" {
 #endif
-    
+
 extern UA_StatusCode %s(UA_Server *server);
 
 #ifdef __cplusplus
@@ -248,47 +219,57 @@ extern UA_StatusCode %s(UA_Server *server);
 #include "%s.h"
 """ % (outfilebase))
 
-    parentrefs = getSubTypesOf(nodeset, nodeset.getNodeByBrowseName("HierarchicalReferences"))
-    parentrefs = list(map(lambda x: x.id, parentrefs))
-
     # Loop over the sorted nodes
     logger.info("Reordering nodes for minimal dependencies during printing")
-    sorted_nodes = reorderNodesMinDependencies(nodeset)
+    sorted_nodes = sortNodes(nodeset)
     logger.info("Writing code for nodes and references")
-    
     functionNumber = 0
 
+    parentreftypes = getSubTypesOf(nodeset, nodeset.getNodeByBrowseName("HierarchicalReferences"))
+    parentreftypes = list(map(lambda x: x.id, parentreftypes))
+
+    printed_ids = set()
     for node in sorted_nodes:
-        # Print node
+        printed_ids.add(node.id)
+
+        parentref = node.popParentRef(parentreftypes)
         if not node.hidden:
             writec("\n/* " + str(node.displayName) + " - " + str(node.id) + " */")
-            code = generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, parentrefs)
+            code = generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, parentref)
             if code is None:
                 writec("/* Ignored. No parent */")
                 nodeset.hide_node(node.id)
                 continue
             else:
-                writec("\nstatic UA_StatusCode function_" + outfilebase + "_" + str(functionNumber) + "_begin(UA_Server *server, UA_UInt16* ns) {\n")
+                writec("\nstatic UA_StatusCode function_" + outfilebase + "_" + str(functionNumber) + "_begin(UA_Server *server, UA_UInt16* ns) {")
                 if isinstance(node, MethodNode):
                     writec("#ifdef UA_ENABLE_METHODCALLS")
                 writec(code)
 
         # Print inverse references leading to this node
-        for ref in node.printRefs:
+        for ref in node.references:
+            if ref.target not in printed_ids:
+                continue
+            if node.hidden and nodeset.nodes[ref.target].hidden:
+                continue
             writec(generateReferenceCode(ref))
-            
+
+        if node.hidden:
+            continue
+
         writec("return retVal;")
+
         if isinstance(node, MethodNode):
             writec("#else")
             writec("return UA_STATUSCODE_GOOD;")
             writec("#endif /* UA_ENABLE_METHODCALLS */")
         writec("}");
 
-        writec("\nstatic UA_StatusCode function_" + outfilebase + "_" + str(functionNumber) + "_finish(UA_Server *server, UA_UInt16* ns) {\n")
+        writec("\nstatic UA_StatusCode function_" + outfilebase + "_" + str(functionNumber) + "_finish(UA_Server *server, UA_UInt16* ns) {")
+
         if isinstance(node, MethodNode):
             writec("#ifdef UA_ENABLE_METHODCALLS")
-        code = generateNodeCode_finish(node)
-        writec("return " + code)
+        writec("return " + generateNodeCode_finish(node))
         if isinstance(node, MethodNode):
             writec("#else")
             writec("return UA_STATUSCODE_GOOD;")
@@ -300,6 +281,7 @@ extern UA_StatusCode %s(UA_Server *server);
     writec("""
 UA_StatusCode %s(UA_Server *server) {
 UA_StatusCode retVal = UA_STATUSCODE_GOOD;""" % (outfilebase))
+
     # Generate namespaces (don't worry about duplicates)
     writec("/* Use namespace ids generated by the server */")
     writec("UA_UInt16 ns[" + str(len(nodeset.namespaces)) + "];")
@@ -310,7 +292,6 @@ UA_StatusCode retVal = UA_STATUSCODE_GOOD;""" % (outfilebase))
     for i in range(0, functionNumber):
         writec("retVal |= function_" + outfilebase + "_" + str(i) + "_begin(server, ns);")
 
-
     for i in reversed(range(0, functionNumber)):
         writec("retVal |= function_" + outfilebase + "_" + str(i) + "_finish(server, ns);")
 

+ 20 - 72
tools/nodeset_compiler/backend_open62541_nodes.py

@@ -20,44 +20,10 @@ from nodes import *
 from backend_open62541_datatypes import *
 import re
 import datetime
-
-###########################################
-# Extract References with Special Meaning #
-###########################################
-
 import logging
 
 logger = logging.getLogger(__name__)
 
-def extractNodeParent(node, parentrefs):
-    """Return a tuple of the most likely (parent, parentReference). The
-    parentReference is removed form the inverse references list of the node.
-
-    """
-    for ref in node.inverseReferences:
-        if ref.referenceType in parentrefs:
-            node.inverseReferences.remove(ref)
-            if ref in node.printRefs:
-                node.printRefs.remove(ref)
-            return (ref.target, ref.referenceType)
-    return None, None
-
-def extractNodeType(node):
-    """Returns the most likely type of the variable- or objecttype node. The
-     isinstanceof reference is removed form the inverse references list of the
-     node.
-
-    """
-    pass
-
-def extractNodeSuperType(node):
-    """Returns the most likely supertype of the variable-, object-, or referencetype
-       node. The reference to the supertype is removed from the inverse
-       references list of the node.
-
-    """
-    pass
-
 #################
 # Generate Code #
 #################
@@ -304,12 +270,9 @@ def generateValueCodeDummy(dataTypeNode, parentNode, nodeset):
     typeStr = "UA_" + typeBrowseNode
 
     if parentNode.valueRank > 0:
-        code.append("UA_STACKARRAY(" + typeStr + ", " + valueName + "," + str(parentNode.valueRank) + ");")
         for i in range(0, parentNode.valueRank):
-            code.append("UA_init(&" + valueName + "[" + str(i) + "], &" + typeArr + ");")
-            code.append("UA_Variant_setArray(&attr.value, " + valueName + ", (UA_Int32) " +
-                        str(parentNode.valueRank) + ", &" + typeArr + ");")
-    else:
+            code.append("UA_Variant_setArray(&attr.value, NULL, (UA_Int32) " + "0, &" + typeArr + ");")
+    elif not dataTypeNode.isAbstract:
         code.append("UA_STACKARRAY(" + typeStr + ", " + valueName + ", 1);")
         code.append("UA_init(" + valueName + ", &" + typeArr + ");")
         code.append("UA_Variant_setScalar(&attr.value, " + valueName + ", &" + typeArr + ");")
@@ -460,12 +423,12 @@ def generateSubtypeOfDefinitionCode(node):
             return generateNodeIdCode(ref.target)
     return "UA_NODEID_NULL"
 
-def generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, parentrefs):
+def generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, parentref):
     code = []
-    code.append("UA_StatusCode retVal = UA_STATUSCODE_GOOD;")
-
     codeCleanup = []
+    code.append("UA_StatusCode retVal = UA_STATUSCODE_GOOD;")
 
+    # Attributes
     if isinstance(node, ReferenceTypeNode):
         code.extend(generateReferenceTypeNodeCode(node))
     elif isinstance(node, ObjectNode):
@@ -486,41 +449,27 @@ def generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, paren
         code.extend(generateDataTypeNodeCode(node))
     elif isinstance(node, ViewNode):
         code.extend(generateViewNodeCode(node))
-
-    code.append("attr.displayName = " + generateLocalizedTextCode(node.displayName, alloc=False, max_string_length=max_string_length) + ";")
-    code.append("attr.description = " + generateLocalizedTextCode(node.description, alloc=False, max_string_length=max_string_length) + ";")
+    code.append("attr.displayName = " + generateLocalizedTextCode(node.displayName, alloc=False,
+                                                                  max_string_length=max_string_length) + ";")
+    code.append("attr.description = " + generateLocalizedTextCode(node.description, alloc=False,
+                                                                  max_string_length=max_string_length) + ";")
     code.append("attr.writeMask = %d;" % node.writeMask)
     code.append("attr.userWriteMask = %d;" % node.userWriteMask)
 
-    typeDef = getNodeTypeDefinition(node)
-    isDataTypeEncodingType = typeDef is not None and typeDef.ns == 0 and typeDef.i == 76
-    # Object nodes of type DataTypeEncoding do not have any parent
-    if not generate_ns0 and not isDataTypeEncodingType:
-        (parentNode, parentRef) = extractNodeParent(node, parentrefs)
-        if parentNode is None or parentRef is None:
-            return None
-    else:
-        (parentNode, parentRef) = (NodeId(), NodeId())
-
-    code.append("retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_{},".format(node.__class__.__name__.upper().replace("NODE" ,"")))
+    # AddNodes call
+    code.append("retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_{},".
+                format(node.__class__.__name__.upper().replace("NODE" ,"")))
     code.append(generateNodeIdCode(node.id) + ",")
-    code.append(generateNodeIdCode(parentNode) + ",")
-    code.append(generateNodeIdCode(parentRef) + ",")
+    code.append(generateNodeIdCode(parentref.target) + ",")
+    code.append(generateNodeIdCode(parentref.referenceType) + ",")
     code.append(generateQualifiedNameCode(node.browseName, max_string_length=max_string_length) + ",")
-    if isinstance(node, VariableTypeNode):
-        # we need the HasSubtype reference
-        code.append(generateSubtypeOfDefinitionCode(node) + ",")
-    elif isinstance(node, VariableNode) or isinstance(node, ObjectNode):
-        typeDefCode = "UA_NODEID_NULL" if typeDef is None else generateNodeIdCode(typeDef)
-        code.append(typeDefCode + ",")
-        # remove hasTypeDef reference from list to be printed
-        for ref in node.printRefs:
-            if ref.referenceType.i == 40:
-                if (ref.isForward and ref.source == node.id) or (not ref.isForward and ref.target == node.id):
-                    node.printRefs.remove(ref)
+    if isinstance(node, VariableNode) or isinstance(node, ObjectNode):
+        typeDefRef = node.popTypeDef()
+        code.append(generateNodeIdCode(typeDefRef.target) + ",")
     else:
-        code.append("UA_NODEID_NULL,")
-    code.append("(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_{}ATTRIBUTES],NULL, NULL);".format(node.__class__.__name__.upper().replace("NODE" ,"")))
+        code.append(" UA_NODEID_NULL,")
+    code.append("(const UA_NodeAttributes*)&attr, &UA_TYPES[UA_TYPES_{}ATTRIBUTES],NULL, NULL);".
+                format(node.__class__.__name__.upper().replace("NODE" ,"")))
     code.extend(codeCleanup)
     
     return "\n".join(code)
@@ -528,7 +477,6 @@ def generateNodeCode_begin(node, nodeset, max_string_length, generate_ns0, paren
 def generateNodeCode_finish(node):
     code = []
 
-
     if isinstance(node, MethodNode):
         code.append("UA_Server_addMethodNode_finish(server, ")
     else:

+ 19 - 27
tools/nodeset_compiler/nodes.py

@@ -30,13 +30,11 @@ if sys.version_info[0] >= 3:
 
 class Reference(object):
     # all either nodeids or strings with an alias
-    def __init__(self, source, referenceType, target, isForward=True, hidden=False, inferred=False):
+    def __init__(self, source, referenceType, target, isForward):
         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
-        self.inferred = inferred
 
     def __str__(self):
         retval = str(self.source)
@@ -67,7 +65,6 @@ class Node(object):
         self.writeMask = 0
         self.userWriteMask = 0
         self.references = set()
-        self.inverseReferences = set()
         self.hidden = False
 
     def __str__(self):
@@ -133,10 +130,21 @@ class Node(object):
                         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))
+            self.references.add(Reference(source, reftype, target, forward))
+
+    def popParentRef(self, parentreftypes):
+        for ref in self.references:
+            if ref.referenceType in parentreftypes and not ref.isForward:
+                self.references.remove(ref)
+                return ref
+        return Reference(NodeId(), NodeId(), NodeId(), False)
+
+    def popTypeDef(self):
+        for ref in self.references:
+            if ref.referenceType.i == 40 and ref.isForward:
+                self.references.remove(ref)
+                return ref
+        return Reference(NodeId(), NodeId(), NodeId(), False)
 
     def replaceAliases(self, aliases):
         if str(self.id) in aliases:
@@ -151,23 +159,12 @@ class Node(object):
                 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]
         if hasattr(self, 'dataType') and isinstance(self.dataType, NodeId):
             self.dataType.ns = nsMapping[self.dataType.ns]
-
         new_refs = set()
         for ref in self.references:
             ref.source.ns = nsMapping[ref.source.ns]
@@ -175,13 +172,6 @@ class Node(object):
             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):
@@ -493,7 +483,9 @@ class DataTypeNode(Node):
 
         if self.__xmlDefinition__ == None:
             # Check if there is a supertype available
-            for ref in self.inverseReferences:
+            for ref in self.references:
+                if ref.isForward:
+                    continue
                 # hasSubtype
                 if ref.referenceType.i == 45:
                     targetNode = nodeset.nodes[ref.target]

+ 11 - 36
tools/nodeset_compiler/nodeset.py

@@ -171,13 +171,10 @@ class NodeSet(object):
         if ndtype == 'referencetype':
             node = ReferenceTypeNode(xmlelement)
 
-        if node and hidden:
-            node.hidden = True
-            # References from an existing nodeset are all suppressed
-            for ref in node.references:
-                ref.hidden = True
-            for ref in node.inverseReferences:
-                ref.hidden = True
+        if node == None:
+            return None
+
+        node.hidden = hidden
         return node
 
     def hide_node(self, nodeId, hidden=True):
@@ -185,11 +182,6 @@ class NodeSet(object):
             return False
         node = self.nodes[nodeId]
         node.hidden = hidden
-        # References from an existing nodeset are all suppressed
-        for ref in node.references:
-            ref.hidden = hidden
-        for ref in node.inverseReferences:
-            ref.hidden = hidden
         return True
 
     def merge_dicts(self, *dict_args):
@@ -252,19 +244,6 @@ class NodeSet(object):
             self.nodes[node.id] = node
             newnodes.append(node)
 
-        # add inverse references
-        for node in newnodes:
-            for ref in node.references:
-                newsource = self.nodes[ref.target]
-                hide = ref.hidden or (node.hidden and newsource.hidden)
-                newref = Reference(newsource.id, ref.referenceType, ref.source, False, hide, inferred=True)
-                newsource.inverseReferences.add(newref)
-            for ref in node.inverseReferences:
-                newsource = self.nodes[ref.target]
-                hide = ref.hidden or (node.hidden and newsource.hidden)
-                newref = Reference(newsource.id, ref.referenceType, ref.source, True, hide, inferred=True)
-                newsource.references.add(newref)
-
     def getBinaryEncodingIdForNode(self, nodeId):
         """
         The node should have a 'HasEncoding' forward reference which points to the encoding ids.
@@ -292,19 +271,19 @@ class NodeSet(object):
                 stat[n.isEncodable()] = stat[n.isEncodable()] + 1
         logger.debug("Type definitions built/passed: " +  str(stat))
 
-
     def allocateVariables(self):
         for n in self.nodes.values():
             if isinstance(n, VariableNode):
                 n.allocateValue(self)
 
-
     def getBaseDataType(self, node):
         if node is None:
             return None
         if node.browseName.name not in opaque_type_mapping:
             return node
-        for ref in node.inverseReferences:
+        for ref in node.references:
+            if ref.isForward:
+                continue
             if ref.referenceType.i == 45:
                 return self.getBaseDataType(self.nodes[ref.target])
         return node
@@ -328,11 +307,7 @@ class NodeSet(object):
         return None
 
     def getRelevantOrderingReferences(self):
-        relevant_types = getSubTypesOf(self,
-                                       self.getNodeByBrowseName("HierarchicalReferences"),
-                                       [])
-        relevant_types += getSubTypesOf(self,
-                                        self.getNodeByBrowseName("HasEncoding"),
-                                        [])
-        relevant_types = map(lambda x: x.id, relevant_types)
-        return list(relevant_types)
+        relevant_types = getSubTypesOf(self, self.getNodeByBrowseName("HierarchicalReferences"), [])
+        relevant_types += getSubTypesOf(self, self.getNodeByBrowseName("HasEncoding"), [])
+        relevant_types += getSubTypesOf(self, self.getNodeByBrowseName("HasTypeDefinition"), [])
+        return list(map(lambda x: x.id, relevant_types))