@@ -17,6 +17,7 @@ import (
1717 "context"
1818 "fmt"
1919 "io"
20+ "iter"
2021 "path"
2122 "sort"
2223 "strconv"
@@ -367,8 +368,9 @@ func (m *pageMap) getPagesInSection(q pageMapQueryPagesInSection) page.Pages {
367368 }
368369
369370 w := & doctree.NodeShiftTreeWalker [contentNodeI ]{
370- Tree : m .treePages ,
371- Prefix : prefix ,
371+ Tree : m .treePages ,
372+ Prefix : prefix ,
373+ DelegeeFallback : true ,
372374 }
373375
374376 w .Handle = func (key string , n contentNodeI , match doctree.DimensionFlag ) (bool , error ) {
@@ -649,6 +651,7 @@ type contentNodeI interface {
649651 identity.ForEeachIdentityProvider
650652 Path () string
651653 isContentNodeBranch () bool
654+ matchDirectOrInDelegees (doctree.Dimensions ) (contentNodeI , doctree.Dimensions )
652655 buildStateReseter
653656 resource.StaleMarker
654657}
@@ -672,6 +675,10 @@ func (n contentNodeIs) isContentNodeBranch() bool {
672675 return n .one ().isContentNodeBranch ()
673676}
674677
678+ func (p contentNodeIs ) matchDirectOrInDelegees (doctree.Dimensions ) (contentNodeI , doctree.Dimensions ) {
679+ panic ("not implemented" )
680+ }
681+
675682func (n contentNodeIs ) GetIdentity () identity.Identity {
676683 return n .one ().GetIdentity ()
677684}
@@ -705,13 +712,13 @@ type contentNodeShifter struct {
705712 numLanguages int
706713}
707714
708- func (s * contentNodeShifter ) Delete (n contentNodeI , dimension doctree.Dimensions ) (contentNodeI , bool , bool ) {
715+ func (s * contentNodeShifter ) Delete (n contentNodeI , dims doctree.Dimensions ) (contentNodeI , bool , bool ) {
709716 switch v := n .(type ) {
710717 case contentNodeIs :
711- deleted := v [dimension ]
718+ deleted := v [dims ]
712719 resource .MarkStale (deleted )
713720 wasDeleted := deleted != nil
714- v [dimension ] = nil
721+ v [dims ] = nil
715722 isEmpty := true
716723 for _ , vv := range v {
717724 if vv != nil {
@@ -721,10 +728,10 @@ func (s *contentNodeShifter) Delete(n contentNodeI, dimension doctree.Dimensions
721728 }
722729 return deleted , wasDeleted , isEmpty
723730 case resourceSources :
724- deleted := v [dimension ]
731+ deleted := v [dims ]
725732 resource .MarkStale (deleted )
726733 wasDeleted := deleted != nil
727- v [dimension ] = nil
734+ v [dims ] = nil
728735 isEmpty := true
729736 for _ , vv := range v {
730737 if vv != nil {
@@ -734,13 +741,13 @@ func (s *contentNodeShifter) Delete(n contentNodeI, dimension doctree.Dimensions
734741 }
735742 return deleted , wasDeleted , isEmpty
736743 case * resourceSource :
737- if dimension != v .Dim () {
744+ if dims != v .Dims () {
738745 return nil , false , false
739746 }
740747 resource .MarkStale (v )
741748 return v , true , true
742749 case * pageState :
743- if dimension != v .s .dims {
750+ if dims != v .s .dims {
744751 return nil , false , false
745752 }
746753 resource .MarkStale (v )
@@ -750,8 +757,25 @@ func (s *contentNodeShifter) Delete(n contentNodeI, dimension doctree.Dimensions
750757 }
751758}
752759
753- func (s * contentNodeShifter ) Shift (n contentNodeI , dims doctree.Dimensions , exact bool ) (contentNodeI , bool , doctree.DimensionFlag ) {
754- // How accurate is the match.
760+ func (s * contentNodeShifter ) findDelegee (q doctree.Dimensions , candidates iter.Seq [contentNodeI ]) contentNodeI {
761+ var (
762+ best contentNodeI = nil
763+ bestDims doctree.Dimensions
764+ )
765+ for n := range candidates {
766+ if nn , dims := n .matchDirectOrInDelegees (q ); nn != nil {
767+ if best == nil || dims .Compare (bestDims ) < 0 {
768+ best = nn
769+ bestDims = dims
770+ }
771+ }
772+ }
773+ return best
774+ }
775+
776+ func (s * contentNodeShifter ) Shift (n contentNodeI , dims doctree.Dimensions , exact , delegeeFallback bool ) (contentNodeI , bool , doctree.DimensionFlag ) {
777+ // dims: language, version and role
778+ // How accurate is the match. TODO1 revise this.
755779 accuracy := doctree .DimensionLanguage
756780 switch v := n .(type ) {
757781 case contentNodeIs :
@@ -762,6 +786,19 @@ func (s *contentNodeShifter) Shift(n contentNodeI, dims doctree.Dimensions, exac
762786 if vv != nil {
763787 return vv , true , accuracy
764788 }
789+ if ! delegeeFallback {
790+ return nil , false , 0
791+ }
792+ iter := func (yield func (n contentNodeI ) bool ) {
793+ for _ , nn := range v {
794+ if ! yield (nn ) {
795+ return
796+ }
797+ }
798+ }
799+ if vv = s .findDelegee (dims , iter ); vv != nil {
800+ return vv , true , accuracy
801+ }
765802 return nil , false , 0
766803 case resourceSources :
767804 vv := v [dims ]
@@ -781,7 +818,7 @@ func (s *contentNodeShifter) Shift(n contentNodeI, dims doctree.Dimensions, exac
781818 }
782819 }
783820 case * resourceSource :
784- if v .Dim () == dims {
821+ if v .Dims () == dims {
785822 return v , true , doctree .DimensionLanguage // TODO1
786823 }
787824 if ! v .isPage () && ! exact {
@@ -843,11 +880,11 @@ func (s *contentNodeShifter) InsertInto(old, new contentNodeI, dimension doctree
843880 if ! ok {
844881 panic (fmt .Sprintf ("unknown type %T" , new ))
845882 }
846- if vv .Dim () == newp .Dim () && newp .Dim () == dimension {
883+ if vv .Dims () == newp .Dims () && newp .Dims () == dimension {
847884 return new , vv , true
848885 }
849886 rs := make (resourceSources , s .numLanguages )
850- rs [vv .Dim ()] = vv
887+ rs [vv .Dims ()] = vv
851888 rs [dimension ] = newp
852889 return rs , vv , false
853890
@@ -889,26 +926,26 @@ func (s *contentNodeShifter) Insert(old, new contentNodeI) (contentNodeI, conten
889926 if ! ok {
890927 panic (fmt .Sprintf ("unknown type %T" , new ))
891928 }
892- if vv .Dim () == newp .Dim () {
929+ if vv .Dims () == newp .Dims () {
893930 if vv != newp {
894931 resource .MarkStale (vv )
895932 }
896933 return new , vv , true
897934 }
898935 rs := make (resourceSources , s .numLanguages )
899- rs [newp .Dim ()] = newp
900- rs [vv .Dim ()] = vv
936+ rs [newp .Dims ()] = newp
937+ rs [vv .Dims ()] = vv
901938 return rs , vv , false
902939 case resourceSources :
903940 newp , ok := new .(* resourceSource )
904941 if ! ok {
905942 panic (fmt .Sprintf ("unknown type %T" , new ))
906943 }
907- oldp := vv [newp .Dim ()]
944+ oldp := vv [newp .Dims ()]
908945 if oldp != newp {
909946 resource .MarkStale (oldp )
910947 }
911- vv [newp .Dim ()] = newp
948+ vv [newp .Dims ()] = newp
912949 return vv , oldp , oldp != nil
913950 default :
914951 panic (fmt .Sprintf ("unknown type %T" , old ))
@@ -1050,7 +1087,7 @@ func (m *pageMap) debugPrint(prefix string, maxLevel int, w io.Writer) {
10501087
10511088 resourceWalker .Handle = func (ss string , n contentNodeI , match doctree.DimensionFlag ) (bool , error ) {
10521089 if isBranch {
1053- ownerKey , _ := pageWalker .Tree .LongestPrefix (ss , true , nil )
1090+ ownerKey , _ := pageWalker .Tree .LongestPrefix (ss , true , false , nil )
10541091 if ownerKey != keyPage {
10551092 // Stop walking downwards, someone else owns this resource.
10561093 pageWalker .SkipPrefix (ownerKey + "/" )
@@ -1500,7 +1537,7 @@ func (sa *sitePagesAssembler) applyAggregates() error {
15001537
15011538 rw .Handle = func (resourceKey string , n contentNodeI , match doctree.DimensionFlag ) (bool , error ) {
15021539 if isBranch {
1503- ownerKey , _ := pw .Tree .LongestPrefix (resourceKey , true , nil )
1540+ ownerKey , _ := pw .Tree .LongestPrefix (resourceKey , true , false , nil )
15041541 if ownerKey != keyPage {
15051542 // Stop walking downwards, someone else owns this resource.
15061543 rw .SkipPrefix (ownerKey + "/" )
0 commit comments