/// <summary> /// Does any initialization required before the address space can be used. /// </summary> /// <remarks> /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// </remarks> public override void CreateAddressSpace(IDictionary <NodeId, IList <IReference> > externalReferences) { lock (Lock) { base.CreateAddressSpace(externalReferences); // Note: might be helpful for debugging //// var env = new AdminShell.PackageEnv("Festo-USB-stick-sample-admin-shell.aasx"); if (true) { var builder = new AasEntityBuilder(this, thePackageEnv, null, this.theServerOptions); // Root of whole structure is special, needs to link to external reference builder.RootAAS = builder.CreateAddFolder(null, "AASROOT"); // Note: this is TOTALLY WEIRD, but it establishes an inverse reference .. somehow this.AddExternalReferencePublic(new NodeId(85, 0), ReferenceTypeIds.Organizes, false, builder.RootAAS.NodeId, externalReferences); this.AddExternalReferencePublic(builder.RootAAS.NodeId, ReferenceTypeIds.Organizes, true, new NodeId(85, 0), externalReferences); // Folders for DataSpecs // DO NOT USE THIS FEATURE -> Data Spec are "under" the CDs //// builder.RootDataSpecifications = builder.CreateAddFolder( //// builder.RootAAS, "DataSpecifications"); //// builder.RootDataSpecifications = builder.CreateAddObject( //// builder.RootAAS, "DataSpecifications"); if (false) // ReSharper disable once HeuristicUnreachableCode #pragma warning disable 162 { // Folders for Concept Descriptions // ReSharper disable once HeuristicUnreachableCode builder.RootConceptDescriptions = builder.CreateAddFolder( builder.RootAAS, "ConceptDescriptions"); // create missing dictionary entries builder.RootMissingDictionaryEntries = builder.CreateAddFolder( builder.RootAAS, "DictionaryEntries"); } #pragma warning restore 162 else { // create folder(s) under root var topOfDict = builder.CreateAddObject(null, "Dictionaries", referenceTypeFromParentId: null, typeDefinitionId: builder.AasTypes.DictionaryFolderType.GetTypeNodeId()); // Note: this is TOTALLY WEIRD, but it establishes an inverse reference .. somehow // 2253 = Objects? this.AddExternalReferencePublic(new NodeId(2253, 0), ReferenceTypeIds.HasComponent, false, topOfDict.NodeId, externalReferences); this.AddExternalReferencePublic(topOfDict.NodeId, ReferenceTypeIds.HasComponent, true, new NodeId(2253, 0), externalReferences); // now, create a dictionary under .. // Folders for Concept Descriptions builder.RootConceptDescriptions = builder.CreateAddObject(topOfDict, "ConceptDescriptions", referenceTypeFromParentId: ReferenceTypeIds.HasComponent, typeDefinitionId: builder.AasTypes.DictionaryFolderType.GetTypeNodeId()); // create missing dictionary entries builder.RootMissingDictionaryEntries = builder.CreateAddObject(topOfDict, "DictionaryEntries", referenceTypeFromParentId: ReferenceTypeIds.HasComponent, typeDefinitionId: builder.AasTypes.DictionaryFolderType.GetTypeNodeId()); } // start process builder.CreateAddInstanceObjects(thePackageEnv.AasEnv); } // Try: ensure the reverse refernces exist. //// AddReverseReferences(externalReferences); if (theServerOptions != null && theServerOptions.SpecialJob == AasxUaServerOptions.JobType.ExportNodesetXml) { try { // empty list var nodesToExport = new NodeStateCollection(); // apply filter criteria foreach (var y in this.PredefinedNodes) { var node = y.Value; if (theServerOptions.ExportFilterNamespaceIndex != null && !theServerOptions.ExportFilterNamespaceIndex.Contains(node.NodeId.NamespaceIndex)) { continue; } nodesToExport.Add(node); } // export Utils.Trace("Writing export file: " + theServerOptions.ExportFilename); var stream = new StreamWriter(theServerOptions.ExportFilename); //// nodesToExport.SaveAsNodeSet2(this.SystemContext, stream.BaseStream, null, //// theServerOptions != null && theServerOptions.FilterForSingleNodeIds); try { stream.Close(); } // ReSharper disable once EmptyGeneralCatchClause catch { } // stop afterwards if (theServerOptions.FinalizeAction != null) { Utils.Trace("Requesting to shut down application.."); theServerOptions.FinalizeAction(); } } catch (Exception ex) { Utils.Trace(ex, "When exporting to {0}", "" + theServerOptions.ExportFilename); } // shutdown .. } Debug.WriteLine("Done creating custom address space!"); Utils.Trace("Done creating custom address space!"); } }
/// <summary> /// Does any initialization required before the address space can be used. /// </summary> /// <remarks> /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// </remarks> public override void CreateAddressSpace(IDictionary <NodeId, IList <IReference> > externalReferences) { lock (Lock) { base.CreateAddressSpace(externalReferences); // Note: might be helpful for debugging //// var env = new AdminShell.PackageEnv("Festo-USB-stick-sample-admin-shell.aasx"); if (true) { var builder = new AasEntityBuilder(this, thePackageEnv, null, this.theServerOptions); // Overall root node is "Objects" // Note: it would be better to already have the "Objects" NodeState, but not // clear how to find .. var fakeObjects = new BaseObjectState(null) { NodeId = new NodeId(85, 0) }; var fakeServer = new BaseObjectState(null) { NodeId = new NodeId(2253, 0) }; // remark: set parent to null, to disable for no HasComponent if (!theServerOptions.LinkRootAsComponent) { fakeObjects = null; fakeServer = null; } // Root of whole structure is special, needs to link to external reference builder.RootAAS = builder.CreateAddFolder(AasUaBaseEntity.CreateMode.Instance, fakeObjects, "AASROOT", doNotAddToParent: true); if (!theServerOptions.LinkRootAsComponent) { builder.RootAAS.AddReference(ReferenceTypeIds.Organizes, isInverse: true, fakeObjects?.NodeId); } // Note: this is TOTALLY WEIRD, but it establishes an inverse reference .. somehow this.AddExternalReferencePublic(new NodeId(85, 0), ReferenceTypeIds.Organizes, false, builder.RootAAS.NodeId, externalReferences); this.AddExternalReferencePublic(builder.RootAAS.NodeId, ReferenceTypeIds.Organizes, true, new NodeId(85, 0), externalReferences); // Folders for DataSpecs // DO NOT USE THIS FEATURE -> Data Spec are "under" the CDs //// builder.RootDataSpecifications = builder.CreateAddFolder( //// builder.RootAAS, "DataSpecifications"); //// builder.RootDataSpecifications = builder.CreateAddObject( //// builder.RootAAS, "DataSpecifications"); #if _not_used #pragma warning disable 162 { // Folders for Concept Descriptions // ReSharper disable once HeuristicUnreachableCode builder.RootConceptDescriptions = builder.CreateAddFolder( AasUaBaseEntity.CreateMode.Instance, builder.RootAAS, "ConceptDescriptions"); // create missing dictionary entries builder.RootMissingDictionaryEntries = builder.CreateAddFolder( AasUaBaseEntity.CreateMode.Instance, builder.RootAAS, "DictionaryEntries"); } #pragma warning restore 162 #else { // create folder(s) under "Objects" var topOfDict = new BaseObjectState(null) { NodeId = new NodeId(17594, 0) }; // it seems, that CeateDictionariesFolder always have to be true! // adding references to a node outside the own node space seems not to work if (theServerOptions.CeateDictionariesFolder) { topOfDict = builder.CreateAddObject( fakeServer, AasOpcUaServer.AasUaBaseEntity.CreateMode.Instance, "Dictionaries", referenceTypeFromParentId: null, typeDefinitionId: builder.AasTypes.DictionaryFolderType.GetTypeNodeId()); } topOfDict.AddReference(ReferenceTypeIds.Organizes, isInverse: true, fakeServer?.NodeId); // Note: this is TOTALLY WEIRD, but it establishes an inverse reference .. somehow // 2253 = Server.Dictionaries ? this.AddExternalReferencePublic(new NodeId(2253, 0), ReferenceTypeIds.HasComponent, false, topOfDict.NodeId, externalReferences); this.AddExternalReferencePublic(topOfDict.NodeId, ReferenceTypeIds.HasComponent, true, new NodeId(2253, 0), externalReferences); // now, create a dictionary under .. // Folders for Concept Descriptions builder.RootConceptDescriptions = builder.CreateAddObject(topOfDict, AasOpcUaServer.AasUaBaseEntity.CreateMode.Instance, "ConceptDescriptions", referenceTypeFromParentId: ReferenceTypeIds.HasComponent, typeDefinitionId: builder.AasTypes.DictionaryFolderType.GetTypeNodeId()); // create missing dictionary entries builder.RootMissingDictionaryEntries = builder.CreateAddObject(topOfDict, AasOpcUaServer.AasUaBaseEntity.CreateMode.Instance, "DictionaryEntries", referenceTypeFromParentId: ReferenceTypeIds.HasComponent, typeDefinitionId: builder.AasTypes.DictionaryFolderType.GetTypeNodeId()); } // start process builder.CreateAddInstanceObjects(thePackageEnv.AasEnv); #endif // Try: ensure the reverse refernces exist. //// AddReverseReferences(externalReferences); if (theServerOptions != null && theServerOptions.SpecialJob == AasxUaServerOptions.JobType.ExportNodesetXml) { try { // empty list var nodesToExport = new NodeStateCollection(); // apply filter criteria foreach (var y in this.PredefinedNodes) { var node = y.Value; if (theServerOptions.ExportFilterNamespaceIndex != null && !theServerOptions.ExportFilterNamespaceIndex.Contains( node.NodeId.NamespaceIndex)) { continue; } nodesToExport.Add(node); } // export Utils.Trace(Utils.TraceMasks.Operation, "Writing export file: " + theServerOptions.ExportFilename); var stream = new StreamWriter(theServerOptions.ExportFilename); //// nodesToExport.SaveAsNodeSet2(this.SystemContext, stream.BaseStream, null, //// theServerOptions != null && theServerOptions.FilterForSingleNodeIds); //// nodesToExport.SaveAsNodeSet2(this.SystemContext, stream.BaseStream); SaveNodestateCollectionAsNodeSet2(this.SystemContext, nodesToExport, stream.BaseStream, filterSingleNodeIds: theServerOptions != null && theServerOptions.FilterForSingleNodeIds, addRootItem: theServerOptions != null && theServerOptions.AddRootItem, builder.RootAAS); try { stream.Close(); } catch (Exception ex) { AdminShellNS.LogInternally.That.SilentlyIgnoredError(ex); } Utils.Trace(Utils.TraceMasks.Operation, "Export file *** completely written! ***"); // stop afterwards if (theServerOptions.FinalizeAction != null) { Utils.Trace(Utils.TraceMasks.Operation, "Requesting to shut down application.."); theServerOptions.FinalizeAction(); } } catch (Exception ex) { Utils.Trace(ex, "When exporting to {0}", "" + theServerOptions.ExportFilename); } // shutdown .. } } Debug.WriteLine("Done creating custom address space!"); Utils.Trace(Utils.TraceMasks.Operation, "Done creating custom address space!"); } }