@@ -197,41 +197,104 @@ protected override async ValueTask<NodeState> AddBehaviourToPredefinedNodeAsync(
197197 {
198198 case ObjectTypes . ServerConfigurationType :
199199 {
200- var activeNode = ( ServerConfigurationState ) passiveNode ;
201-
200+ var activeNode = new ServerConfigurationState ( passiveNode . Parent ) ;
201+
202+ // Optional ServerConfigurationType methods this
203+ // SDK wires in CreateServerConfiguration but that
204+ // are no longer emitted by the singleton factory
205+ // (Optional per Part 12). Use the idempotent
206+ // generated Add{Method} helpers so the typed
207+ // slot is initialised with the type-level
208+ // factory (BrowseName, InputArguments, etc.)
209+ // before Create() copies the loaded passive
210+ // node into the active subtree. The new
211+ // Add{Method}(context, nodeId?) chains via the
212+ // owner state for fluent usage.
202213 activeNode
203214 . AddGetCertificates ( context )
204215 . AddCreateSelfSignedCertificate ( context ) ;
205216
217+ activeNode . Create ( context , passiveNode ) ;
218+
206219 m_serverConfigurationNode = activeNode ;
207220
221+ // replace the node in the parent.
222+ if ( passiveNode . Parent != null )
223+ {
224+ passiveNode . Parent . ReplaceChild ( context , activeNode ) ;
225+ }
226+ else
227+ {
228+ NodeState ? serverNode = await Server . NodeManager . FindNodeInAddressSpaceAsync ( ObjectIds . Server , cancellationToken )
229+ . ConfigureAwait ( false ) ;
230+ serverNode ? . ReplaceChild ( context , activeNode ) ;
231+ }
232+ // remove the reference to server node because it is set as parent
233+ activeNode . RemoveReference (
234+ ReferenceTypeIds . HasComponent ,
235+ true ,
236+ ObjectIds . Server ) ;
237+
208238 return activeNode ;
209239 }
210240 case ObjectTypes . CertificateGroupFolderType :
211241 {
212- var activeNode = ( CertificateGroupFolderState ) passiveNode ;
242+ var activeNode = new CertificateGroupFolderState ( passiveNode . Parent ) ;
243+ activeNode . Create ( context , passiveNode ) ;
213244
214- ServerCertificateGroup ? applicationGroup =
215- m_certificateGroups . FirstOrDefault ( m => m . BrowseName == BrowseNames . DefaultApplicationGroup ) ;
245+ // delete unsupported groups
246+ if ( m_certificateGroups . All ( group =>
247+ activeNode . DefaultHttpsGroup == null ||
248+ activeNode . DefaultHttpsGroup . BrowseName != group . BrowseName ) )
249+ {
250+ activeNode . DefaultHttpsGroup = null ;
251+ }
252+ if ( m_certificateGroups . All ( group =>
253+ activeNode . DefaultUserTokenGroup == null ||
254+ activeNode . DefaultUserTokenGroup . BrowseName != group . BrowseName ) )
255+ {
256+ activeNode . DefaultUserTokenGroup = null ;
257+ }
258+ if ( m_certificateGroups . All ( group =>
259+ activeNode . DefaultApplicationGroup == null ||
260+ activeNode . DefaultApplicationGroup . BrowseName != group . BrowseName ) )
261+ {
262+ activeNode . DefaultApplicationGroup = null ;
263+ }
216264
217- applicationGroup ! . Node = activeNode . DefaultApplicationGroup ! ;
265+ // replace the node in the parent.
266+ passiveNode . Parent ? . ReplaceChild ( context , activeNode ) ;
267+ return activeNode ;
268+ }
269+ case ObjectTypes . CertificateGroupType :
270+ {
271+ ServerCertificateGroup ? result = m_certificateGroups
272+ . FirstOrDefault ( group =>
273+ group . NodeId == passiveNode . NodeId ) ;
218274
219- ServerCertificateGroup ? httpsGroup =
220- m_certificateGroups . FirstOrDefault ( m => m . BrowseName == BrowseNames . DefaultHttpsGroup ) ;
221- if ( httpsGroup != null )
275+ if ( result != null )
222276 {
223- activeNode . AddDefaultHttpsGroup ( context ) ;
224- httpsGroup . Node = activeNode . DefaultHttpsGroup ! ;
225- }
277+ var activeNode = new CertificateGroupState ( passiveNode . Parent ) ;
278+ activeNode . Create ( context , passiveNode ) ;
279+
280+ result . NodeId = activeNode . NodeId ;
281+ result . Node = activeNode ;
226282
227- ServerCertificateGroup ? userTokenGroup =
228- m_certificateGroups . FirstOrDefault ( m => m . BrowseName == BrowseNames . DefaultUserTokenGroup ) ;
229- if ( userTokenGroup != null )
283+ // replace the node in the parent.
284+ passiveNode . Parent ? . ReplaceChild ( context , activeNode ) ;
285+ return activeNode ;
286+ }
287+ }
288+ break ;
289+ case ObjectTypes . UserManagementType :
290+ {
291+ if ( passiveNode is UserManagementState )
230292 {
231- activeNode . AddDefaultUserTokenGroup ( context ) ;
232- userTokenGroup . Node = activeNode . DefaultUserTokenGroup ! ;
293+ break ;
233294 }
234-
295+ var activeNode = new UserManagementState ( passiveNode . Parent ) ;
296+ activeNode . Create ( context , passiveNode ) ;
297+ passiveNode . Parent ? . ReplaceChild ( context , activeNode ) ;
235298 return activeNode ;
236299 }
237300 }
@@ -456,10 +519,16 @@ public async ValueTask<NamespaceMetadataState> CreateNamespaceMetadataStateAsync
456519 }
457520
458521 // create the NamespaceMetadata node
459- namespaceMetadataState = SystemContext. CreateInstanceOfNamespaceMetadataType (
460- serverNamespacesNode ,
461- new QualifiedName ( namespaceUri , NamespaceIndex ) ) ;
462- namespaceMetadataState. NodeId = SystemContext . NodeIdFactory . New ( SystemContext , namespaceMetadataState ) ;
522+ namespaceMetadataState = new NamespaceMetadataState( serverNamespacesNode )
523+ {
524+ BrowseName = new QualifiedName( namespaceUri , NamespaceIndex )
525+ } ;
526+ namespaceMetadataState. Create (
527+ SystemContext ,
528+ default ,
529+ namespaceMetadataState . BrowseName ,
530+ default ,
531+ true ) ;
463532 namespaceMetadataState. DisplayName = LocalizedText . From ( namespaceUri ) ;
464533 namespaceMetadataState. SymbolicName = namespaceUri ;
465534 namespaceMetadataState! . NamespaceUri ! . Value = namespaceUri ;
0 commit comments