in gremlin-annotations/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/GremlinDslProcessor.java [220:366]
private void generateTraversalSource(final Context ctx) throws IOException {
final TypeElement graphTraversalSourceElement = ctx.traversalSourceDslType;
final TypeSpec.Builder 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 Element 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 (ExecutableElement 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 (ExecutableElement templateMethod : findMethodsOfElement(graphTraversalSourceElement, notGraphTraversalReturnValues)) {
final MethodSpec.Builder 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.getGremlinLang().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.getGremlinLang().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.getGremlinLang().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.getGremlinLang().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.getGremlinLang().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("$N clone = this.clone()", ctx.traversalSourceClazz)
.addStatement("clone.getGremlinLang().addStep($T.V, vertexIds)", 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, vertexIds))", 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("$N clone = this.clone()", ctx.traversalSourceClazz)
.addStatement("clone.getGremlinLang().addStep($T.E, edgeIds)", 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, edgeIds))", 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("$N clone = this.clone()", ctx.traversalSourceClazz)
.addStatement("clone.getGremlinLang().addStep($T.inject, starts)", GraphTraversal.Symbols.class)
.addStatement("$N traversal = new $N(clone)", ctx.defaultTraversalClazz, ctx.defaultTraversalClazz)
.addStatement("return ($T) traversal.asAdmin().addStep(new $T(traversal, starts))", 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 JavaFile traversalSourceJavaFile = JavaFile.builder(ctx.packageName, traversalSourceClass.build()).build();
traversalSourceJavaFile.writeTo(filer);
}