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() }
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 }
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...) }
func propertiesOf(obj *otto.Object, name string) []string { val, _ := obj.Get(name) if val.IsUndefined() { return nil } export, _ := val.Export() return export.([]string) }
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() }
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 }
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 }
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 }
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 }
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 }
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) } } } }
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 }
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 }
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 }
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)) } }
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 }
// 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 }
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...) }
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) }
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) }
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) }
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 }
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 }
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 }
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()) } } }
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 }
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)) } }
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 }