in gremlin-annotations/src/main/java/com/jetbrains/youtrackdb/internal/annotations/gremlin/dsl/GremlinDslProcessor.java [232:429]
private void generateTraversalSource(final Context ctx) throws IOException {
final var graphTraversalSourceElement = ctx.traversalSourceDslType;
final var traversalSourceClass = TypeSpec.classBuilder(ctx.traversalSourceClazz)
.addModifiers(Modifier.PUBLIC)
.superclass(TypeName.get(graphTraversalSourceElement.asType()));
// add the required constructors for instantiation
traversalSourceClass.addMethod(MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addParameter(Graph.class, "graph")
.addStatement("super($N)", "graph")
.build());
traversalSourceClass.addMethod(MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addParameter(Graph.class, "graph")
.addParameter(TraversalStrategies.class, "strategies")
.addStatement("super($N, $N)", "graph", "strategies")
.build());
traversalSourceClass.addMethod(MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addParameter(RemoteConnection.class, "connection")
.addStatement("super($N)", "connection")
.build());
// override methods to return the DSL TraversalSource. find GraphTraversalSource class somewhere in the hierarchy
final var tinkerPopsGraphTraversalSource = findClassAsElement(graphTraversalSourceElement,
GraphTraversalSource.class);
final Predicate<ExecutableElement> notGraphTraversalSourceReturnValues = e -> !(
e.getReturnType().getKind() == TypeKind.DECLARED
&& ((DeclaredType) e.getReturnType()).asElement().getSimpleName()
.contentEquals(GraphTraversalSource.class.getSimpleName()));
for (var elementOfGraphTraversalSource : findMethodsOfElement(
tinkerPopsGraphTraversalSource, notGraphTraversalSourceReturnValues)) {
// first copy/override methods that return a GraphTraversalSource so that we can instead return
// the DSL TraversalSource class.
traversalSourceClass.addMethod(
constructMethod(elementOfGraphTraversalSource, ctx.traversalSourceClassName, "",
Modifier.PUBLIC));
}
// override methods that return GraphTraversal that come from the user defined extension of GraphTraversal
if (!graphTraversalSourceElement.getSimpleName()
.contentEquals(GraphTraversalSource.class.getSimpleName())) {
final Predicate<ExecutableElement> notGraphTraversalReturnValues = e -> !(
e.getReturnType().getKind() == TypeKind.DECLARED
&& ((DeclaredType) e.getReturnType()).asElement().getSimpleName()
.contentEquals(GraphTraversal.class.getSimpleName()));
for (var templateMethod : findMethodsOfElement(graphTraversalSourceElement,
notGraphTraversalReturnValues)) {
final var methodToAdd = MethodSpec.methodBuilder(
templateMethod.getSimpleName().toString())
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class);
methodToAdd.addStatement("$T clone = this.clone()", ctx.traversalSourceClassName);
addMethodBody(methodToAdd, templateMethod, "return new $T (clone, super.$L(",
").asAdmin())",
ctx.defaultTraversalClassName, templateMethod.getSimpleName());
methodToAdd.returns(getReturnTypeDefinition(ctx.traversalClassName, templateMethod));
traversalSourceClass.addMethod(methodToAdd.build());
}
}
if (ctx.generateDefaultMethods) {
// override methods that return GraphTraversal
traversalSourceClass.addMethod(MethodSpec.methodBuilder("addV")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class)
.addStatement("$N clone = this.clone()", ctx.traversalSourceClazz)
.addStatement("clone.getBytecode().addStep($T.addV)", GraphTraversal.Symbols.class)
.addStatement("$N traversal = new $N(clone)", ctx.defaultTraversalClazz,
ctx.defaultTraversalClazz)
.addStatement("return ($T) traversal.asAdmin().addStep(new $T(traversal, (String) null))",
ctx.traversalClassName, AddVertexStartStep.class)
.returns(ParameterizedTypeName.get(ctx.traversalClassName, ClassName.get(Vertex.class),
ClassName.get(Vertex.class)))
.build());
traversalSourceClass.addMethod(MethodSpec.methodBuilder("addV")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class)
.addParameter(String.class, "label")
.addStatement("$N clone = this.clone()", ctx.traversalSourceClazz)
.addStatement("clone.getBytecode().addStep($T.addV, label)", GraphTraversal.Symbols.class)
.addStatement("$N traversal = new $N(clone)", ctx.defaultTraversalClazz,
ctx.defaultTraversalClazz)
.addStatement("return ($T) traversal.asAdmin().addStep(new $T(traversal, label))",
ctx.traversalClassName, AddVertexStartStep.class)
.returns(ParameterizedTypeName.get(ctx.traversalClassName, ClassName.get(Vertex.class),
ClassName.get(Vertex.class)))
.build());
traversalSourceClass.addMethod(MethodSpec.methodBuilder("addV")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class)
.addParameter(Traversal.class, "vertexLabelTraversal")
.addStatement("$N clone = this.clone()", ctx.traversalSourceClazz)
.addStatement("clone.getBytecode().addStep($T.addV, vertexLabelTraversal)",
GraphTraversal.Symbols.class)
.addStatement("$N traversal = new $N(clone)", ctx.defaultTraversalClazz,
ctx.defaultTraversalClazz)
.addStatement(
"return ($T) traversal.asAdmin().addStep(new $T(traversal, vertexLabelTraversal))",
ctx.traversalClassName, AddVertexStartStep.class)
.returns(ParameterizedTypeName.get(ctx.traversalClassName, ClassName.get(Vertex.class),
ClassName.get(Vertex.class)))
.build());
traversalSourceClass.addMethod(MethodSpec.methodBuilder("addE")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class)
.addParameter(String.class, "label")
.addStatement("$N clone = this.clone()", ctx.traversalSourceClazz)
.addStatement("clone.getBytecode().addStep($T.addE, label)", GraphTraversal.Symbols.class)
.addStatement("$N traversal = new $N(clone)", ctx.defaultTraversalClazz,
ctx.defaultTraversalClazz)
.addStatement("return ($T) traversal.asAdmin().addStep(new $T(traversal, label))",
ctx.traversalClassName, AddEdgeStartStep.class)
.returns(ParameterizedTypeName.get(ctx.traversalClassName, ClassName.get(Edge.class),
ClassName.get(Edge.class)))
.build());
traversalSourceClass.addMethod(MethodSpec.methodBuilder("addE")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class)
.addParameter(Traversal.class, "edgeLabelTraversal")
.addStatement("$N clone = this.clone()", ctx.traversalSourceClazz)
.addStatement("clone.getBytecode().addStep($T.addE, edgeLabelTraversal)",
GraphTraversal.Symbols.class)
.addStatement("$N traversal = new $N(clone)", ctx.defaultTraversalClazz,
ctx.defaultTraversalClazz)
.addStatement(
"return ($T) traversal.asAdmin().addStep(new $T(traversal, edgeLabelTraversal))",
ctx.traversalClassName, AddEdgeStartStep.class)
.returns(ParameterizedTypeName.get(ctx.traversalClassName, ClassName.get(Edge.class),
ClassName.get(Edge.class)))
.build());
traversalSourceClass.addMethod(MethodSpec.methodBuilder("V")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class)
.addParameter(Object[].class, "vertexIds")
.varargs(true)
.addStatement("final Object[] ids = null == vertexIds ? new Object[] { null } : vertexIds;")
.addStatement("$N clone = this.clone()", ctx.traversalSourceClazz)
.addStatement("clone.getBytecode().addStep($T.V, ids)",
GraphTraversal.Symbols.class)
.addStatement("$N traversal = new $N(clone)", ctx.defaultTraversalClazz,
ctx.defaultTraversalClazz)
.addStatement(
"return ($T) traversal.asAdmin().addStep(new $T(traversal, $T.class, true, ids))",
ctx.traversalClassName, GraphStep.class, Vertex.class)
.returns(ParameterizedTypeName.get(ctx.traversalClassName, ClassName.get(Vertex.class),
ClassName.get(Vertex.class)))
.build());
traversalSourceClass.addMethod(MethodSpec.methodBuilder("E")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class)
.addParameter(Object[].class, "edgeIds")
.varargs(true)
.addStatement("final Object[] ids = null == edgeIds ? new Object[] { null } : edgeIds;")
.addStatement("$N clone = this.clone()", ctx.traversalSourceClazz)
.addStatement("clone.getBytecode().addStep($T.E, ids)", GraphTraversal.Symbols.class)
.addStatement("$N traversal = new $N(clone)", ctx.defaultTraversalClazz,
ctx.defaultTraversalClazz)
.addStatement(
"return ($T) traversal.asAdmin().addStep(new $T(traversal, $T.class, true, ids))",
ctx.traversalClassName, GraphStep.class, Edge.class)
.returns(ParameterizedTypeName.get(ctx.traversalClassName, ClassName.get(Edge.class),
ClassName.get(Edge.class)))
.build());
traversalSourceClass.addMethod(MethodSpec.methodBuilder("inject")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class)
.addParameter(ArrayTypeName.of(TypeVariableName.get("S")), "starts")
.varargs(true)
.addTypeVariable(TypeVariableName.get("S"))
.addStatement("final S[] s = null == starts ? (S[]) new Object[] { null } : starts;")
.addStatement("$N clone = this.clone()", ctx.traversalSourceClazz)
.addStatement("clone.getBytecode().addStep($T.inject, s)",
GraphTraversal.Symbols.class)
.addStatement("$N traversal = new $N(clone)", ctx.defaultTraversalClazz,
ctx.defaultTraversalClazz)
.addStatement("return ($T) traversal.asAdmin().addStep(new $T(traversal, s))",
ctx.traversalClassName, InjectStep.class)
.returns(ParameterizedTypeName.get(ctx.traversalClassName, TypeVariableName.get("S"),
TypeVariableName.get("S")))
.build());
traversalSourceClass.addMethod(MethodSpec.methodBuilder("getAnonymousTraversalClass")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class)
.addStatement("return Optional.of(__.class)")
.returns(ParameterizedTypeName.get(ClassName.get(Optional.class),
ParameterizedTypeName.get(ClassName.get(Class.class),
WildcardTypeName.subtypeOf(Object.class))))
.build());
}
final var traversalSourceJavaFile = JavaFile.builder(ctx.packageName,
traversalSourceClass.build()).build();
traversalSourceJavaFile.writeTo(filer);
}