func getString(obj *otto.Object, name string) (string, error) {
	v, err := obj.Get(name)
	if err != nil {
		return "", err
	}
	return v.ToString()
}
func getInt(obj *otto.Object, name string) (int64, error) {
	v, err := obj.Get(name)
	if err != nil {
		return -1, err
	}
	return v.ToInteger()
}
Beispiel #3
0
func getViaData(obj *otto.Object) (predicates []interface{}, tags []string, ok bool) {
	argList, _ := obj.Get("_gremlin_values")
	if argList.Class() != "GoArray" {
		clog.Errorf("How is arglist not an array? Return nothing. %v", argList.Class())
		return nil, nil, false
	}
	argArray := argList.Object()
	lengthVal, _ := argArray.Get("length")
	length, _ := lengthVal.ToInteger()
	if length == 0 {
		predicates = []interface{}{}
	} else {
		zero, _ := argArray.Get("0")
		predicates = buildPathFromValue(zero)
	}
	if length >= 2 {
		one, _ := argArray.Get("1")
		if one.IsString() {
			tags = append(tags, one.String())
		} else if one.Class() == "Array" {
			tags = stringsFrom(one.Object())
		}
	}
	ok = true
	return
}
Beispiel #4
0
func (ctx ppctx) fields(obj *otto.Object) []string {
	var (
		vals, methods []string
		seen          = make(map[string]bool)
	)
	add := func(k string) {
		if seen[k] || boringKeys[k] {
			return
		}
		seen[k] = true
		if v, _ := obj.Get(k); v.IsFunction() {
			methods = append(methods, k)
		} else {
			vals = append(vals, k)
		}
	}
	// add own properties
	ctx.doOwnProperties(obj.Value(), add)
	// add properties of the constructor
	if cp := constructorPrototype(obj); cp != nil {
		ctx.doOwnProperties(cp.Value(), add)
	}
	sort.Strings(vals)
	sort.Strings(methods)
	return append(vals, methods...)
}
Beispiel #5
0
func propertiesOf(obj *otto.Object, name string) []string {
	val, _ := obj.Get(name)
	if val.IsUndefined() {
		return nil
	}
	export, _ := val.Export()
	return export.([]string)
}
Beispiel #6
0
func getFirstArgAsMorphismChain(obj *otto.Object) *otto.Object {
	arg, _ := obj.Get("_gremlin_values")
	firstArg, _ := arg.Object().Get("0")
	if isVertexChain(firstArg.Object()) {
		return nil
	}
	return firstArg.Object()
}
Beispiel #7
0
func constructorPrototype(obj *otto.Object) *otto.Object {
	if v, _ := obj.Get("constructor"); v.Object() != nil {
		if v, _ = v.Object().Get("prototype"); v.Object() != nil {
			return v.Object()
		}
	}
	return nil
}
Beispiel #8
0
func debugChain(obj *otto.Object) bool {
	val, _ := obj.Get("_gremlin_type")
	glog.V(2).Infoln(val)
	val, _ = obj.Get("_gremlin_prev")
	if val.IsObject() {
		return debugChain(val.Object())
	}
	return false
}
Beispiel #9
0
func debugChain(obj *otto.Object) bool {
	val, _ := obj.Get("_gremlin_type")
	if clog.V(2) {
		clog.Infof("%v", val)
	}
	val, _ = obj.Get("_gremlin_prev")
	if val.IsObject() {
		return debugChain(val.Object())
	}
	return false
}
Beispiel #10
0
func isVertexChain(obj *otto.Object) bool {
	val, _ := obj.Get("_gremlin_type")
	if val.String() == "vertex" {
		return true
	}
	val, _ = obj.Get("_gremlin_prev")
	if val.IsObject() {
		return isVertexChain(val.Object())
	}
	return false
}
Beispiel #11
0
func getStrings(obj *otto.Object, field string) []string {
	strings := make([]string, 0)
	val, _ := obj.Get(field)
	if !val.IsUndefined() {
		export, _ := val.Export()
		array := export.([]interface{})
		for _, arg := range array {
			strings = append(strings, arg.(string))
		}
	}
	return strings
}
Beispiel #12
0
func setHeader(o *otto.Object, h *http.Header) {
	header, _ := o.Get("header")
	headerIface, _ := header.Export()
	headerMap, ok := headerIface.(map[string]interface{})

	if ok {
		for k, v := range headerMap {
			strV, ok := v.(string)
			if ok {
				h.Set(k, strV)
			}
		}
	}
}
Beispiel #13
0
func getFirstArgAsInt64(obj *otto.Object) (int64, bool) {
	arg, err := obj.Get("_gremlin_values")
	if err != nil {
		return 0, false
	}
	firstArg, err := arg.Object().Get("0")
	if err != nil {
		return 0, false
	}
	if !firstArg.IsNumber() {
		return 0, false
	}
	v, err := firstArg.ToInteger()
	return v, err == nil
}
Beispiel #14
0
func stringsFrom(obj *otto.Object) []string {
	var output []string
	lengthValue, _ := obj.Get("length")
	length, _ := lengthValue.ToInteger()
	ulength := uint32(length)
	for i := uint32(0); i < ulength; i++ {
		name := strconv.FormatInt(int64(i), 10)
		value, err := obj.Get(name)
		if err != nil || !value.IsString() {
			continue
		}
		output = append(output, value.String())
	}
	return output
}
Beispiel #15
0
func (ctx ppctx) isBigNumber(v *otto.Object) bool {
	// Handle numbers with custom constructor.
	if v, _ := v.Get("constructor"); v.Object() != nil {
		if strings.HasPrefix(toString(v.Object()), "function BigNumber") {
			return true
		}
	}
	// Handle default constructor.
	BigNumber, _ := ctx.vm.Object("BigNumber.prototype")
	if BigNumber == nil {
		return false
	}
	bv, _ := BigNumber.Call("isPrototypeOf", v)
	b, _ := bv.ToBoolean()
	return b
}
Beispiel #16
0
func JsoToResponseWriter(respObj *otto.Object, w http.ResponseWriter) {
	contentTypeV, err := respObj.Get("contentType")
	if err == nil {
		contentType, _ := contentTypeV.ToString()
		w.Header().Set("Content-Type", contentType)
	}

	wHeader := w.Header()
	setHeader(respObj, &wHeader)

	codeV, err := respObj.Get("statusCode")
	if err == nil && codeV.IsDefined() {
		code, _ := codeV.ToInteger()
		w.WriteHeader(int(code))
	}
}
Beispiel #17
0
func makeListOfStringsFromArrayValue(obj *otto.Object) []string {
	var output []string
	lengthValue, _ := obj.Get("length")
	length, _ := lengthValue.ToInteger()
	ulength := uint32(length)
	for index := uint32(0); index < ulength; index += 1 {
		name := strconv.FormatInt(int64(index), 10)
		value, err := obj.Get(name)
		if err != nil {
			continue
		}
		if !value.IsString() {
			continue
		}
		s, _ := value.ToString()
		output = append(output, s)
	}
	return output
}
Beispiel #18
0
// Converts a JS array into a Go string array.
func ottoArrayToStrings(array *otto.Object) []string {
	lengthVal, err := array.Get("length")
	if err != nil {
		return nil
	}
	length, err := lengthVal.ToInteger()
	if err != nil || length <= 0 {
		return nil
	}

	result := make([]string, 0, length)
	for i := 0; i < int(length); i++ {
		item, err := array.Get(strconv.Itoa(i))
		if err == nil && item.IsString() {
			result = append(result, item.String())
		}
	}
	return result
}
Beispiel #19
0
func (ctx ppctx) fields(obj *otto.Object) []string {
	var (
		vals, methods []string
		seen          = make(map[string]bool)
	)
	add := func(k string) {
		if seen[k] || boringKeys[k] || strings.HasPrefix(k, "_") {
			return
		}
		seen[k] = true
		if v, _ := obj.Get(k); v.IsFunction() {
			methods = append(methods, k)
		} else {
			vals = append(vals, k)
		}
	}
	iterOwnAndConstructorKeys(ctx.vm, obj, add)
	sort.Strings(vals)
	sort.Strings(methods)
	return append(vals, methods...)
}
Beispiel #20
0
func buildInOutIterator(obj *otto.Object, ts graph.TripleStore, base graph.Iterator, isReverse bool) graph.Iterator {
	argList, _ := obj.Get("_gremlin_values")
	if argList.Class() != "GoArray" {
		glog.Errorln("How is arglist not an array? Return nothing.", argList.Class())
		return graph.NewNullIterator()
	}
	argArray := argList.Object()
	lengthVal, _ := argArray.Get("length")
	length, _ := lengthVal.ToInteger()
	var predicateNodeIterator graph.Iterator
	if length == 0 {
		predicateNodeIterator = ts.GetNodesAllIterator()
	} else {
		zero, _ := argArray.Get("0")
		predicateNodeIterator = buildIteratorFromValue(zero, ts)
	}
	if length >= 2 {
		var tags []string
		one, _ := argArray.Get("1")
		if one.IsString() {
			s, _ := one.ToString()
			tags = append(tags, s)
		} else if one.Class() == "Array" {
			tags = makeListOfStringsFromArrayValue(one.Object())
		}
		for _, tag := range tags {
			predicateNodeIterator.AddTag(tag)
		}
	}

	in, out := graph.Subject, graph.Object
	if isReverse {
		in, out = out, in
	}
	lto := graph.NewLinksToIterator(ts, base, in)
	and := graph.NewAndIterator()
	and.AddSubIterator(graph.NewLinksToIterator(ts, predicateNodeIterator, graph.Predicate))
	and.AddSubIterator(lto)
	return graph.NewHasaIterator(ts, and, out)
}
Beispiel #21
0
func reverseGremlinChainHelper(env *otto.Otto, chain *otto.Object, newBase *otto.Object, tag string) (*otto.Object, *otto.Object) {
	kindVal, _ := chain.Get("_gremlin_type")
	kind, _ := kindVal.ToString()

	if tag != "" {
		if kind == "tag" {
			tags := getStringArgs(chain)
			for _, t := range tags {
				if t == tag {
					return newBase, chain
				}
			}
		}
	}

	if kind == "morphism" || kind == "vertex" {
		return newBase, chain
	}
	var newKind string
	switch kind {
	case "in":
		newKind = "out"
	case "out":
		newKind = "in"
	default:
		newKind = kind
	}
	prev, _ := chain.Get("_gremlin_prev")
	env.Run("var out = {}")
	out, _ := env.Object("out")
	out.Set("_gremlin_type", newKind)
	values, _ := chain.Get("_gremlin_values")
	out.Set("_gremlin_values", values)
	back, _ := chain.Get("_gremlin_back_chain")
	out.Set("_gremlin_back_chain", back)
	out.Set("_gremlin_prev", newBase)
	strings, _ := chain.Get("string_args")
	out.Set("string_args", strings)
	return reverseGremlinChainHelper(env, prev.Object(), out, tag)
}
Beispiel #22
0
func buildInOutIterator(obj *otto.Object, qs graph.QuadStore, base graph.Iterator, isReverse bool) graph.Iterator {
	argList, _ := obj.Get("_gremlin_values")
	if argList.Class() != "GoArray" {
		glog.Errorln("How is arglist not an array? Return nothing.", argList.Class())
		return iterator.NewNull()
	}
	argArray := argList.Object()
	lengthVal, _ := argArray.Get("length")
	length, _ := lengthVal.ToInteger()
	var predicateNodeIterator graph.Iterator
	if length == 0 {
		predicateNodeIterator = qs.NodesAllIterator()
	} else {
		zero, _ := argArray.Get("0")
		predicateNodeIterator = buildIteratorFromValue(zero, qs)
	}
	if length >= 2 {
		var tags []string
		one, _ := argArray.Get("1")
		if one.IsString() {
			tags = append(tags, one.String())
		} else if one.Class() == "Array" {
			tags = stringsFrom(one.Object())
		}
		for _, tag := range tags {
			predicateNodeIterator.Tagger().Add(tag)
		}
	}

	in, out := quad.Subject, quad.Object
	if isReverse {
		in, out = out, in
	}
	lto := iterator.NewLinksTo(qs, base, in)
	and := iterator.NewAnd()
	and.AddSubIterator(iterator.NewLinksTo(qs, predicateNodeIterator, quad.Predicate))
	and.AddSubIterator(lto)
	return iterator.NewHasA(qs, and, out)
}
Beispiel #23
0
func convertObject(input *otto.Object) map[string]interface{} {
	output := map[string]interface{}{}
	if input == nil {
		return output
	}

	for _, key := range input.Keys() {
		v1, _ := input.Get(key)

		var trueValue interface{}
		if v1.IsBoolean() {
			trueValue, _ = v1.ToBoolean()
		} else if v1.IsNumber() {
			trueValue, _ = v1.ToInteger()
		} else {
			trueValue = v1.String()
		}

		output[key] = trueValue
	}

	return output
}
Beispiel #24
0
func ottoToGoArray(array *otto.Object) ([]interface{}, error) {
	lengthVal, err := array.Get("length")
	if err != nil {
		return nil, err
	}
	length, err := lengthVal.ToInteger()
	if err != nil {
		return nil, err
	}

	result := make([]interface{}, length)
	for i := 0; i < int(length); i++ {
		item, err := array.Get(strconv.Itoa(i))
		if err != nil {
			return nil, err
		}
		result[i], err = ottoToGo(item)
		if err != nil {
			return nil, err
		}
	}
	return result, nil
}
Beispiel #25
0
func JsoToRequest(o *otto.Object) *http.Request {
	url, _ := o.Get("url")
	method, err := o.Get("method")
	body, _ := o.Get("body")

	methodStr, err := method.ToString()
	if method == otto.UndefinedValue() || err != nil {
		methodStr = "GET"
	}
	urlStr, _ := url.ToString()

	req, _ := http.NewRequest(methodStr, urlStr, nil)

	if body != otto.UndefinedValue() {
		str, err := body.ToString()
		if err == nil {
			req.Body = &ClosingBuffer{bytes.NewBufferString(str)}
		}
	}

	setHeader(o, &req.Header)

	return req
}
Beispiel #26
0
func (ctx ppctx) printObject(obj *otto.Object, level int, inArray bool) {
	switch obj.Class() {
	case "Array":
		lv, _ := obj.Get("length")
		len, _ := lv.ToInteger()
		if len == 0 {
			fmt.Printf("[]")
			return
		}
		if level > maxPrettyPrintLevel {
			fmt.Print("[...]")
			return
		}
		fmt.Print("[")
		for i := int64(0); i < len; i++ {
			el, err := obj.Get(strconv.FormatInt(i, 10))
			if err == nil {
				ctx.printValue(el, level+1, true)
			}
			if i < len-1 {
				fmt.Printf(", ")
			}
		}
		fmt.Print("]")

	case "Object":
		// Print values from bignumber.js as regular numbers.
		if ctx.isBigNumber(obj) {
			numberColor.Print(toString(obj))
			return
		}
		// Otherwise, print all fields indented, but stop if we're too deep.
		keys := ctx.fields(obj)
		if len(keys) == 0 {
			fmt.Print("{}")
			return
		}
		if level > maxPrettyPrintLevel {
			fmt.Print("{...}")
			return
		}
		fmt.Println("{")
		for i, k := range keys {
			v, _ := obj.Get(k)
			fmt.Printf("%s%s: ", ctx.indent(level+1), k)
			ctx.printValue(v, level+1, false)
			if i < len(keys)-1 {
				fmt.Printf(",")
			}
			fmt.Println()
		}
		if inArray {
			level--
		}
		fmt.Printf("%s}", ctx.indent(level))

	case "Function":
		// Use toString() to display the argument list if possible.
		if robj, err := obj.Call("toString"); err != nil {
			functionColor.Print("function()")
		} else {
			desc := strings.Trim(strings.Split(robj.String(), "{")[0], " \t\n")
			desc = strings.Replace(desc, " (", "(", 1)
			functionColor.Print(desc)
		}

	case "RegExp":
		stringColor.Print(toString(obj))

	default:
		if v, _ := obj.Get("toString"); v.IsFunction() && level <= maxPrettyPrintLevel {
			s, _ := obj.Call("toString")
			fmt.Printf("<%s %s>", obj.Class(), s.String())
		} else {
			fmt.Printf("<%s>", obj.Class())
		}
	}
}
Beispiel #27
0
func buildIteratorTreeHelper(obj *otto.Object, ts graph.TripleStore, base graph.Iterator) graph.Iterator {
	var it graph.Iterator
	it = base
	// TODO: Better error handling
	kindVal, _ := obj.Get("_gremlin_type")
	stringArgs := getStringArgs(obj)
	var subIt graph.Iterator
	prevVal, _ := obj.Get("_gremlin_prev")
	if !prevVal.IsObject() {
		subIt = base
	} else {
		subIt = buildIteratorTreeHelper(prevVal.Object(), ts, base)
	}

	kind, _ := kindVal.ToString()
	switch kind {
	case "vertex":
		if len(stringArgs) == 0 {
			it = ts.GetNodesAllIterator()
		} else {
			fixed := ts.MakeFixed()
			for _, name := range stringArgs {
				fixed.AddValue(ts.GetIdFor(name))
			}
			it = fixed
		}
	case "tag":
		it = subIt
		for _, tag := range stringArgs {
			it.AddTag(tag)
		}
	case "save":
		all := ts.GetNodesAllIterator()
		if len(stringArgs) > 2 || len(stringArgs) == 0 {
			return graph.NewNullIterator()
		}
		if len(stringArgs) == 2 {
			all.AddTag(stringArgs[1])
		} else {
			all.AddTag(stringArgs[0])
		}
		predFixed := ts.MakeFixed()
		predFixed.AddValue(ts.GetIdFor(stringArgs[0]))
		subAnd := graph.NewAndIterator()
		subAnd.AddSubIterator(graph.NewLinksToIterator(ts, predFixed, graph.Predicate))
		subAnd.AddSubIterator(graph.NewLinksToIterator(ts, all, graph.Object))
		hasa := graph.NewHasaIterator(ts, subAnd, graph.Subject)
		and := graph.NewAndIterator()
		and.AddSubIterator(hasa)
		and.AddSubIterator(subIt)
		it = and
	case "saver":
		all := ts.GetNodesAllIterator()
		if len(stringArgs) > 2 || len(stringArgs) == 0 {
			return graph.NewNullIterator()
		}
		if len(stringArgs) == 2 {
			all.AddTag(stringArgs[1])
		} else {
			all.AddTag(stringArgs[0])
		}
		predFixed := ts.MakeFixed()
		predFixed.AddValue(ts.GetIdFor(stringArgs[0]))
		subAnd := graph.NewAndIterator()
		subAnd.AddSubIterator(graph.NewLinksToIterator(ts, predFixed, graph.Predicate))
		subAnd.AddSubIterator(graph.NewLinksToIterator(ts, all, graph.Subject))
		hasa := graph.NewHasaIterator(ts, subAnd, graph.Object)
		and := graph.NewAndIterator()
		and.AddSubIterator(hasa)
		and.AddSubIterator(subIt)
		it = and
	case "has":
		fixed := ts.MakeFixed()
		if len(stringArgs) < 2 {
			return graph.NewNullIterator()
		}
		for _, name := range stringArgs[1:] {
			fixed.AddValue(ts.GetIdFor(name))
		}
		predFixed := ts.MakeFixed()
		predFixed.AddValue(ts.GetIdFor(stringArgs[0]))
		subAnd := graph.NewAndIterator()
		subAnd.AddSubIterator(graph.NewLinksToIterator(ts, predFixed, graph.Predicate))
		subAnd.AddSubIterator(graph.NewLinksToIterator(ts, fixed, graph.Object))
		hasa := graph.NewHasaIterator(ts, subAnd, graph.Subject)
		and := graph.NewAndIterator()
		and.AddSubIterator(hasa)
		and.AddSubIterator(subIt)
		it = and
	case "morphism":
		it = base
	case "and":
		arg, _ := obj.Get("_gremlin_values")
		firstArg, _ := arg.Object().Get("0")
		if !isVertexChain(firstArg.Object()) {
			return graph.NewNullIterator()
		}
		argIt := buildIteratorTree(firstArg.Object(), ts)

		and := graph.NewAndIterator()
		and.AddSubIterator(subIt)
		and.AddSubIterator(argIt)
		it = and
	case "back":
		arg, _ := obj.Get("_gremlin_back_chain")
		argIt := buildIteratorTree(arg.Object(), ts)
		and := graph.NewAndIterator()
		and.AddSubIterator(subIt)
		and.AddSubIterator(argIt)
		it = and
	case "is":
		fixed := ts.MakeFixed()
		for _, name := range stringArgs {
			fixed.AddValue(ts.GetIdFor(name))
		}
		and := graph.NewAndIterator()
		and.AddSubIterator(fixed)
		and.AddSubIterator(subIt)
		it = and
	case "or":
		arg, _ := obj.Get("_gremlin_values")
		firstArg, _ := arg.Object().Get("0")
		if !isVertexChain(firstArg.Object()) {
			return graph.NewNullIterator()
		}
		argIt := buildIteratorTree(firstArg.Object(), ts)

		or := graph.NewOrIterator()
		or.AddSubIterator(subIt)
		or.AddSubIterator(argIt)
		it = or
	case "both":
		// Hardly the most efficient pattern, but the most general.
		// Worth looking into an Optimize() optimization here.
		clone := subIt.Clone()
		it1 := buildInOutIterator(obj, ts, subIt, false)
		it2 := buildInOutIterator(obj, ts, clone, true)

		or := graph.NewOrIterator()
		or.AddSubIterator(it1)
		or.AddSubIterator(it2)
		it = or
	case "out":
		it = buildInOutIterator(obj, ts, subIt, false)
	case "follow":
		// Follow a morphism
		arg, _ := obj.Get("_gremlin_values")
		firstArg, _ := arg.Object().Get("0")
		if isVertexChain(firstArg.Object()) {
			return graph.NewNullIterator()
		}
		it = buildIteratorTreeHelper(firstArg.Object(), ts, subIt)
	case "followr":
		// Follow a morphism
		arg, _ := obj.Get("_gremlin_followr")
		if isVertexChain(arg.Object()) {
			return graph.NewNullIterator()
		}
		it = buildIteratorTreeHelper(arg.Object(), ts, subIt)
	case "in":
		it = buildInOutIterator(obj, ts, subIt, true)
	}
	return it
}
Beispiel #28
0
func buildPathFromObject(obj *otto.Object) *path.Path {
	var p *path.Path
	val, _ := obj.Get("_gremlin_type")
	stringArgs := propertiesOf(obj, "string_args")
	gremlinType := val.String()
	if prev, _ := obj.Get("_gremlin_prev"); !prev.IsObject() {
		switch gremlinType {
		case "vertex":
			return path.StartMorphism(stringArgs...)
		case "morphism":
			return path.StartMorphism()
		default:
			panic("No base gremlin path other than 'vertex' or 'morphism'")
		}
	} else {
		p = buildPathFromObject(prev.Object())
	}
	if p == nil {
		return nil
	}
	switch gremlinType {
	case "Is":
		return p.Is(stringArgs...)
	case "In":
		preds, tags, ok := getViaData(obj)
		if !ok {
			return nil
		}
		return p.InWithTags(tags, preds...)
	case "Out":
		preds, tags, ok := getViaData(obj)
		if !ok {
			return nil
		}
		return p.OutWithTags(tags, preds...)
	case "Both":
		preds, _, ok := getViaData(obj)
		if !ok {
			return nil
		}
		return p.Both(preds...)
	case "Follow":
		subobj := getFirstArgAsMorphismChain(obj)
		if subobj == nil {
			return nil
		}
		return p.Follow(buildPathFromObject(subobj))
	case "FollowR":
		subobj := getFirstArgAsMorphismChain(obj)
		if subobj == nil {
			return nil
		}
		return p.FollowReverse(buildPathFromObject(subobj))
	case "And", "Intersect":
		subobj := getFirstArgAsVertexChain(obj)
		if subobj == nil {
			return nil
		}
		return p.And(buildPathFromObject(subobj))
	case "Union", "Or":
		subobj := getFirstArgAsVertexChain(obj)
		if subobj == nil {
			return nil
		}
		return p.Or(buildPathFromObject(subobj))
	case "Back":
		if len(stringArgs) != 1 {
			return nil
		}
		return p.Back(stringArgs[0])
	case "Tag", "As":
		return p.Tag(stringArgs...)
	case "Has":
		if len(stringArgs) < 2 {
			return nil
		}
		return p.Has(stringArgs[0], stringArgs[1:]...)
	case "Save", "SaveR":
		if len(stringArgs) > 2 || len(stringArgs) == 0 {
			return nil
		}
		tag := stringArgs[0]
		if len(stringArgs) == 2 {
			tag = stringArgs[1]
		}
		if gremlinType == "SaveR" {
			return p.SaveReverse(stringArgs[0], tag)
		}
		return p.Save(stringArgs[0], tag)
	case "Except", "Difference":
		subobj := getFirstArgAsVertexChain(obj)
		if subobj == nil {
			return nil
		}
		return p.Except(buildPathFromObject(subobj))
	case "InPredicates":
		return p.InPredicates()
	case "OutPredicates":
		return p.OutPredicates()
	case "LabelContext":
		labels, tags, ok := getViaData(obj)
		if !ok {
			return nil
		}
		return p.LabelContextWithTags(tags, labels...)
	default:
		panic(fmt.Sprint("Unimplemented Gremlin function", gremlinType))
	}
}
Beispiel #29
0
func buildIteratorTreeHelper(obj *otto.Object, qs graph.QuadStore, base graph.Iterator) graph.Iterator {
	it := base

	// TODO: Better error handling
	var subIt graph.Iterator
	if prev, _ := obj.Get("_gremlin_prev"); !prev.IsObject() {
		subIt = base
	} else {
		subIt = buildIteratorTreeHelper(prev.Object(), qs, base)
	}

	stringArgs := propertiesOf(obj, "string_args")
	val, _ := obj.Get("_gremlin_type")
	switch val.String() {
	case "vertex":
		if len(stringArgs) == 0 {
			it = qs.NodesAllIterator()
		} else {
			fixed := qs.FixedIterator()
			for _, name := range stringArgs {
				fixed.Add(qs.ValueOf(name))
			}
			it = fixed
		}
	case "tag":
		it = subIt
		for _, tag := range stringArgs {
			it.Tagger().Add(tag)
		}
	case "save":
		all := qs.NodesAllIterator()
		if len(stringArgs) > 2 || len(stringArgs) == 0 {
			return iterator.NewNull()
		}
		if len(stringArgs) == 2 {
			all.Tagger().Add(stringArgs[1])
		} else {
			all.Tagger().Add(stringArgs[0])
		}
		predFixed := qs.FixedIterator()
		predFixed.Add(qs.ValueOf(stringArgs[0]))
		subAnd := iterator.NewAnd()
		subAnd.AddSubIterator(iterator.NewLinksTo(qs, predFixed, quad.Predicate))
		subAnd.AddSubIterator(iterator.NewLinksTo(qs, all, quad.Object))
		hasa := iterator.NewHasA(qs, subAnd, quad.Subject)
		and := iterator.NewAnd()
		and.AddSubIterator(hasa)
		and.AddSubIterator(subIt)
		it = and
	case "saver":
		all := qs.NodesAllIterator()
		if len(stringArgs) > 2 || len(stringArgs) == 0 {
			return iterator.NewNull()
		}
		if len(stringArgs) == 2 {
			all.Tagger().Add(stringArgs[1])
		} else {
			all.Tagger().Add(stringArgs[0])
		}
		predFixed := qs.FixedIterator()
		predFixed.Add(qs.ValueOf(stringArgs[0]))
		subAnd := iterator.NewAnd()
		subAnd.AddSubIterator(iterator.NewLinksTo(qs, predFixed, quad.Predicate))
		subAnd.AddSubIterator(iterator.NewLinksTo(qs, all, quad.Subject))
		hasa := iterator.NewHasA(qs, subAnd, quad.Object)
		and := iterator.NewAnd()
		and.AddSubIterator(hasa)
		and.AddSubIterator(subIt)
		it = and
	case "has":
		fixed := qs.FixedIterator()
		if len(stringArgs) < 2 {
			return iterator.NewNull()
		}
		for _, name := range stringArgs[1:] {
			fixed.Add(qs.ValueOf(name))
		}
		predFixed := qs.FixedIterator()
		predFixed.Add(qs.ValueOf(stringArgs[0]))
		subAnd := iterator.NewAnd()
		subAnd.AddSubIterator(iterator.NewLinksTo(qs, predFixed, quad.Predicate))
		subAnd.AddSubIterator(iterator.NewLinksTo(qs, fixed, quad.Object))
		hasa := iterator.NewHasA(qs, subAnd, quad.Subject)
		and := iterator.NewAnd()
		and.AddSubIterator(hasa)
		and.AddSubIterator(subIt)
		it = and
	case "morphism":
		it = base
	case "and":
		arg, _ := obj.Get("_gremlin_values")
		firstArg, _ := arg.Object().Get("0")
		if !isVertexChain(firstArg.Object()) {
			return iterator.NewNull()
		}
		argIt := buildIteratorTree(firstArg.Object(), qs)

		and := iterator.NewAnd()
		and.AddSubIterator(subIt)
		and.AddSubIterator(argIt)
		it = and
	case "back":
		arg, _ := obj.Get("_gremlin_back_chain")
		argIt := buildIteratorTree(arg.Object(), qs)
		and := iterator.NewAnd()
		and.AddSubIterator(subIt)
		and.AddSubIterator(argIt)
		it = and
	case "is":
		fixed := qs.FixedIterator()
		for _, name := range stringArgs {
			fixed.Add(qs.ValueOf(name))
		}
		and := iterator.NewAnd()
		and.AddSubIterator(fixed)
		and.AddSubIterator(subIt)
		it = and
	case "or":
		arg, _ := obj.Get("_gremlin_values")
		firstArg, _ := arg.Object().Get("0")
		if !isVertexChain(firstArg.Object()) {
			return iterator.NewNull()
		}
		argIt := buildIteratorTree(firstArg.Object(), qs)

		or := iterator.NewOr()
		or.AddSubIterator(subIt)
		or.AddSubIterator(argIt)
		it = or
	case "both":
		// Hardly the most efficient pattern, but the most general.
		// Worth looking into an Optimize() optimization here.
		clone := subIt.Clone()
		it1 := buildInOutIterator(obj, qs, subIt, false)
		it2 := buildInOutIterator(obj, qs, clone, true)

		or := iterator.NewOr()
		or.AddSubIterator(it1)
		or.AddSubIterator(it2)
		it = or
	case "out":
		it = buildInOutIterator(obj, qs, subIt, false)
	case "follow":
		// Follow a morphism
		arg, _ := obj.Get("_gremlin_values")
		firstArg, _ := arg.Object().Get("0")
		if isVertexChain(firstArg.Object()) {
			return iterator.NewNull()
		}
		it = buildIteratorTreeHelper(firstArg.Object(), qs, subIt)
	case "followr":
		// Follow a morphism
		arg, _ := obj.Get("_gremlin_followr")
		if isVertexChain(arg.Object()) {
			return iterator.NewNull()
		}
		it = buildIteratorTreeHelper(arg.Object(), qs, subIt)
	case "in":
		it = buildInOutIterator(obj, qs, subIt, true)
	}
	return it
}