github.com/ipld/go-ipld-prime@v0.21.0/traversal/selector/builder/builder.go (about)

     1  package builder
     2  
     3  import (
     4  	"github.com/ipld/go-ipld-prime/datamodel"
     5  	"github.com/ipld/go-ipld-prime/fluent"
     6  	"github.com/ipld/go-ipld-prime/traversal/selector"
     7  )
     8  
     9  // SelectorSpec is a specification for a selector that can build
    10  // a selector datamodel.Node or an actual parsed Selector
    11  type SelectorSpec interface {
    12  	Node() datamodel.Node
    13  	Selector() (selector.Selector, error)
    14  }
    15  
    16  // SelectorSpecBuilder is a utility interface to build selector ipld nodes
    17  // quickly.
    18  //
    19  // It serves two purposes:
    20  // 1. Save the user of go-ipld time and mental overhead with an easy
    21  // interface for making selector nodes in much less code without having to remember
    22  // the selector sigils
    23  // 2. Provide a level of protection from selector schema changes, at least in terms
    24  // of naming, if not structure
    25  type SelectorSpecBuilder interface {
    26  	ExploreRecursiveEdge() SelectorSpec
    27  	ExploreRecursive(limit selector.RecursionLimit, sequence SelectorSpec) SelectorSpec
    28  	ExploreUnion(...SelectorSpec) SelectorSpec
    29  	ExploreAll(next SelectorSpec) SelectorSpec
    30  	ExploreIndex(index int64, next SelectorSpec) SelectorSpec
    31  	ExploreRange(start, end int64, next SelectorSpec) SelectorSpec
    32  	ExploreFields(ExploreFieldsSpecBuildingClosure) SelectorSpec
    33  	ExploreInterpretAs(as string, next SelectorSpec) SelectorSpec
    34  	Matcher() SelectorSpec
    35  	MatcherSubset(from, to int64) SelectorSpec
    36  }
    37  
    38  // ExploreFieldsSpecBuildingClosure is a function that provided to SelectorSpecBuilder's
    39  // ExploreFields method that assembles the fields map in the selector using
    40  // an ExploreFieldsSpecBuilder
    41  type ExploreFieldsSpecBuildingClosure func(ExploreFieldsSpecBuilder)
    42  
    43  // ExploreFieldsSpecBuilder is an interface for assemble the map of fields to
    44  // selectors in ExploreFields
    45  type ExploreFieldsSpecBuilder interface {
    46  	Insert(k string, v SelectorSpec)
    47  }
    48  
    49  type selectorSpecBuilder struct {
    50  	np datamodel.NodePrototype
    51  }
    52  
    53  type selectorSpec struct {
    54  	n datamodel.Node
    55  }
    56  
    57  func (ss selectorSpec) Node() datamodel.Node {
    58  	return ss.n
    59  }
    60  
    61  func (ss selectorSpec) Selector() (selector.Selector, error) {
    62  	return selector.ParseSelector(ss.n)
    63  }
    64  
    65  // NewSelectorSpecBuilder creates a SelectorSpecBuilder which will store
    66  // data in the format determined by the given datamodel.NodePrototype.
    67  func NewSelectorSpecBuilder(np datamodel.NodePrototype) SelectorSpecBuilder {
    68  	return &selectorSpecBuilder{np}
    69  }
    70  
    71  func (ssb *selectorSpecBuilder) ExploreRecursiveEdge() SelectorSpec {
    72  	return selectorSpec{
    73  		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
    74  			na.AssembleEntry(selector.SelectorKey_ExploreRecursiveEdge).CreateMap(0, func(na fluent.MapAssembler) {})
    75  		}),
    76  	}
    77  }
    78  
    79  func (ssb *selectorSpecBuilder) ExploreRecursive(limit selector.RecursionLimit, sequence SelectorSpec) SelectorSpec {
    80  	return selectorSpec{
    81  		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
    82  			na.AssembleEntry(selector.SelectorKey_ExploreRecursive).CreateMap(2, func(na fluent.MapAssembler) {
    83  				na.AssembleEntry(selector.SelectorKey_Limit).CreateMap(1, func(na fluent.MapAssembler) {
    84  					switch limit.Mode() {
    85  					case selector.RecursionLimit_Depth:
    86  						na.AssembleEntry(selector.SelectorKey_LimitDepth).AssignInt(limit.Depth())
    87  					case selector.RecursionLimit_None:
    88  						na.AssembleEntry(selector.SelectorKey_LimitNone).CreateMap(0, func(na fluent.MapAssembler) {})
    89  					default:
    90  						panic("Unsupported recursion limit type")
    91  					}
    92  				})
    93  				na.AssembleEntry(selector.SelectorKey_Sequence).AssignNode(sequence.Node())
    94  			})
    95  		}),
    96  	}
    97  }
    98  
    99  func (ssb *selectorSpecBuilder) ExploreAll(next SelectorSpec) SelectorSpec {
   100  	return selectorSpec{
   101  		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
   102  			na.AssembleEntry(selector.SelectorKey_ExploreAll).CreateMap(1, func(na fluent.MapAssembler) {
   103  				na.AssembleEntry(selector.SelectorKey_Next).AssignNode(next.Node())
   104  			})
   105  		}),
   106  	}
   107  }
   108  func (ssb *selectorSpecBuilder) ExploreIndex(index int64, next SelectorSpec) SelectorSpec {
   109  	return selectorSpec{
   110  		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
   111  			na.AssembleEntry(selector.SelectorKey_ExploreIndex).CreateMap(2, func(na fluent.MapAssembler) {
   112  				na.AssembleEntry(selector.SelectorKey_Index).AssignInt(index)
   113  				na.AssembleEntry(selector.SelectorKey_Next).AssignNode(next.Node())
   114  			})
   115  		}),
   116  	}
   117  }
   118  
   119  func (ssb *selectorSpecBuilder) ExploreRange(start, end int64, next SelectorSpec) SelectorSpec {
   120  	return selectorSpec{
   121  		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
   122  			na.AssembleEntry(selector.SelectorKey_ExploreRange).CreateMap(3, func(na fluent.MapAssembler) {
   123  				na.AssembleEntry(selector.SelectorKey_Start).AssignInt(start)
   124  				na.AssembleEntry(selector.SelectorKey_End).AssignInt(end)
   125  				na.AssembleEntry(selector.SelectorKey_Next).AssignNode(next.Node())
   126  			})
   127  		}),
   128  	}
   129  }
   130  
   131  func (ssb *selectorSpecBuilder) ExploreUnion(members ...SelectorSpec) SelectorSpec {
   132  	return selectorSpec{
   133  		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
   134  			na.AssembleEntry(selector.SelectorKey_ExploreUnion).CreateList(int64(len(members)), func(na fluent.ListAssembler) {
   135  				for _, member := range members {
   136  					na.AssembleValue().AssignNode(member.Node())
   137  				}
   138  			})
   139  		}),
   140  	}
   141  }
   142  
   143  func (ssb *selectorSpecBuilder) ExploreFields(specBuilder ExploreFieldsSpecBuildingClosure) SelectorSpec {
   144  	return selectorSpec{
   145  		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
   146  			na.AssembleEntry(selector.SelectorKey_ExploreFields).CreateMap(1, func(na fluent.MapAssembler) {
   147  				na.AssembleEntry(selector.SelectorKey_Fields).CreateMap(-1, func(na fluent.MapAssembler) {
   148  					specBuilder(exploreFieldsSpecBuilder{na})
   149  				})
   150  			})
   151  		}),
   152  	}
   153  }
   154  
   155  func (ssb *selectorSpecBuilder) ExploreInterpretAs(as string, next SelectorSpec) SelectorSpec {
   156  	return selectorSpec{
   157  		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
   158  			na.AssembleEntry(selector.SelectorKey_ExploreInterpretAs).CreateMap(1, func(na fluent.MapAssembler) {
   159  				na.AssembleEntry(selector.SelectorKey_As).AssignString(as)
   160  				na.AssembleEntry(selector.SelectorKey_Next).AssignNode(next.Node())
   161  			})
   162  		}),
   163  	}
   164  }
   165  
   166  func (ssb *selectorSpecBuilder) Matcher() SelectorSpec {
   167  	return selectorSpec{
   168  		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
   169  			na.AssembleEntry(selector.SelectorKey_Matcher).CreateMap(0, func(na fluent.MapAssembler) {})
   170  		}),
   171  	}
   172  }
   173  
   174  func (ssb *selectorSpecBuilder) MatcherSubset(from, to int64) SelectorSpec {
   175  	return selectorSpec{
   176  		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
   177  			na.AssembleEntry(selector.SelectorKey_Matcher).CreateMap(1, func(na fluent.MapAssembler) {
   178  				na.AssembleEntry(selector.SelectorKey_Subset).CreateMap(2, func(na fluent.MapAssembler) {
   179  					na.AssembleEntry(selector.SelectorKey_From).AssignInt(from)
   180  					na.AssembleEntry(selector.SelectorKey_To).AssignInt(to)
   181  				})
   182  			})
   183  		}),
   184  	}
   185  }
   186  
   187  type exploreFieldsSpecBuilder struct {
   188  	na fluent.MapAssembler
   189  }
   190  
   191  func (efsb exploreFieldsSpecBuilder) Insert(field string, s SelectorSpec) {
   192  	efsb.na.AssembleEntry(field).AssignNode(s.Node())
   193  }