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;
}