builder.go 5.79 KB
Newer Older
1
package builder
2 3

import (
tavit ohanian's avatar
tavit ohanian committed
4
	ld "gitlab.dms3.io/ld/go-ld-prime"
tavit ohanian's avatar
tavit ohanian committed
5 6
	"gitlab.dms3.io/ld/go-ld-prime/fluent"
	selector "gitlab.dms3.io/ld/go-ld-prime/traversal/selector"
7 8 9
)

// SelectorSpec is a specification for a selector that can build
tavit ohanian's avatar
tavit ohanian committed
10
// a selector ld.Node or an actual parsed Selector
11
type SelectorSpec interface {
tavit ohanian's avatar
tavit ohanian committed
12
	Node() ld.Node
13
	Selector() (selector.Selector, error)
14 15
}

tavit ohanian's avatar
tavit ohanian committed
16
// SelectorSpecBuilder is a utility interface to build selector ld nodes
17 18 19
// quickly.
//
// It serves two purposes:
tavit ohanian's avatar
tavit ohanian committed
20
// 1. Save the user of go-ld-prime time and mental overhead with an easy
21 22 23 24 25 26
// interface for making selector nodes in much less code without having to remember
// the selector sigils
// 2. Provide a level of protection from selector schema changes, at least in terms
// of naming, if not structure
type SelectorSpecBuilder interface {
	ExploreRecursiveEdge() SelectorSpec
27
	ExploreRecursive(limit selector.RecursionLimit, sequence SelectorSpec) SelectorSpec
28 29
	ExploreUnion(...SelectorSpec) SelectorSpec
	ExploreAll(next SelectorSpec) SelectorSpec
30 31
	ExploreIndex(index int64, next SelectorSpec) SelectorSpec
	ExploreRange(start, end int64, next SelectorSpec) SelectorSpec
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
	ExploreFields(ExploreFieldsSpecBuildingClosure) SelectorSpec
	Matcher() SelectorSpec
}

// ExploreFieldsSpecBuildingClosure is a function that provided to SelectorSpecBuilder's
// ExploreFields method that assembles the fields map in the selector using
// an ExploreFieldsSpecBuilder
type ExploreFieldsSpecBuildingClosure func(ExploreFieldsSpecBuilder)

// ExploreFieldsSpecBuilder is an interface for assemble the map of fields to
// selectors in ExploreFields
type ExploreFieldsSpecBuilder interface {
	Insert(k string, v SelectorSpec)
}

type selectorSpecBuilder struct {
tavit ohanian's avatar
tavit ohanian committed
48
	np ld.NodePrototype
49 50 51
}

type selectorSpec struct {
tavit ohanian's avatar
tavit ohanian committed
52
	n ld.Node
53 54
}

tavit ohanian's avatar
tavit ohanian committed
55
func (ss selectorSpec) Node() ld.Node {
56 57 58
	return ss.n
}

59 60
func (ss selectorSpec) Selector() (selector.Selector, error) {
	return selector.ParseSelector(ss.n)
61 62
}

63
// NewSelectorSpecBuilder creates a SelectorSpecBuilder which will store
tavit ohanian's avatar
tavit ohanian committed
64 65
// data in the format determined by the given ld.NodePrototype.
func NewSelectorSpecBuilder(np ld.NodePrototype) SelectorSpecBuilder {
66
	return &selectorSpecBuilder{np}
67 68 69 70
}

func (ssb *selectorSpecBuilder) ExploreRecursiveEdge() SelectorSpec {
	return selectorSpec{
71
		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
72
			na.AssembleEntry(selector.SelectorKey_ExploreRecursiveEdge).CreateMap(0, func(na fluent.MapAssembler) {})
73 74 75 76
		}),
	}
}

77
func (ssb *selectorSpecBuilder) ExploreRecursive(limit selector.RecursionLimit, sequence SelectorSpec) SelectorSpec {
78
	return selectorSpec{
79
		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
80 81
			na.AssembleEntry(selector.SelectorKey_ExploreRecursive).CreateMap(2, func(na fluent.MapAssembler) {
				na.AssembleEntry(selector.SelectorKey_Limit).CreateMap(1, func(na fluent.MapAssembler) {
82 83
					switch limit.Mode() {
					case selector.RecursionLimit_Depth:
84
						na.AssembleEntry(selector.SelectorKey_LimitDepth).AssignInt(limit.Depth())
85
					case selector.RecursionLimit_None:
86
						na.AssembleEntry(selector.SelectorKey_LimitNone).CreateMap(0, func(na fluent.MapAssembler) {})
87 88
					default:
						panic("Unsupported recursion limit type")
89
					}
90
				})
91
				na.AssembleEntry(selector.SelectorKey_Sequence).AssignNode(sequence.Node())
92
			})
93 94 95 96 97 98
		}),
	}
}

func (ssb *selectorSpecBuilder) ExploreAll(next SelectorSpec) SelectorSpec {
	return selectorSpec{
99
		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
100
			na.AssembleEntry(selector.SelectorKey_ExploreAll).CreateMap(1, func(na fluent.MapAssembler) {
101
				na.AssembleEntry(selector.SelectorKey_Next).AssignNode(next.Node())
102
			})
103 104 105
		}),
	}
}
106
func (ssb *selectorSpecBuilder) ExploreIndex(index int64, next SelectorSpec) SelectorSpec {
107
	return selectorSpec{
108
		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
109 110
			na.AssembleEntry(selector.SelectorKey_ExploreIndex).CreateMap(2, func(na fluent.MapAssembler) {
				na.AssembleEntry(selector.SelectorKey_Index).AssignInt(index)
111
				na.AssembleEntry(selector.SelectorKey_Next).AssignNode(next.Node())
112
			})
113 114 115 116
		}),
	}
}

117
func (ssb *selectorSpecBuilder) ExploreRange(start, end int64, next SelectorSpec) SelectorSpec {
118
	return selectorSpec{
119
		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
120 121 122
			na.AssembleEntry(selector.SelectorKey_ExploreRange).CreateMap(3, func(na fluent.MapAssembler) {
				na.AssembleEntry(selector.SelectorKey_Start).AssignInt(start)
				na.AssembleEntry(selector.SelectorKey_End).AssignInt(end)
123
				na.AssembleEntry(selector.SelectorKey_Next).AssignNode(next.Node())
124
			})
125 126 127 128 129 130
		}),
	}
}

func (ssb *selectorSpecBuilder) ExploreUnion(members ...SelectorSpec) SelectorSpec {
	return selectorSpec{
131
		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
132
			na.AssembleEntry(selector.SelectorKey_ExploreUnion).CreateList(int64(len(members)), func(na fluent.ListAssembler) {
133
				for _, member := range members {
134
					na.AssembleValue().AssignNode(member.Node())
135
				}
136
			})
137 138 139 140 141 142
		}),
	}
}

func (ssb *selectorSpecBuilder) ExploreFields(specBuilder ExploreFieldsSpecBuildingClosure) SelectorSpec {
	return selectorSpec{
143
		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
144 145
			na.AssembleEntry(selector.SelectorKey_ExploreFields).CreateMap(1, func(na fluent.MapAssembler) {
				na.AssembleEntry(selector.SelectorKey_Fields).CreateMap(-1, func(na fluent.MapAssembler) {
146 147 148
					specBuilder(exploreFieldsSpecBuilder{na})
				})
			})
149 150 151 152 153 154
		}),
	}
}

func (ssb *selectorSpecBuilder) Matcher() SelectorSpec {
	return selectorSpec{
155
		fluent.MustBuildMap(ssb.np, 1, func(na fluent.MapAssembler) {
156
			na.AssembleEntry(selector.SelectorKey_Matcher).CreateMap(0, func(na fluent.MapAssembler) {})
157 158 159 160 161
		}),
	}
}

type exploreFieldsSpecBuilder struct {
162
	na fluent.MapAssembler
163 164 165
}

func (efsb exploreFieldsSpecBuilder) Insert(field string, s SelectorSpec) {
166
	efsb.na.AssembleEntry(field).AssignNode(s.Node())
167
}