Skip to content

Commit

Permalink
Remove hierarchy for clients
Browse files Browse the repository at this point in the history
  • Loading branch information
Duzhinsky committed Sep 21, 2023
1 parent 746b77b commit 285850f
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 150 deletions.
2 changes: 2 additions & 0 deletions generator/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ java {
val optionsJar = tasks.create<Jar>("optionsJar") {
archiveClassifier = "options"
from(sourceSets.main.get().proto)
from(project(":javaApi").sourceSets.main.get().java)
}

signing {
Expand Down Expand Up @@ -76,6 +77,7 @@ tasks.shadowJar {

dependencies {
implementation(project(":javapoet"))
implementation(project(":javaApi"))
implementation("com.google.protobuf:protobuf-java:3.21.9")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ private CodeBlock body(List<ParameterSpec> params) {
}
}
returnExpr = CodeBlock.of("$LStubCall(grpcRequest)", method.generatedName());
// todo research
if (!returnType.getTypeName().toString().equalsIgnoreCase("void")) {
if (returnType.getTypeName() != TypeName.VOID) {
returnExpr = CodeBlock.of("return $L", returnExpr);
}
return CodeBlock.builder().add(body).addStatement(returnExpr).build();
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@

import javax.annotation.processing.Generated;
import javax.lang.model.element.Modifier;
import java.util.List;
import java.util.stream.Stream;

public class ClientGenerator {

public static final String modificationNotice = """
The client was generated by protogen. If you want to add some logic, mark the service using
`option (protogen.abstract) = true;` and make your own class.
""";

static final ClassName managedChannelClass = ClassName.get("io.grpc", "ManagedChannel");

private final GenerationContext context;

private final Service service;
Expand All @@ -23,20 +31,19 @@ public class ClientGenerator {
public ClientGenerator(GenerationContext context, Service service) {
this.context = context;
this.service = service;
this.stubField = FieldSpec.builder(service.blockingStubClass(), "blockingStub", Modifier.PROTECTED, Modifier.FINAL).build();
this.stubField = FieldSpec.builder(service.blockingStubClass(), "blockingStub", Modifier.PRIVATE, Modifier.FINAL).build();
}

public TypeSpec generate() {
CodeBlock constructorsBody = CodeBlock.builder()
.addStatement("this.$N = $T.newBlockingStub($N)", stubField, service.stubClass(), BaseGrpcClient.channel)
.build();
// CodeBlock constructorsBody = CodeBlock.builder()
// .addStatement("this.$N = $T.newBlockingStub($N)", stubField, service.stubClass(), BaseGrpcClient.channel)
// .build();

TypeSpec.Builder builder = TypeSpec.classBuilder(service.generatedClientName())
.addModifiers(Modifier.PUBLIC)
.superclass(BaseGrpcClient.clazz)
.addField(stubField)
.addAnnotation(AnnotationSpec.builder(ClassName.get(Generated.class)).addMember("value", CodeBlock.of("\"protogen\"")).build())
.addMethods(BaseGrpcClient.generateConstructors(constructorsBody))
.addMethods(generateConstructors())
.addMethods(service.getMethods().stream()
.filter(Method::doGenerate)
.flatMap(this::generateRpcMethod)
Expand All @@ -45,39 +52,49 @@ public TypeSpec generate() {
if (service.isAbstract()) {
builder.addModifiers(Modifier.ABSTRACT);
} else {
builder.addJavadoc(CodeBlock.of(BaseGrpcClient.modificationNotice));
builder.addJavadoc(CodeBlock.of(modificationNotice));
}
return builder.build();
}

private List<MethodSpec> generateConstructors() {
return List.of(
MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addParameter(ParameterSpec.builder(managedChannelClass, "managedChannel").build())
.addCode(CodeBlock.of("this.blockingStub = $T.newBlockingStub($L);", service.stubClass(), "managedChannel"))
.build(),
MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addParameter(ParameterSpec.builder(service.blockingStubClass(), "stub").build())
.addCode(CodeBlock.of("this.blockingStub = stub;"))
.build()
);
}

private Stream<MethodSpec> generateRpcMethod(Method method) {
TypeModel returnType = getReturnType(method);
TypeModel returnType = getMethodReturnType(method);
TypeModel requestType = context.processType(method.getInputType());
MethodSpec publicApi = new ApiMethodGeneratorBase(context, method, returnType, requestType).generate();
MethodSpec grpcRequestMethod = new StubCallMethodGenerator(context, method, returnType, stubField).generate();
return Stream.of(grpcRequestMethod, publicApi);
}

protected TypeModel getReturnType(Method method) {
protected TypeModel getMethodReturnType(Method method) {
if (method.getOutputType().getFields().isEmpty()) {
return new TypeModel(TypeName.VOID);
}
var responseType = context.processType(method.getOutputType());
TypeModel type;
if (responseType != null) {
type = responseType;
} else if (method.doUnfoldResponse(responseType)) {
type = new UnfoldedType(context.processType(method.unfoldedResponseField()), method.getOutputType());
} else {
if (method.getOutputType().getFields().isEmpty()) {
type = new TypeModel(TypeName.VOID);
} else {
throw new IllegalStateException(("Unable to create a method returning %s because request consist of more than " +
"1 field and doesn't have a domain object.").formatted(method.getOutputType().getFullName()));
}
throw new IllegalStateException(("Unable to create a method returning %s because request consist of more than " +
"1 field and doesn't have a domain object.").formatted(method.getOutputType().getFullName()));
}
if (method.isOutputStreaming()) {
// // todo research why
if (type.getTypeName().toString().equalsIgnoreCase("void")) {
return type;
}
return new RepeatedType(type, method.getStreamToContainer());
}
return type;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.sudu.protogen.generator.client;

import com.squareup.javapoet.*;
import org.sudu.protogen.BaseClientUtils;
import org.sudu.protogen.descriptors.Method;
import org.sudu.protogen.descriptors.RepeatedContainer;
import org.sudu.protogen.generator.GenerationContext;
Expand All @@ -13,8 +14,11 @@
public class StubCallMethodGenerator {

protected final FieldSpec stubField;

private final GenerationContext context;

private final Method method;

private final TypeModel returnType;

public StubCallMethodGenerator(GenerationContext context, Method method, TypeModel returnType, FieldSpec stubField) {
Expand Down Expand Up @@ -59,11 +63,10 @@ private CodeBlock body() {
}

if (method.isNullable()) {
returnExpr = CodeBlock.of("nullifyIfNotFound(() -> $L)", returnExpr);
returnExpr = CodeBlock.of("$T.nullifyIfNotFound(() -> $L)", BaseClientUtils.class, returnExpr);
}

// todo research why
if (!returnType.getTypeName().toString().equalsIgnoreCase("void")) {
if (returnType.getTypeName() != TypeName.VOID) {
returnExpr = CodeBlock.of("return $L", returnExpr);
}
return CodeBlock.builder().add(body).addStatement(returnExpr).build();
Expand Down
5 changes: 5 additions & 0 deletions javaApi/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dependencies {
implementation("io.grpc:grpc-api:1.51.0")
testImplementation(platform("org.junit:junit-bom:5.9.1"))
testImplementation("org.junit.jupiter:junit-jupiter")
}
34 changes: 34 additions & 0 deletions javaApi/src/main/java/org/sudu/protogen/BaseClientUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.sudu.protogen;

import io.grpc.Status;
import io.grpc.StatusRuntimeException;
import org.jetbrains.annotations.NotNull;

import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;

public class BaseClientUtils {

public static <T> T nullifyIfNotFound(@NotNull Supplier<T> block) {
try {
return block.get();
} catch (StatusRuntimeException ex) {
if (ex.getStatus().getCode() == Status.NOT_FOUND.getCode()) {
return null;
}
throw ex;
}
}

public static <T> Collection<T> emptyIfNotFound(@NotNull Supplier<Collection<T>> block) {
try {
return block.get();
} catch (StatusRuntimeException ex) {
if (ex.getStatus().getCode() == Status.NOT_FOUND.getCode()) {
return List.of();
}
throw ex;
}
}
}
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ rootProject.name = "protogen"

include(
"javapoet",
"javaApi",
"generator",
"tests"
)
1 change: 1 addition & 0 deletions tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ protobuf {

dependencies {
protobuf(project(":generator"))
implementation(project(":javaApi"))
implementation("io.grpc:grpc-protobuf:1.51.0")
implementation("io.grpc:grpc-stub:1.51.0")
implementation("io.grpc:grpc-services:1.51.0")
Expand Down
76 changes: 0 additions & 76 deletions tests/src/main/java/org/sudu/api/BaseGrpcClient.java

This file was deleted.

0 comments on commit 285850f

Please sign in to comment.