Rewrite Gremlin's buildIterator in terms of paths
This commit is contained in:
parent
97247ae40f
commit
f74051a520
5 changed files with 246 additions and 391 deletions
|
|
@ -15,6 +15,8 @@
|
|||
package path
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/cayley/graph"
|
||||
"github.com/google/cayley/graph/iterator"
|
||||
"github.com/google/cayley/quad"
|
||||
|
|
@ -114,25 +116,41 @@ func tagMorphism(tags ...string) morphism {
|
|||
}
|
||||
|
||||
// outMorphism iterates forward one RDF triple or via an entire path.
|
||||
func outMorphism(via ...interface{}) morphism {
|
||||
func outMorphism(tags []string, via ...interface{}) morphism {
|
||||
return morphism{
|
||||
Name: "out",
|
||||
Reversal: func() morphism { return inMorphism(via...) },
|
||||
Reversal: func() morphism { return inMorphism(tags, via...) },
|
||||
Apply: func(qs graph.QuadStore, in graph.Iterator, ctx *context) (graph.Iterator, *context) {
|
||||
path := buildViaPath(qs, via...)
|
||||
return inOutIterator(path, in, false), ctx
|
||||
return inOutIterator(path, in, false, tags), ctx
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// inMorphism iterates backwards one RDF triple or via an entire path.
|
||||
func inMorphism(via ...interface{}) morphism {
|
||||
func inMorphism(tags []string, via ...interface{}) morphism {
|
||||
return morphism{
|
||||
Name: "in",
|
||||
Reversal: func() morphism { return outMorphism(via...) },
|
||||
Reversal: func() morphism { return outMorphism(tags, via...) },
|
||||
Apply: func(qs graph.QuadStore, in graph.Iterator, ctx *context) (graph.Iterator, *context) {
|
||||
path := buildViaPath(qs, via...)
|
||||
return inOutIterator(path, in, true), ctx
|
||||
return inOutIterator(path, in, true, tags), ctx
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func bothMorphism(tags []string, via ...interface{}) morphism {
|
||||
return morphism{
|
||||
Name: "in",
|
||||
Reversal: func() morphism { return bothMorphism(tags, via...) },
|
||||
Apply: func(qs graph.QuadStore, in graph.Iterator, ctx *context) (graph.Iterator, *context) {
|
||||
path := buildViaPath(qs, via...)
|
||||
inSide := inOutIterator(path, in, true, tags)
|
||||
outSide := inOutIterator(path, in.Clone(), false, tags)
|
||||
or := iterator.NewOr()
|
||||
or.AddSubIterator(inSide)
|
||||
or.AddSubIterator(outSide)
|
||||
return or, ctx
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -270,13 +288,16 @@ func buildSave(
|
|||
return join(qs, from, save)
|
||||
}
|
||||
|
||||
func inOutIterator(viaPath *Path, from graph.Iterator, inIterator bool) graph.Iterator {
|
||||
func inOutIterator(viaPath *Path, from graph.Iterator, inIterator bool, tags []string) graph.Iterator {
|
||||
start, goal := quad.Subject, quad.Object
|
||||
if inIterator {
|
||||
start, goal = goal, start
|
||||
}
|
||||
|
||||
viaIter := viaPath.BuildIterator()
|
||||
for _, tag := range tags {
|
||||
viaIter.Tagger().Add(tag)
|
||||
}
|
||||
|
||||
source := iterator.NewLinksTo(viaPath.qs, from, start)
|
||||
trail := iterator.NewLinksTo(viaPath.qs, viaIter, quad.Predicate)
|
||||
|
|
@ -292,12 +313,22 @@ func buildViaPath(qs graph.QuadStore, via ...interface{}) *Path {
|
|||
} else if len(via) == 1 {
|
||||
v := via[0]
|
||||
switch p := v.(type) {
|
||||
case nil:
|
||||
return PathFromIterator(qs, qs.NodesAllIterator())
|
||||
case *Path:
|
||||
if p.qs != qs {
|
||||
newp := &Path{
|
||||
qs: qs,
|
||||
baseContext: p.baseContext,
|
||||
stack: p.stack[:],
|
||||
}
|
||||
return newp
|
||||
}
|
||||
return p
|
||||
case string:
|
||||
return StartPath(qs, p)
|
||||
default:
|
||||
panic("Invalid type passed to buildViaPath.")
|
||||
panic(fmt.Sprint("Invalid type passed to buildViaPath. ", p))
|
||||
}
|
||||
}
|
||||
var strings []string
|
||||
|
|
|
|||
|
|
@ -14,11 +14,7 @@
|
|||
|
||||
package path
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/cayley/graph"
|
||||
)
|
||||
import "github.com/google/cayley/graph"
|
||||
|
||||
type applyMorphism func(graph.QuadStore, graph.Iterator, *context) (graph.Iterator, *context)
|
||||
|
||||
|
|
@ -102,13 +98,13 @@ func (p *Path) Tag(tags ...string) *Path {
|
|||
// current nodes, via the given outbound predicate.
|
||||
//
|
||||
// For example:
|
||||
// // Returns the list of nodes that "A" follows.
|
||||
// // Returns the list of nodes that "B" follows.
|
||||
// //
|
||||
// // Will return []string{"B"} if there is a predicate (edge) from "A"
|
||||
// // to "B" labelled "follows".
|
||||
// // Will return []string{"F"} if there is a predicate (edge) from "B"
|
||||
// // to "F" labelled "follows".
|
||||
// StartPath(qs, "A").Out("follows")
|
||||
func (p *Path) Out(via ...interface{}) *Path {
|
||||
p.stack = append(p.stack, outMorphism(via...))
|
||||
p.stack = append(p.stack, outMorphism(nil, via...))
|
||||
return p
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +118,34 @@ func (p *Path) Out(via ...interface{}) *Path {
|
|||
// // edges from those nodes to "B" labelled "follows".
|
||||
// StartPath(qs, "B").In("follows")
|
||||
func (p *Path) In(via ...interface{}) *Path {
|
||||
p.stack = append(p.stack, inMorphism(via...))
|
||||
p.stack = append(p.stack, inMorphism(nil, via...))
|
||||
return p
|
||||
}
|
||||
|
||||
// InWithTags is exactly like In, except it tags the value of the predicate
|
||||
// traversed with the tags provided.
|
||||
func (p *Path) InWithTags(tags []string, via ...interface{}) *Path {
|
||||
p.stack = append(p.stack, inMorphism(tags, via...))
|
||||
return p
|
||||
}
|
||||
|
||||
// OutWithTags is exactly like In, except it tags the value of the predicate
|
||||
// traversed with the tags provided.
|
||||
func (p *Path) OutWithTags(tags []string, via ...interface{}) *Path {
|
||||
p.stack = append(p.stack, outMorphism(tags, via...))
|
||||
return p
|
||||
}
|
||||
|
||||
// Both updates this path following both inbound and outbound predicates.
|
||||
//
|
||||
// For example:
|
||||
// // Return the list of nodes that follow or are followed by "B".
|
||||
// //
|
||||
// // Will return []string{"A", "C", "D", "F} if there are the appropriate
|
||||
// // edges from those nodes to "B" labelled "follows", in either direction.
|
||||
// StartPath(qs, "B").Both("follows")
|
||||
func (p *Path) Both(via ...interface{}) *Path {
|
||||
p.stack = append(p.stack, bothMorphism(nil, via...))
|
||||
return p
|
||||
}
|
||||
|
||||
|
|
@ -275,12 +298,3 @@ func (p *Path) Morphism() graph.ApplyMorphism {
|
|||
return i
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Path) debugPrint() {
|
||||
var strs []string
|
||||
for _, x := range p.stack {
|
||||
strs = append(strs, x.Name)
|
||||
}
|
||||
fmt.Println("stack:", strs)
|
||||
fmt.Println("ctx:", p.baseContext)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue