exploreFields.go 2.41 KB
Newer Older
1 2 3 4 5
package selector

import (
	"fmt"

tavit ohanian's avatar
tavit ohanian committed
6
	ld "gitlab.dms3.io/ld/go-ld-prime"
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
)

// ExploreFields traverses named fields in a map (or equivalently, struct, if
// traversing on typed/schema nodes) and applies a next selector to the
// reached nodes.
//
// Note that a concept of "ExplorePath" (e.g. "foo/bar/baz") can be represented
// as a set of three nexted ExploreFields selectors, each specifying one field.
// (For this reason, we don't have a special "ExplorePath" feature; use this.)
//
// ExploreFields also works for selecting specific elements out of a list;
// if a "field" is a base-10 int, it will be coerced and do the right thing.
// ExploreIndex or ExploreRange is more appropriate, however, and should be preferred.
type ExploreFields struct {
	selections map[string]Selector
tavit ohanian's avatar
tavit ohanian committed
22
	interests  []ld.PathSegment // keys of above; already boxed as that's the only way we consume them
23 24 25
}

// Interests for ExploreFields are the fields listed in the selector node
tavit ohanian's avatar
tavit ohanian committed
26
func (s ExploreFields) Interests() []ld.PathSegment {
27 28 29 30 31
	return s.interests
}

// Explore returns the selector for the given path if it is a field in
// the selector node or nil if not
tavit ohanian's avatar
tavit ohanian committed
32
func (s ExploreFields) Explore(n ld.Node, p ld.PathSegment) Selector {
33 34 35 36
	return s.selections[p.String()]
}

// Decide always returns false because this is not a matcher
tavit ohanian's avatar
tavit ohanian committed
37
func (s ExploreFields) Decide(n ld.Node) bool {
38 39 40 41 42
	return false
}

// ParseExploreFields assembles a Selector
// from a ExploreFields selector node
tavit ohanian's avatar
tavit ohanian committed
43 44
func (pc ParseContext) ParseExploreFields(n ld.Node) (Selector, error) {
	if n.Kind() != ld.Kind_Map {
45 46
		return nil, fmt.Errorf("selector spec parse rejected: selector body must be a map")
	}
47
	fields, err := n.LookupByString(SelectorKey_Fields)
48 49 50
	if err != nil {
		return nil, fmt.Errorf("selector spec parse rejected: fields in ExploreFields selector must be present")
	}
tavit ohanian's avatar
tavit ohanian committed
51
	if fields.Kind() != ld.Kind_Map {
52 53 54 55
		return nil, fmt.Errorf("selector spec parse rejected: fields in ExploreFields selector must be a map")
	}
	x := ExploreFields{
		make(map[string]Selector, fields.Length()),
tavit ohanian's avatar
tavit ohanian committed
56
		make([]ld.PathSegment, 0, fields.Length()),
57 58 59 60 61 62 63 64
	}
	for itr := fields.MapIterator(); !itr.Done(); {
		kn, v, err := itr.Next()
		if err != nil {
			return nil, fmt.Errorf("error during selector spec parse: %s", err)
		}

		kstr, _ := kn.AsString()
tavit ohanian's avatar
tavit ohanian committed
65
		x.interests = append(x.interests, ld.PathSegmentOfString(kstr))
66
		x.selections[kstr], err = pc.ParseSelector(v)
67 68 69 70 71 72
		if err != nil {
			return nil, err
		}
	}
	return x, nil
}