default ExprResult getSubTraversalAsExpr()

in interactive_engine/compiler/src/main/java/com/alibaba/graphscope/gremlin/transform/TraversalParentTransform.java [50:224]


    default ExprResult getSubTraversalAsExpr(ExprArg exprArg) {
        int size = exprArg.size();
        // return a result representing the traversal cannot be converted to expression
        final ExprResult defaultNonExpr = (new ExprResult()).addTagExpr("", Optional.empty());
        // the followings are considered as expressions instead of apply
        if (size <= 1) {
            if (exprArg.isEmpty()) { // by()
                return (new ExprResult()).addTagExpr("", Optional.of("@"));
            } else {
                Step step = exprArg.getStartStep();
                if (step instanceof PropertyMapStep) { // valueMap(..)
                    String[] mapKeys = ((PropertyMapStep) step).getPropertyKeys();
                    if (mapKeys.length > 0) {
                        StringBuilder stringBuilder = new StringBuilder();
                        stringBuilder.append("{");
                        for (int i = 0; i < mapKeys.length; ++i) {
                            if (i > 0) {
                                stringBuilder.append(", ");
                            }
                            stringBuilder.append("@." + mapKeys[i]);
                        }
                        stringBuilder.append("}");
                        return (new ExprResult())
                                .addTagExpr("", Optional.of(stringBuilder.toString()));
                    } else {
                        // valueMap() -> @.~all
                        return (new ExprResult())
                                .addTagExpr("", Optional.of("@." + ArgUtils.PROPERTY_ALL));
                    }
                } else if (step instanceof PropertiesStep) { // values(..)
                    String[] mapKeys = ((PropertiesStep) step).getPropertyKeys();
                    if (mapKeys.length == 0) {
                        throw new OpArgIllegalException(
                                OpArgIllegalException.Cause.UNSUPPORTED_TYPE,
                                "values() is unsupported");
                    }
                    if (mapKeys.length > 1) {
                        throw new OpArgIllegalException(
                                OpArgIllegalException.Cause.UNSUPPORTED_TYPE,
                                "use valueMap(..) instead if there are multiple project keys");
                    }
                    return (new ExprResult()).addTagExpr("", Optional.of("@." + mapKeys[0]));
                } else if (step instanceof LabelStep) {
                    return (new ExprResult())
                            .addTagExpr("", Optional.of("@." + T.label.getAccessor())); // @.~label
                } else if (step instanceof IdStep) {
                    return (new ExprResult())
                            .addTagExpr("", Optional.of("@." + T.id.getAccessor())); // @.~id
                } else if (step instanceof ElementMapStep) { // elementMap(..)
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append("{");
                    // id
                    stringBuilder.append("@." + ArgUtils.ID + ",");
                    // label
                    stringBuilder.append("@." + ArgUtils.LABEL + ",");
                    // properties
                    String[] mapKeys = ((ElementMapStep) step).getPropertyKeys();
                    if (mapKeys.length > 0) {
                        for (int i = 0; i < mapKeys.length; ++i) {
                            if (i > 0) {
                                stringBuilder.append(",");
                            }
                            stringBuilder.append("@." + mapKeys[i]);
                        }
                    } else {
                        // elementMap() -> @.~all
                        stringBuilder.append("@." + ArgUtils.PROPERTY_ALL);
                    }
                    stringBuilder.append("}");
                    return (new ExprResult()).addTagExpr("", Optional.of(stringBuilder.toString()));
                } else if (step instanceof SelectOneStep || step instanceof SelectStep) {
                    // select('a'), select('a').by()
                    // select('a').by('name'/values/valueMap)
                    // select('a', 'b'), select('a', 'b').by()
                    // select('a', 'b').by('name'/values/valueMap).by('name'/values/valueMap)
                    Map<String, Traversal.Admin> selectBys =
                            getProjectTraversals((TraversalParent) step);
                    ExprResult exprRes = new ExprResult();
                    for (Map.Entry<String, Traversal.Admin> entry : selectBys.entrySet()) {
                        String k = entry.getKey();
                        Traversal.Admin v = entry.getValue();
                        Optional<String> byExpr =
                                getSubTraversalAsExpr(new ExprArg(v)).getSingleExpr();
                        if (byExpr.isPresent()) {
                            String expr = byExpr.get().replace("@", "@" + k);
                            exprRes.addTagExpr(k, Optional.of(expr));
                        } else {
                            exprRes.addTagExpr(k, Optional.empty());
                        }
                    }
                    return exprRes;
                } else if (step instanceof WhereTraversalStep.WhereStartStep) { // where(as('a'))
                    WhereTraversalStep.WhereStartStep startStep =
                            (WhereTraversalStep.WhereStartStep) step;
                    String selectKey = (String) startStep.getScopeKeys().iterator().next();
                    return (new ExprResult()).addTagExpr(selectKey, Optional.of("@" + selectKey));
                } else if (step instanceof TraversalMapStep) { // select(keys), select(values)
                    ProjectOp mapOp =
                            (ProjectOp) StepTransformFactory.TRAVERSAL_MAP_STEP.apply(step);
                    List<Pair> pairs = (List<Pair>) mapOp.getExprWithAlias().get().applyArg();
                    String mapExpr = (String) pairs.get(0).getValue0();
                    String mapKey = mapExpr.substring(1);
                    return (new ExprResult()).addTagExpr(mapKey, Optional.of(mapExpr));
                } else if (step instanceof DedupGlobalStep) {
                    // support the pattern of dedup by variables, i.e. dedup().by("name") or
                    // dedup("a").by("name")
                    ExprResult exprRes = new ExprResult();

                    DedupGlobalStep dedupStep = (DedupGlobalStep) step;
                    List<Traversal.Admin> traversals = dedupStep.getLocalChildren();
                    // get dedupTraversal nested in by() from dedup step
                    Traversal.Admin dedupTraversal =
                            traversals.isEmpty() ? new IdentityTraversal() : traversals.get(0);
                    // check whether the dedupTraversal can be represented as a expression or a
                    // apply,
                    // return string if it is a expression, i.e. dedup().by("name") or
                    // dedup("a").by("name"),
                    // return null if it is a apply, i.e. dedup().by(out().count())
                    Optional<String> exprOpt =
                            getSubTraversalAsExpr(new ExprArg(dedupTraversal)).getSingleExpr();
                    // get dedup keys from dedup step, i.e dedup() -> [""], dedup("a") -> ["a"],
                    // dedup("a", "b") ->
                    // ["a", "b"]
                    Set<String> dedupKeys =
                            dedupStep.getScopeKeys().isEmpty()
                                    ? Collections.singleton("")
                                    : dedupStep.getScopeKeys();
                    for (String key : dedupKeys) {
                        if (exprOpt.isPresent()) { // dedup().by("name") or dedup("a").by("name")
                            String expr = exprOpt.get().replace("@", "@" + key);
                            exprRes.addTagExpr(key, Optional.of(expr));
                        } else { // dedup().by(out().count())
                            exprRes.addTagExpr(key, Optional.empty());
                        }
                    }
                    return exprRes;
                } else {
                    return defaultNonExpr;
                }
            }
        } else if (size == 2) {
            Step startStep = exprArg.getStartStep();
            Step endStep = exprArg.getEndStep();
            if ((startStep instanceof SelectOneStep || startStep instanceof TraversalMapStep)
                    && (endStep instanceof PropertiesStep || endStep instanceof PropertyMapStep)) {
                Optional<String> propertyExpr =
                        getSubTraversalAsExpr((new ExprArg(Collections.singletonList(endStep))))
                                .getSingleExpr();
                if (!propertyExpr.isPresent()) {
                    return defaultNonExpr;
                }
                String selectKey = null;
                if (startStep
                        instanceof
                        SelectOneStep) { // select('a').values(..), select('a').valueMap(..)
                    selectKey =
                            (String) ((SelectOneStep) startStep).getScopeKeys().iterator().next();
                } else if (startStep
                        instanceof
                        TraversalMapStep) { // select(keys).values(..), select(values).valueMap(..)
                    ProjectOp mapOp =
                            (ProjectOp) StepTransformFactory.TRAVERSAL_MAP_STEP.apply(startStep);
                    List<Pair> pairs = (List<Pair>) mapOp.getExprWithAlias().get().applyArg();
                    String mapExpr = (String) pairs.get(0).getValue0();
                    selectKey = mapExpr.substring(1);
                }
                String expr = propertyExpr.get().replace("@", "@" + selectKey);
                return (new ExprResult()).addTagExpr(selectKey, Optional.of(expr));
            } else {
                return defaultNonExpr;
            }
        } else {
            return defaultNonExpr;
        }
    }