瀏覽代碼

Node instantiation is now biderictionally hierarchical (inheritance and child instantiation); recursion protection is in place.

ichrispa 9 年之前
父節點
當前提交
b0e4f46304
共有 4 個文件被更改,包括 227 次插入206 次删除
  1. 15 0
      include/ua_server.h
  2. 190 202
      src/server/ua_server_addressspace.c
  3. 10 1
      tools/pyUANamespace/open62541_MacroHelper.py
  4. 12 3
      tools/pyUANamespace/ua_namespace.py

+ 15 - 0
include/ua_server.h

@@ -500,6 +500,21 @@ UA_Server_addExternalNamespace(UA_Server *server, UA_UInt16 namespaceIndex, cons
 typedef UA_StatusCode (*UA_InstantiationCallback)(UA_NodeId objectId, UA_NodeId definitionId, void *handle);
 #endif
 
+typedef struct arrayOfNodeIds_s {
+  UA_Int32  size;
+  UA_NodeId *ids;
+} arrayOfNodeIds;
+
+UA_StatusCode 
+UA_Server_appendInstanceOfSupertype(UA_Server *server, UA_NodeId nodeId, UA_NodeId appendToNodeId, 
+                                    arrayOfNodeIds *subtypeRefs, arrayOfNodeIds *componentRefs, 
+                                    UA_InstantiationCallback *callback, arrayOfNodeIds *instantiatedTypes);
+
+void 
+UA_Server_addInstanceOf_instatiateChildNode(UA_Server *server, 
+                                            arrayOfNodeIds *subtypeRefs, arrayOfNodeIds *componentRefs, arrayOfNodeIds *typedefRefs,
+                                            UA_NodeId objectRoot, UA_InstantiationCallback *callback, void *typeDefNode,
+                                            UA_Boolean instantiateObjects, arrayOfNodeIds *instantiatedTypes);
 UA_StatusCode UA_EXPORT
 UA_Server_addInstanceOf(UA_Server *server, UA_NodeId nodeId, const UA_QualifiedName browseName,
                         UA_LocalizedText displayName, UA_LocalizedText description, const UA_NodeId parentNodeId, 

+ 190 - 202
src/server/ua_server_addressspace.c

@@ -1204,84 +1204,126 @@ UA_StatusCode UA_Server_getAttributeValue(UA_Server *server, UA_NodeId nodeId, U
   return retval;
 }
 
-UA_StatusCode UA_Server_appendInstanceOfSupertype(UA_Server *server, UA_NodeId nodeId, UA_NodeId appendToNodeId, 
-                                                  UA_InstantiationCallback *callback);
-UA_StatusCode UA_Server_appendInstanceOfSupertype(UA_Server *server, UA_NodeId nodeId, UA_NodeId appendToNodeId, 
-                                                  UA_InstantiationCallback *callback)  {
+
+#define arrayOfNodeIds_addNodeId(ARRAYNAME, NODEID) { \
+  ARRAYNAME.size++; \
+  ARRAYNAME.ids = UA_realloc(ARRAYNAME.ids, sizeof(UA_NodeId) * ARRAYNAME.size); \
+  UA_NodeId_copy(&NODEID, &ARRAYNAME.ids[ARRAYNAME.size-1]); \
+}
+
+#define arrayOfNodeIds_deleteMembers(ARRAYNAME) { \
+  if (ARRAYNAME.size > 0)   \
+    UA_free(ARRAYNAME.ids); \
+  ARRAYNAME.size = 0;       \
+}
+
+#define arrayOfNodeIds_idInArray(ARRAYNAME, NODEID, BOOLEAN, BOOLINIT) { \
+  BOOLEAN = BOOLINIT;\
+  for (int z=0; z<ARRAYNAME.size; z++) {\
+    if (UA_NodeId_equal(&ARRAYNAME.ids[z], &NODEID)) {\
+      BOOLEAN = !BOOLINIT; \
+      break; \
+    } \
+  } \
+} \
+
+static void UA_Server_addInstanceOf_inheritParentAttributes(UA_Server *server, arrayOfNodeIds *subtypeRefs, arrayOfNodeIds *componentRefs, 
+                                                            UA_NodeId objectRoot, UA_InstantiationCallback *callback, UA_ObjectTypeNode *typeDefNode,
+                                                            arrayOfNodeIds *instantiatedTypes) 
+{
+  UA_Boolean refTypeValid;
+  UA_ReferenceNode ref;
+  arrayOfNodeIds visitedNodes = (arrayOfNodeIds) {.size=0, .ids = NULL};
+  for(int i=0; i<typeDefNode->referencesSize; i++) {
+    ref = typeDefNode->references[i];
+    if (ref.isInverse == UA_FALSE)
+      continue;
+    refTypeValid = UA_FALSE;
+    arrayOfNodeIds_idInArray((*subtypeRefs), ref.referenceTypeId, refTypeValid, UA_FALSE);
+    if (!refTypeValid) 
+      continue;
+    
+    // Check if already tried to inherit from this node (there is such a thing as duplicate refs)
+    arrayOfNodeIds_idInArray(visitedNodes, ref.targetId.nodeId, refTypeValid, UA_TRUE);
+    if (!refTypeValid) 
+      continue;
+    // Go ahead and inherit this nodes variables and methods (not objects!)
+    arrayOfNodeIds_addNodeId(visitedNodes, ref.targetId.nodeId);
+    UA_Server_appendInstanceOfSupertype(server, ref.targetId.nodeId, objectRoot, subtypeRefs, componentRefs, callback, instantiatedTypes);
+  } // End check all hassubtype refs
+  arrayOfNodeIds_deleteMembers(visitedNodes);
+  return;
+}
+
+static void UA_Server_addInstanceOf_instatiateChildObject(UA_Server *server, 
+                                                          arrayOfNodeIds *subtypeRefs, arrayOfNodeIds *componentRefs, arrayOfNodeIds *typedefRefs,
+                                                          UA_Node *objectCopy, UA_NodeId parentId, UA_ExpandedNodeId typeDefinition, UA_NodeId referenceTypeId,
+                                                          UA_InstantiationCallback *callback, UA_Boolean instantiateObjects, arrayOfNodeIds *instantiatedTypes) 
+{
   UA_StatusCode retval = UA_STATUSCODE_GOOD;
-  UA_Int32 inheritedFromIdsSize = 0;
-  UA_NodeId *inheritedFromIds = NULL;
+  
+  // Refuse to create this node if we detect a circular type definition
+  UA_Boolean typeDefRecursion;
+  arrayOfNodeIds_idInArray((*instantiatedTypes), typeDefinition.nodeId, typeDefRecursion, UA_FALSE);
+  if (typeDefRecursion) 
+    return;
   
   UA_Node *typeDefNode;
-  UA_Server_getNodeCopy(server, nodeId, (void *) &typeDefNode);
+  UA_Server_getNodeCopy(server, typeDefinition.nodeId, (void *) &typeDefNode);
+  
   if (typeDefNode == NULL) {
-    return UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+    return;
   }
   if (!typeDefNode->nodeClass == UA_NODECLASS_OBJECTTYPE) {
     UA_Server_deleteNodeCopy(server, (void **) &typeDefNode);
-    return UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+    return;
   }
   
-  // These refs will be examined later. 
-  // FIXME: Create these arrays dynamically to include any subtypes as well
-  UA_Int32 subtypeRefsSize = 1;
-  UA_NodeId subtypeRefs[] = { UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE)};
-  UA_Int32 componentRefsSize = 2;
-  UA_NodeId componentRefs[] = { UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY)};
+  // Create the object root as specified by the user
+  UA_NodeId objectRoot;
+  retval |= UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(parentId.namespaceIndex, 0), objectCopy->browseName, objectCopy->displayName, 
+                                    objectCopy->description, parentId, referenceTypeId, objectCopy->userWriteMask, objectCopy->writeMask,
+                                    typeDefinition, &objectRoot);
+  if (retval)
+    return;
+   
+  UA_ExpandedNodeId *objectRootExpanded = UA_ExpandedNodeId_new();
+  UA_NodeId_copy(&objectRoot, &objectRootExpanded->nodeId );
   
-  UA_ReferenceNode ref;
+  // (1) If this node is a subtype of any other node, create its things first
+  UA_Server_addInstanceOf_inheritParentAttributes(server, subtypeRefs, componentRefs, objectRoot, callback, 
+                                                  (UA_ObjectTypeNode *) typeDefNode, instantiatedTypes);
+  
+  // (2) For each object or variable referenced with hasComponent or hasProperty, create a new node of that
+  //     type for this objectRoot
+  UA_Server_addInstanceOf_instatiateChildNode(server, subtypeRefs, componentRefs, typedefRefs,
+                                              objectRoot, callback, (UA_ObjectTypeNode *) typeDefNode, 
+                                              UA_TRUE, instantiatedTypes);
+  
+  UA_ExpandedNodeId_delete(objectRootExpanded);
+  UA_Server_deleteNodeCopy(server, (void **) &typeDefNode);
+  return;
+}
+  
+void UA_Server_addInstanceOf_instatiateChildNode(UA_Server *server, 
+                                                arrayOfNodeIds *subtypeRefs, arrayOfNodeIds *componentRefs, arrayOfNodeIds *typedefRefs,
+                                                UA_NodeId objectRoot, UA_InstantiationCallback *callback, void *typeDefNode,
+                                                UA_Boolean instantiateObjects, arrayOfNodeIds *instantiatedTypes) 
+{
   UA_Boolean refTypeValid;
   UA_NodeClass *refClass;
   UA_Node      *nodeClone;
   UA_ExpandedNodeId *objectRootExpanded = UA_ExpandedNodeId_new();
-  UA_NodeId_copy(&appendToNodeId, &objectRootExpanded->nodeId );
   UA_VariableNode *newVarNode;
   UA_VariableTypeNode *varTypeNode;
-  for(int i=0; i<typeDefNode->referencesSize; i++) {
-    ref = typeDefNode->references[i];
-    if (ref.isInverse == UA_FALSE)
-      continue;
-    refTypeValid = UA_FALSE;
-    for (int j=0; j<subtypeRefsSize; j++) {
-      if (UA_NodeId_equal(&subtypeRefs[j], &ref.referenceTypeId)) {
-        refTypeValid = UA_TRUE;
-        break;
-      }
-    } // End check isSubtype ref
-    if (!refTypeValid) 
-      continue;
-    
-    // Check if already tried to inherit from this node (there is such a thing as duplicate refs)
-    refTypeValid = UA_TRUE;
-    for (int k=0; k<inheritedFromIdsSize; k++) {
-      if (UA_NodeId_equal(&inheritedFromIds[k], &ref.targetId.nodeId)) {
-        refTypeValid = UA_FALSE;
-        break;
-      }
-    }
-    if (!refTypeValid) 
-      continue;
-    
-    // Go ahead and inherit this nodes variables and methods (not objects!)
-    inheritedFromIdsSize++;
-    inheritedFromIds = UA_realloc(inheritedFromIds, sizeof(UA_NodeId) * inheritedFromIdsSize);
-    UA_NodeId_copy(&ref.targetId.nodeId, &inheritedFromIds[inheritedFromIdsSize-1]);
-    UA_Server_appendInstanceOfSupertype(server, ref.targetId.nodeId, appendToNodeId, callback);
-  } // End check all hassubtype refs
-  inheritedFromIdsSize = 0;
-  UA_free(inheritedFromIds);
+  UA_ReferenceNode ref;
+  UA_NodeId_copy(&objectRoot, &objectRootExpanded->nodeId );
   
-  for(int i=0; i<typeDefNode->referencesSize; i++) {
-    ref = typeDefNode->references[i];
+  for(int i=0; i< ((UA_ObjectTypeNode *) typeDefNode)->referencesSize; i++) {
+    ref = ((UA_ObjectTypeNode *) typeDefNode)->references[i];
     if (ref.isInverse)
       continue;
-    refTypeValid = UA_FALSE;
-    for (int j=0; j<componentRefsSize; j++) {
-      if (UA_NodeId_equal(&componentRefs[j], &ref.referenceTypeId)) {
-        refTypeValid = UA_TRUE;
-        break;
-      }
-    } // End check hasComponent ref
+    arrayOfNodeIds_idInArray((*componentRefs), ref.referenceTypeId, refTypeValid, UA_FALSE);
     if (!refTypeValid) 
       continue;
     
@@ -1292,14 +1334,14 @@ UA_StatusCode UA_Server_appendInstanceOfSupertype(UA_Server *server, UA_NodeId n
       case UA_NODECLASS_VARIABLE: // Just clone the variable node with a new nodeId
         UA_Server_getNodeCopy(server, ref.targetId.nodeId, (void **) &nodeClone);
         UA_NodeId_init(&nodeClone->nodeId);
-        nodeClone->nodeId.namespaceIndex = appendToNodeId.namespaceIndex;
+        nodeClone->nodeId.namespaceIndex = objectRoot.namespaceIndex;
         if (nodeClone != NULL)
           UA_Server_addNode(server, nodeClone,  *objectRootExpanded, ref.referenceTypeId);
         break;
       case UA_NODECLASS_VARIABLETYPE: // Convert from a value protoype to a value, then add it
         UA_Server_getNodeCopy(server, ref.targetId.nodeId, (void **) &varTypeNode);
         newVarNode = UA_VariableNode_new();
-        newVarNode->nodeId.namespaceIndex = appendToNodeId.namespaceIndex;
+        newVarNode->nodeId.namespaceIndex = objectRoot.namespaceIndex;
         UA_QualifiedName_copy(&varTypeNode->browseName, &varTypeNode->browseName);
         UA_LocalizedText_copy(&varTypeNode->displayName, &varTypeNode->displayName);
         UA_LocalizedText_copy(&varTypeNode->description, &varTypeNode->description);
@@ -1317,17 +1359,77 @@ UA_StatusCode UA_Server_appendInstanceOfSupertype(UA_Server *server, UA_NodeId n
         UA_Server_deleteNodeCopy(server, (void **) &newVarNode);
         UA_Server_deleteNodeCopy(server, (void **) &varTypeNode);
         break;
+      case UA_NODECLASS_OBJECT: // An object may have it's own inheritance or child nodes
+        if (!instantiateObjects)
+          break;
+        
+        UA_Server_getNodeCopy(server, ref.targetId.nodeId, (void **) &nodeClone);
+        if (nodeClone == UA_NULL)
+          break; // switch
+          
+          // Retrieve this nodes type definition
+          UA_ExpandedNodeId_init(objectRootExpanded); // Slight misuse of an unsused ExpandedNodeId to encode the typeDefinition
+          int tidx;
+          for(tidx=0; tidx<nodeClone->referencesSize; tidx++) {
+            arrayOfNodeIds_idInArray((*typedefRefs), nodeClone->references[tidx].referenceTypeId, refTypeValid, UA_FALSE);
+            if (refTypeValid) 
+              break;
+          } // End iterate over nodeClone refs
+          
+          if (!refTypeValid) // This may be plain wrong, but since got this far...
+            objectRootExpanded->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE);
+          else
+            UA_ExpandedNodeId_copy(&nodeClone->references[tidx].targetId, objectRootExpanded);
+          
+          int lastArrayDepth = instantiatedTypes->size;
+          arrayOfNodeIds_addNodeId((*instantiatedTypes), ((UA_ObjectTypeNode *) typeDefNode)->nodeId);
+          
+          UA_Server_addInstanceOf_instatiateChildObject(server, subtypeRefs, componentRefs, typedefRefs, nodeClone,
+                                                        objectRoot, *objectRootExpanded, ref.referenceTypeId,
+                                                        callback, UA_TRUE, instantiatedTypes);
+          instantiatedTypes->size = lastArrayDepth;
+          instantiatedTypes->ids = (UA_NodeId *) realloc(instantiatedTypes->ids, lastArrayDepth);
+          
+          UA_Server_deleteNodeCopy(server, (void **) &nodeClone);
+          UA_ExpandedNodeId_deleteMembers(objectRootExpanded); // since we only borrowed this, reset it
+          UA_NodeId_copy(&objectRoot, &objectRootExpanded->nodeId );
+          break;
       case UA_NODECLASS_METHOD: // Link this method (don't clone the node)
-        UA_Server_AddMonodirectionalReference(server, appendToNodeId, ref.targetId, ref.referenceTypeId, UA_TRUE);
+        UA_Server_AddMonodirectionalReference(server, objectRoot, ref.targetId, ref.referenceTypeId, UA_TRUE);
         break;
       default:
-        printf("We don't care about nodeclass %d\n", *refClass);
+        break;
     }
     UA_NodeClass_delete(refClass);
   }
-  UA_ExpandedNodeId_delete(objectRootExpanded);
-  UA_Server_deleteNodeCopy(server, (void **) &typeDefNode);
-  return retval;
+  return;
+}
+
+UA_StatusCode UA_Server_appendInstanceOfSupertype(UA_Server *server, UA_NodeId nodeId, UA_NodeId appendToNodeId, 
+                                                  arrayOfNodeIds *subtypeRefs, arrayOfNodeIds *componentRefs, 
+                                                  UA_InstantiationCallback *callback, arrayOfNodeIds *instantiatedTypes)  {
+UA_StatusCode retval = UA_STATUSCODE_GOOD;
+
+UA_Node *typeDefNode;
+UA_Server_getNodeCopy(server, nodeId, (void *) &typeDefNode);
+if (typeDefNode == NULL) {
+return UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+}
+if (!typeDefNode->nodeClass == UA_NODECLASS_OBJECTTYPE) {
+UA_Server_deleteNodeCopy(server, (void **) &typeDefNode);
+return UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
+}
+
+UA_ExpandedNodeId *objectRootExpanded = UA_ExpandedNodeId_new();
+UA_NodeId_copy(&appendToNodeId, &objectRootExpanded->nodeId );
+// (1) If this node is a subtype of any other node, create its things first
+UA_Server_addInstanceOf_inheritParentAttributes(server, subtypeRefs, componentRefs, appendToNodeId, callback, 
+                                                (UA_ObjectTypeNode *) typeDefNode, instantiatedTypes);
+
+UA_Server_addInstanceOf_instatiateChildNode(server, subtypeRefs, componentRefs, UA_NULL, 
+                                            appendToNodeId, callback, (UA_ObjectTypeNode *) typeDefNode, 
+                                            UA_FALSE, instantiatedTypes);
+return retval;
 }
 
 UA_StatusCode UA_Server_addInstanceOf(UA_Server *server, UA_NodeId nodeId, const UA_QualifiedName browseName,
@@ -1337,9 +1439,6 @@ UA_StatusCode UA_Server_addInstanceOf(UA_Server *server, UA_NodeId nodeId, const
 {
   UA_StatusCode retval = UA_STATUSCODE_GOOD;
   
-  UA_Int32 inheritedFromIdsSize = 0;
-  UA_NodeId *inheritedFromIds = NULL;
-  
   UA_Node *typeDefNode;
   UA_Server_getNodeCopy(server, typeDefinition.nodeId, (void *) &typeDefNode);
   
@@ -1362,147 +1461,36 @@ UA_StatusCode UA_Server_addInstanceOf(UA_Server *server, UA_NodeId nodeId, const
   
   // These refs will be examined later. 
   // FIXME: Create these arrays dynamically to include any subtypes as well
-  UA_Int32 subtypeRefsSize = 1;
-  UA_NodeId subtypeRefs[] = { UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE)};
-  UA_Int32 componentRefsSize = 2;
-  UA_NodeId componentRefs[] = { UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY)};
-  UA_Int32 typedefRefsSize = 1;
-  UA_NodeId typedefRefs[] = { UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION)};
+  arrayOfNodeIds subtypeRefs = (arrayOfNodeIds) {
+    .size  = 1,
+    .ids   = (UA_NodeId[]) { UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE)}
+  };
+  arrayOfNodeIds componentRefs = (arrayOfNodeIds) {
+    .size = 2,
+    .ids  = (UA_NodeId[]) { UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY)}
+  };
+  arrayOfNodeIds typedefRefs = (arrayOfNodeIds) {
+    .size = 1,
+    .ids  = (UA_NodeId[]) { UA_NODEID_NUMERIC(0, UA_NS0ID_HASTYPEDEFINITION)}
+  };
   
-  UA_ReferenceNode ref;
-  UA_Boolean refTypeValid;
-  UA_NodeClass *refClass;
-  UA_Node      *nodeClone;
   UA_ExpandedNodeId *objectRootExpanded = UA_ExpandedNodeId_new();
-  UA_VariableNode *newVarNode;
-  UA_VariableTypeNode *varTypeNode;
   UA_NodeId_copy(&objectRoot, &objectRootExpanded->nodeId );
   
+  arrayOfNodeIds instantiatedTypes = (arrayOfNodeIds ) {.size=0, .ids=NULL};
+  arrayOfNodeIds_addNodeId(instantiatedTypes, typeDefNode->nodeId);
+  
   // (1) If this node is a subtype of any other node, create its things first
-  for(int i=0; i<typeDefNode->referencesSize; i++) {
-    ref = typeDefNode->references[i];
-    if (ref.isInverse == UA_FALSE)
-      continue;
-    refTypeValid = UA_FALSE;
-    for (int j=0; j<subtypeRefsSize; j++) {
-      if (UA_NodeId_equal(&subtypeRefs[j], &ref.referenceTypeId)) {
-        refTypeValid = UA_TRUE;
-        break;
-      }
-    } // End check isSubtype ref
-    if (!refTypeValid) 
-      continue;
-    
-    // Check if already tried to inherit from this node (there is such a thing as duplicate refs)
-    refTypeValid = UA_TRUE;
-    for (int k=0; k<inheritedFromIdsSize; k++) {
-      if (UA_NodeId_equal(&inheritedFromIds[k], &ref.targetId.nodeId)) {
-        refTypeValid = UA_FALSE;
-        break;
-      }
-    }
-    if (!refTypeValid) 
-      continue;
-    
-    // Go ahead and inherit this nodes variables and methods (not objects!)
-    inheritedFromIdsSize++;
-    inheritedFromIds = UA_realloc(inheritedFromIds, sizeof(UA_NodeId) * inheritedFromIdsSize);
-    UA_NodeId_copy(&ref.targetId.nodeId, &inheritedFromIds[inheritedFromIdsSize-1]);
-    UA_Server_appendInstanceOfSupertype(server, ref.targetId.nodeId, objectRoot, callback);
-  } // End check all hassubtype refs
-  inheritedFromIdsSize = 0;
-  UA_free(inheritedFromIds); 
+  UA_Server_addInstanceOf_inheritParentAttributes(server, &subtypeRefs, &componentRefs, objectRoot, callback, 
+                                                  (UA_ObjectTypeNode *) typeDefNode, &instantiatedTypes);
   
   // (2) For each object or variable referenced with hasComponent or hasProperty, create a new node of that
   //     type for this objectRoot
-  for(int i=0; i<typeDefNode->referencesSize; i++) {
-    ref = typeDefNode->references[i];
-    if (ref.isInverse)
-      continue;
-    refTypeValid = UA_FALSE;
-    for (int j=0; j<componentRefsSize; j++) {
-      if (UA_NodeId_equal(&componentRefs[j], &ref.referenceTypeId)) {
-        refTypeValid = UA_TRUE;
-        break;
-      }
-    } // End check hasComponent ref
-    if (!refTypeValid) 
-      continue;
-    
-    // What type of node is this?
-    refClass = NULL;
-    UA_Server_getAttributeValue(server, ref.targetId.nodeId, UA_ATTRIBUTEID_NODECLASS, (void **) &refClass);
-    switch (*refClass) {
-      case UA_NODECLASS_VARIABLE: // Just clone the variable node with a new nodeId
-        UA_Server_getNodeCopy(server, ref.targetId.nodeId, (void **) &nodeClone);
-        UA_NodeId_init(&nodeClone->nodeId);
-        nodeClone->nodeId.namespaceIndex = objectRoot.namespaceIndex;
-        if (nodeClone != NULL)
-          UA_Server_addNode(server, nodeClone,  *objectRootExpanded, ref.referenceTypeId);
-        break;
-      case UA_NODECLASS_VARIABLETYPE: // Convert from a value protoype to a value, then add it
-        UA_Server_getNodeCopy(server, ref.targetId.nodeId, (void **) &varTypeNode);
-        newVarNode = UA_VariableNode_new();
-        newVarNode->nodeId.namespaceIndex = objectRoot.namespaceIndex;
-        UA_QualifiedName_copy(&varTypeNode->browseName, &varTypeNode->browseName);
-        UA_LocalizedText_copy(&varTypeNode->displayName, &varTypeNode->displayName);
-        UA_LocalizedText_copy(&varTypeNode->description, &varTypeNode->description);
-        newVarNode->writeMask = varTypeNode->writeMask;
-        newVarNode->userWriteMask = varTypeNode->userWriteMask;
-        newVarNode->valueRank = varTypeNode->valueRank;
-        
-        newVarNode->valueSource = varTypeNode->valueSource;
-        if (varTypeNode->valueSource == UA_VALUESOURCE_DATASOURCE)
-          newVarNode->value.dataSource = varTypeNode->value.dataSource;
-        else
-          UA_Variant_copy(&varTypeNode->value.variant, &newVarNode->value.variant);
-        
-        UA_Server_addNode(server, (UA_Node *) newVarNode, *objectRootExpanded, ref.referenceTypeId);
-        UA_Server_deleteNodeCopy(server, (void **) &newVarNode);
-        UA_Server_deleteNodeCopy(server, (void **) &varTypeNode);
-        break;
-      case UA_NODECLASS_OBJECT: // An object may have it's own inheritance or child nodes
-        UA_Server_getNodeCopy(server, ref.targetId.nodeId, (void **) &nodeClone);
-        if (nodeClone == UA_NULL)
-          break; // switch
-          
-        // Retrieve this nodes type definition
-        UA_ExpandedNodeId_init(objectRootExpanded); // Slight misuse of an unsused ExpandedNodeId to encode the typeDefinition
-        for(int k=0; k<nodeClone->referencesSize; k++) {
-          refTypeValid = UA_FALSE;
-          for (int j=0; j<typedefRefsSize; j++) {
-            if (UA_NodeId_equal(&typedefRefs[j], &nodeClone->references[k].referenceTypeId)) {
-              refTypeValid = UA_TRUE;
-              UA_ExpandedNodeId_copy(&nodeClone->references[k].targetId, objectRootExpanded);
-              break;
-            }
-          } // End check isTypedef ref
-          if (!refTypeValid) 
-            continue;
-        } // End iterate over nodeClone refs
-        
-        if (!refTypeValid) // This may be plain wrong, but since got this far...
-          objectRootExpanded->nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE);
-        // ... we might as well keep going
-        
-        UA_Server_addInstanceOf(server, UA_NODEID_NUMERIC(objectRoot.namespaceIndex, 0), nodeClone->browseName,
-                                nodeClone->displayName, nodeClone->description, objectRoot, 
-                                ref.referenceTypeId,nodeClone->userWriteMask, nodeClone->writeMask, 
-                                *objectRootExpanded, callback, NULL
-        );
-        UA_Server_deleteNodeCopy(server, (void **) &nodeClone);
-        UA_ExpandedNodeId_deleteMembers(objectRootExpanded); // since we only borrowed this, reset it
-        UA_NodeId_copy(&objectRoot, &objectRootExpanded->nodeId );
-        break;
-      case UA_NODECLASS_METHOD: // Link this method (don't clone the node)
-        UA_Server_AddMonodirectionalReference(server, objectRoot, ref.targetId, ref.referenceTypeId, UA_TRUE);
-        break;
-      default:
-        printf("We don't care about nodeclass %d\n", *refClass);
-    }
-    UA_NodeClass_delete(refClass);
-  }
-
+  UA_Server_addInstanceOf_instatiateChildNode(server, &subtypeRefs, &componentRefs, &typedefRefs,
+                                              objectRoot, callback, (UA_ObjectTypeNode *) typeDefNode, 
+                                              UA_TRUE, &instantiatedTypes);
+  arrayOfNodeIds_deleteMembers(instantiatedTypes);
+  
   UA_ExpandedNodeId_delete(objectRootExpanded);
   UA_Server_deleteNodeCopy(server, (void **) &typeDefNode);
   return retval;

+ 10 - 1
tools/pyUANamespace/open62541_MacroHelper.py

@@ -38,7 +38,16 @@ class open62541_MacroHelper():
       return ""
     else:
       return ""
-
+  
+  def getNodeIdDefineString(self, node):
+    code = []
+    extrNs = node.browseName().split(":")
+    if len(extrNs) > 1:
+      code.append("#define UA_NS"  + str(node.id().ns) + "ID_" + extrNs[1].upper())
+    else:
+      code.append("#define UA_NS"  + str(node.id().ns) + "ID_" + extrNs[0].upper())
+    return code
+  
   def getCreateNodeIDMacro(self, node):
     if node.id().i != None:
       return "UA_NODEID_NUMERIC(" + str(node.id().ns) + ", " + str(node.id().i) + ")"

+ 12 - 3
tools/pyUANamespace/ua_namespace.py

@@ -23,6 +23,7 @@ from struct import pack as structpack
 from logger import *;
 from ua_builtin_types import *;
 from ua_node_types import *;
+from ua_constants import *;
 from open62541_MacroHelper import open62541_MacroHelper
 
 def getNextElementNode(xmlvalue):
@@ -634,8 +635,6 @@ class opcua_namespace():
     header.append('#include "server/ua_server_internal.h"')
     header.append('#include "server/ua_nodes.h"')
     header.append('#include "ua_types.h"')
-    header.append("extern void "+outfilename+"(UA_Server *server);\n")
-    header.append("#endif /* "+outfilename.upper()+"_H_ */")
 
     code.append('#include "'+outfilename+'.h"')
     code.append("inline void "+outfilename+"(UA_Server *server) {")
@@ -646,6 +645,13 @@ class opcua_namespace():
     log(self, "Collecting all references used in the namespace.", LOG_LEVEL_DEBUG)
     refsUsed = []
     for n in self.nodes:
+      # Since we are already looping over all nodes, use this chance to print NodeId defines
+      if n.id().ns != 0:
+        nc = n.nodeClass()
+        if nc != NODE_CLASS_OBJECT and nc != NODE_CLASS_VARIABLE and nc != NODE_CLASS_VIEW:
+          header = header + codegen.getNodeIdDefineString(n)
+          
+      # Now for the actual references...
       for r in n.getReferences():
         # Only print valid refernces in namespace 0 (users will not want their refs bootstrapped)
         if not r.referenceType() in refsUsed and r.referenceType() != None and r.referenceType().id().ns == 0:
@@ -653,7 +659,10 @@ class opcua_namespace():
     log(self, str(len(refsUsed)) + " reference types are used in the namespace, which will now get bootstrapped.", LOG_LEVEL_DEBUG)
     for r in refsUsed:
       code = code + r.printOpen62541CCode(unPrintedNodes, unPrintedRefs);
-
+    
+    header.append("extern void "+outfilename+"(UA_Server *server);\n")
+    header.append("#endif /* "+outfilename.upper()+"_H_ */")
+    
     # Note to self: do NOT - NOT! - try to iterate over unPrintedNodes!
     #               Nodes remove themselves from this list when printed.
     log(self, "Printing all other nodes.", LOG_LEVEL_DEBUG)