@@ -2,6 +2,7 @@ package nodeutil
22
33import (
44 "context"
5+ "errors"
56 "fmt"
67 "reflect"
78 "sort"
@@ -151,6 +152,10 @@ type Node struct {
151152 // an rpc input.
152153 OnNewObject func (t reflect.Type , m meta.Definition , insideList bool ) (reflect.Value , error )
153154
155+ // OnNewNode is called when a new node needs to be created whether it is a child node of
156+ // an rpc i/o or notification event.
157+ OnNewNode func (n * Node , m meta.Meta , obj any ) (node.Node , error )
158+
154159 OnContext func (n * Node , s * node.Selection ) context.Context
155160
156161 c reflectContainer // internal handler based on object type to handle containers and leafs
@@ -291,7 +296,7 @@ func (n *Node) DoAction(r node.ActionRequest) (node.Node, error) {
291296 if err != nil {
292297 return nil , err
293298 }
294- return a .do (n , r .Input )
299+ return a .do (n , r .Meta , r . Input )
295300}
296301
297302func (n * Node ) Notify (r node.NotifyRequest ) (node.NotifyCloser , error ) {
@@ -343,6 +348,18 @@ func (ref *Node) exists(m meta.Definition) bool {
343348 if found != nil && cerr == nil {
344349 return true
345350 }
351+ } else if meta .IsChoice (m ) {
352+ cs , cerr := ref .Choose (nil , m .(* meta.Choice ))
353+ if cs != nil && cerr == nil {
354+ // getting a case def might be the default case and not evidence
355+ // data actually exists so we need to recurse into the case defs
356+ for _ , ddef := range cs .DataDefinitions () {
357+ if ref .exists (ddef ) {
358+ return true
359+ }
360+ }
361+ return true
362+ }
346363 } else {
347364 r := node.FieldRequest {Meta : m .(meta.Leafable )}
348365 var hnd node.ValueHandle
@@ -466,10 +483,10 @@ func (ref *Node) DoNewChild(r node.ChildRequest) (node.Node, error) {
466483 return nil , err
467484 }
468485 if meta .IsList (r .Meta ) && r .Selection .Path .Meta != r .Meta {
469- return ref .NewList (obj .Interface (), ref .onListUpdate (r .Meta .(* meta.List )))
486+ return ref .NewList (r . Meta , obj .Interface (), ref .onListUpdate (r .Meta .(* meta.List )))
470487 }
471488
472- return ref .New (obj .Interface ()), nil
489+ return ref .New (r . Meta , obj .Interface ())
473490}
474491
475492func (ref * Node ) onListUpdate (m * meta.List ) NodeListUpdate {
@@ -508,30 +525,42 @@ func (ref *Node) DoGetChild(r node.ChildRequest) (node.Node, error) {
508525 return nil , nil
509526 }
510527 if meta .IsList (r .Meta ) && r .Selection .Path .Meta != r .Meta {
511- return ref .NewList (obj .Interface (), ref .onListUpdate (r .Meta .(* meta.List )))
528+ return ref .NewList (r . Meta , obj .Interface (), ref .onListUpdate (r .Meta .(* meta.List )))
512529 }
513- return ref .New (obj .Interface ()), nil
530+ return ref .New (r . Meta , obj .Interface ())
514531}
515532
516- func (ref * Node ) NewList (obj any , u NodeListUpdate ) (* Node , error ) {
517- copy := ref .New (obj )
518- var err error
519- copy .l , err = ref .newListHandler (reflect .ValueOf (obj ), u )
533+ func (ref * Node ) NewList (m meta.Meta , obj any , u NodeListUpdate ) (node.Node , error ) {
534+ n , err := ref .New (m , obj )
520535 if err != nil {
521536 return nil , err
522537 }
523- return copy , nil
538+ if copy , isCopy := n .(* Node ); isCopy {
539+ var err error
540+ copy .l , err = ref .newListHandler (reflect .ValueOf (obj ), u )
541+ if err != nil {
542+ return nil , err
543+ }
544+ }
545+ return n , nil
546+ }
547+
548+ func (ref * Node ) New (m meta.Meta , obj any ) (node.Node , error ) {
549+ if ref .OnNewNode != nil {
550+ return ref .OnNewNode (ref , m , obj )
551+ }
552+ return ref .DoNewNode (m , obj )
524553}
525554
526- func (ref * Node ) New ( obj any ) * Node {
555+ func (ref * Node ) DoNewNode ( m meta. Meta , obj any ) ( * Node , error ) {
527556 if _ , isVal := obj .(reflect.Value ); isVal {
528- panic ("passing in reflect.Value and not true obj" )
557+ return nil , errors . New ("passing in reflect.Value and not true obj" )
529558 }
530559 copy := * ref
531560 copy .Object = obj
532561 copy .l = nil
533562 copy .c = nil
534- return & copy
563+ return & copy , nil
535564}
536565
537566type reflectContainer interface {
@@ -587,7 +616,7 @@ func (ref *Node) DoGetByKey(r node.ListRequest) (node.Node, error) {
587616 if err != nil || ! item .IsValid () || item .IsNil () {
588617 return nil , err
589618 }
590- return ref .New (item .Interface ()), nil
619+ return ref .New (r . Meta , item .Interface ())
591620}
592621
593622func (ref * Node ) DoGetByRow (r node.ListRequest ) (node.Node , []val.Value , error ) {
@@ -605,7 +634,8 @@ func (ref *Node) DoGetByRow(r node.ListRequest) (node.Node, []val.Value, error)
605634 }
606635 }
607636 }
608- return ref .New (item .Interface ()), key , nil
637+ n , err := ref .New (r .Meta , item .Interface ())
638+ return n , key , err
609639
610640}
611641
@@ -618,7 +648,7 @@ func (ref *Node) DoNewListItem(r node.ListRequest) (node.Node, error) {
618648 if err != nil || ! item .IsValid () || item .IsNil () {
619649 return nil , err
620650 }
621- return ref .New (item .Interface ()), nil
651+ return ref .New (r . Meta , item .Interface ())
622652}
623653
624654func (ref * Node ) getValue (v val.Value ) any {
0 commit comments