protected Script produceScript()

in gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/DotNetTranslator.java [355:503]


        protected Script produceScript(final String traversalSource, final Bytecode o) {
            script.append(traversalSource);
            int instructionPosition = 0;
            for (final Bytecode.Instruction instruction : o.getInstructions()) {
                final String methodName = instruction.getOperator();
                // perhaps too many if/then conditions for specifying generics. doesnt' seem like there is a clear
                // way to refactor this more nicely though.
                //
                // inject() only has types when called with it when its used as a start step
                if (0 == instruction.getArguments().length) {
                    if (methodName.equals(GraphTraversal.Symbols.fold) && o.getSourceInstructions().size() + o.getStepInstructions().size() > 1 ||
                            (methodName.equals(GraphTraversal.Symbols.inject) && instructionPosition > 0))
                        script.append(".").append(resolveSymbol(methodName).replace("<object>", "")).append("()");
                    else if (stringMethodsWithScopes.contains(methodName))
                        // string functions with doesn't use generics if no scope is specified
                        script.append(".").append(resolveSymbol(methodName).replace("<object>", "")).append("()");
                    else
                        script.append(".").append(resolveSymbol(methodName)).append("()");
                } else {
                    if (methodsWithArgsNotNeedingGeneric.contains(methodName) ||
                            (methodName.equals(GraphTraversal.Symbols.inject) && (Arrays.stream(instruction.getArguments()).noneMatch(Objects::isNull) || instructionPosition > 0)) ||
                            (stringMethodsWithScopes.contains(methodName) && (Arrays.stream(instruction.getArguments()).noneMatch(EnumUtils.getEnumList(Scope.class)::contains))))
                        script.append(".").append(resolveSymbol(methodName).replace("<object>", "").replace("<object,object>", "")).append("(");
                    else
                        script.append(".").append(resolveSymbol(methodName)).append("(");

                    // have to special case withSack() because UnaryOperator and BinaryOperator signatures
                    // make it impossible for the interpreter to figure out which function to call. specifically we need
                    // to discern between:
                    //     withSack(A initialValue, UnaryOperator<A> splitOperator)
                    //     withSack(A initialValue, BinaryOperator<A> splitOperator)
                    // and:
                    //     withSack(Supplier<A> initialValue, UnaryOperator<A> mergeOperator)
                    //     withSack(Supplier<A> initialValue, BinaryOperator<A> mergeOperator)
                    if (methodName.equals(TraversalSource.Symbols.withSack) &&
                            instruction.getArguments().length == 2 && instruction.getArguments()[1] instanceof Lambda) {
                        final String castFirstArgTo = instruction.getArguments()[0] instanceof Lambda ? "ISupplier" : "";
                        final Lambda secondArg = (Lambda) instruction.getArguments()[1];
                        final String castSecondArgTo = secondArg.getLambdaArguments() == 1 ? "IUnaryOperator" : "IBinaryOperator";
                        if (!castFirstArgTo.isEmpty())
                            script.append(String.format("(%s) ", castFirstArgTo));
                        convertToScript(instruction.getArguments()[0]);
                        script.append(", (").append(castSecondArgTo).append(") ");
                        convertToScript(instruction.getArguments()[1]);
                        script.append(",");
                    } else if (methodName.equals(GraphTraversal.Symbols.mergeE) || methodName.equals(GraphTraversal.Symbols.mergeV)) {
                        // there must be at least one argument - if null go with Map
                        final Object instArg = instruction.getArguments()[0];
                        if (null == instArg) {
                            script.append("(IDictionary<object,object>) null");
                        } else {
                            if (instArg instanceof Traversal || instArg instanceof Bytecode) {
                                script.append("(ITraversal) ");
                            } else {
                                script.append("(IDictionary<object,object>) ");
                            }
                            convertToScript(instArg);
                        }
                        script.append(",");
                    } else if (methodName.equals(GraphTraversalSource.Symbols.tx)) {
                        final String command = resolveSymbol(instruction.getArguments()[0].toString());
                        script.append(").").append(command).append("()");
                    } else if (methodName.equals(GraphTraversal.Symbols.call)) {
                        // call()
                        // call(String)
                        // call(String, Map)
                        // call(String, Traversal)
                        // call(String, Map, Traversal)
                        final Object[] instArgs = instruction.getArguments();
                        if (instArgs.length > 0) {
                            // [0] always String
                            convertToScript(instArgs[0]);
                            script.append(",");
                        }
                        if (instArgs.length > 1) {
                            // [1] could be Map or Traversal
                            if (instArgs[1] instanceof Traversal || instArgs[1] instanceof Bytecode) {
                                script.append("(ITraversal) ");
                            } else {
                                script.append("(IDictionary<object,object>) ");
                            }
                            convertToScript(instArgs[1]);
                            script.append(",");
                        }
                        if (instArgs.length > 2) {
                            // [2] always Traversal
                            script.append("(ITraversal) ");
                            convertToScript(instArgs[2]);
                            script.append(",");
                        }
                    } else if (methodName.equals(GraphTraversal.Symbols.option) &&
                            instruction.getArguments().length == 2 && instruction.getArguments()[0] instanceof Merge) {
                        final Object[] instArgs = instruction.getArguments();
                        // trying to catch option(Merge,Traversal|Map)
                        convertToScript(instArgs[0]);
                        script.append(", ");
                        if (instArgs[1] instanceof Traversal || instArgs[1] instanceof Bytecode) {
                            script.append("(ITraversal) ");
                        } else {
                            script.append("(IDictionary<object,object>) ");
                        }
                        convertToScript(instArgs[1]);
                        script.append(",");
                    } else {
                        final Object[] instArgs = instruction.getArguments();
                        for (int idx = 0; idx < instArgs.length; idx++) {
                            final Object instArg = instArgs[idx];
                            // overloads might have trouble with null in calling the right one. add more as we find
                            // them i guess
                            if (null == instArg) {
                                if ((methodName.equals(GraphTraversal.Symbols.addV) && idx % 2 == 0) ||
                                        (methodName.equals(GraphTraversal.Symbols.hasLabel) && instArgs.length == 1 && idx == 0) ||
                                        (methodName.equals(GraphTraversal.Symbols.hasKey) && instArgs.length == 1 && idx == 0)) {
                                    script.append("(string) ");
                                } else if (methodName.equals(GraphTraversal.Symbols.hasValue) && idx == 0) {
                                    script.append("(object) ");
                                } else if (methodName.equals(GraphTraversal.Symbols.has)) {
                                    if (instArgs.length == 2) {
                                        if (null == instArgs[0] && idx == 0) {
                                            // need to avoid a null T accessor or else GraphTraversal gets
                                            // IllegalArgumentException and when called by way of reflection through
                                            // JavaTranslator
                                            script.append("(string)" );
                                        } else if ((instArgs[0] instanceof T || instArgs[0] instanceof String) && idx == 1) {
                                            script.append("(object) ");
                                        }
                                    } else if (instArgs.length == 3) {
                                        if ((instArgs[0] instanceof T || instArgs[0] instanceof String) && idx == 1) {
                                            script.append("(string) ");
                                        } else if ((instArgs[0] instanceof T || instArgs[0] instanceof String) && idx == 2) {
                                            script.append("(object) ");
                                        }
                                    }
                                } else if (methodName.equals(GraphTraversal.Symbols.property)) {
                                    if (instArgs[0] instanceof VertexProperty.Cardinality && instArgs.length == 3) {
                                        script.append("(object) ");
                                    }
                                }
                            }
                            convertToScript(instArg);
                            script.append(",");
                        }
                    }
                    script.setCharAtEnd(')');
                }
                instructionPosition++;
            }
            return script;
        }