graph/path: Add LabelContext to the path query language.

This commit is contained in:
Barak Michener 2015-10-30 16:50:33 -04:00
parent 7a5e206539
commit 36d0f48d15
4 changed files with 73 additions and 14 deletions

View file

@ -25,11 +25,14 @@ import (
// join puts two iterators together by intersecting their result sets with an AND
// Since we're using an and iterator, it's a good idea to put the smallest result
// set first so that Next() produces fewer values to check Contains().
func join(qs graph.QuadStore, itL, itR graph.Iterator) graph.Iterator {
func join(qs graph.QuadStore, its ...graph.Iterator) graph.Iterator {
and := iterator.NewAnd(qs)
and.AddSubIterator(itL)
and.AddSubIterator(itR)
for _, it := range its {
if it == nil {
continue
}
and.AddSubIterator(it)
}
return and
}
@ -122,8 +125,9 @@ func outMorphism(tags []string, via ...interface{}) morphism {
Reversal: func(ctx *context) (morphism, *context) { return inMorphism(tags, via...), ctx },
Apply: func(qs graph.QuadStore, in graph.Iterator, ctx *context) (graph.Iterator, *context) {
path := buildViaPath(qs, via...)
return inOutIterator(path, in, false, tags), ctx
return inOutIterator(path, in, false, tags, ctx), ctx
},
tags: tags,
}
}
@ -134,8 +138,9 @@ func inMorphism(tags []string, via ...interface{}) morphism {
Reversal: func(ctx *context) (morphism, *context) { return outMorphism(tags, via...), ctx },
Apply: func(qs graph.QuadStore, in graph.Iterator, ctx *context) (graph.Iterator, *context) {
path := buildViaPath(qs, via...)
return inOutIterator(path, in, true, tags), ctx
return inOutIterator(path, in, true, tags, ctx), ctx
},
tags: tags,
}
}
@ -145,13 +150,36 @@ func bothMorphism(tags []string, via ...interface{}) morphism {
Reversal: func(ctx *context) (morphism, *context) { return bothMorphism(tags, via...), ctx },
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)
inSide := inOutIterator(path, in, true, tags, ctx)
outSide := inOutIterator(path, in.Clone(), false, tags, ctx)
or := iterator.NewOr()
or.AddSubIterator(inSide)
or.AddSubIterator(outSide)
return or, ctx
},
tags: tags,
}
}
func labelContextMorphism(via ...interface{}) morphism {
var path *Path
if len(via) == 0 {
path = nil
} else {
path = buildViaPath(nil, via...)
}
return morphism{
Name: "label_context",
Reversal: func(ctx *context) (morphism, *context) {
out := ctx.copy()
ctx.labelSet = path
return labelContextMorphism(via...), &out
},
Apply: func(qs graph.QuadStore, in graph.Iterator, ctx *context) (graph.Iterator, *context) {
out := ctx.copy()
out.labelSet = path
return in, &out
},
}
}
@ -290,7 +318,7 @@ func buildSave(
return join(qs, from, save)
}
func inOutIterator(viaPath *Path, from graph.Iterator, inIterator bool, tags []string) graph.Iterator {
func inOutIterator(viaPath *Path, from graph.Iterator, inIterator bool, tags []string, ctx *context) graph.Iterator {
start, goal := quad.Subject, quad.Object
if inIterator {
start, goal = goal, start
@ -303,8 +331,14 @@ func inOutIterator(viaPath *Path, from graph.Iterator, inIterator bool, tags []s
source := iterator.NewLinksTo(viaPath.qs, from, start)
trail := iterator.NewLinksTo(viaPath.qs, viaIter, quad.Predicate)
route := join(viaPath.qs, source, trail)
var label graph.Iterator
if ctx != nil {
if ctx.labelSet != nil {
labeliter := ctx.labelSet.BuildIteratorOn(viaPath.qs)
label = iterator.NewLinksTo(viaPath.qs, labeliter, quad.Label)
}
}
route := join(viaPath.qs, source, trail, label)
return iterator.NewHasA(viaPath.qs, route, goal)
}