From d1dab3c6a1aadb04b26771fef60709e6cad880b9 Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Fri, 2 Oct 2020 15:03:48 -0400 Subject: [PATCH 01/12] fix #1099: conjure-undertow correctly dealiases binary responses --- ...liasOptionalDoubleAliasedBinaryResult.java | 48 ++++++++++++++++ .../palantir/product/AliasedBinaryResult.java | 43 +++++++++++++++ .../product/DialogueEteBinaryEndpoints.java | 30 ++++++++++ .../product/DoubleAliasedBinaryResult.java | 43 +++++++++++++++ .../palantir/product/EteBinaryService.java | 4 ++ .../product/EteBinaryServiceAsync.java | 20 +++++++ .../product/EteBinaryServiceBlocking.java | 10 ++++ .../product/EteBinaryServiceEndpoints.java | 55 ++++++++++++++++++- .../product/EteBinaryServiceRetrofit.java | 4 ++ .../product/UndertowEteBinaryService.java | 5 ++ .../UndertowReturnValueClassNameVisitor.java | 24 +++++++- .../UndertowServiceHandlerGenerator.java | 42 ++++++++------ .../java/services/UndertowTypeFunctions.java | 31 +++++++---- .../conjure/java/EteBinaryResource.java | 6 ++ .../conjure/java/UndertowBinaryResource.java | 5 ++ .../src/test/resources/ete-binary.yml | 14 +++++ .../test/api/TestService.java.undertow | 2 +- .../test/api/TestService.java.undertow.prefix | 2 +- .../api/TestServiceEndpoints.java.undertow | 8 +-- .../TestServiceEndpoints.java.undertow.prefix | 8 +-- 20 files changed, 364 insertions(+), 40 deletions(-) create mode 100644 conjure-java-core/src/integrationInput/java/com/palantir/product/AliasOptionalDoubleAliasedBinaryResult.java create mode 100644 conjure-java-core/src/integrationInput/java/com/palantir/product/AliasedBinaryResult.java create mode 100644 conjure-java-core/src/integrationInput/java/com/palantir/product/DoubleAliasedBinaryResult.java diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/AliasOptionalDoubleAliasedBinaryResult.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/AliasOptionalDoubleAliasedBinaryResult.java new file mode 100644 index 000000000..3cd181f34 --- /dev/null +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/AliasOptionalDoubleAliasedBinaryResult.java @@ -0,0 +1,48 @@ +package com.palantir.product; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.palantir.logsafe.Preconditions; +import java.util.Optional; +import javax.annotation.Generated; +import javax.annotation.Nonnull; + +@Generated("com.palantir.conjure.java.types.AliasGenerator") +public final class AliasOptionalDoubleAliasedBinaryResult { + private final Optional value; + + private AliasOptionalDoubleAliasedBinaryResult(@Nonnull Optional value) { + this.value = Preconditions.checkNotNull(value, "value cannot be null"); + } + + private AliasOptionalDoubleAliasedBinaryResult() { + this(Optional.empty()); + } + + @JsonValue + public Optional get() { + return value; + } + + @Override + public String toString() { + return value.toString(); + } + + @Override + public boolean equals(Object other) { + return this == other + || (other instanceof AliasOptionalDoubleAliasedBinaryResult + && this.value.equals(((AliasOptionalDoubleAliasedBinaryResult) other).value)); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @JsonCreator + public static AliasOptionalDoubleAliasedBinaryResult of(@Nonnull Optional value) { + return new AliasOptionalDoubleAliasedBinaryResult(value); + } +} diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/AliasedBinaryResult.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/AliasedBinaryResult.java new file mode 100644 index 000000000..f0c206e5e --- /dev/null +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/AliasedBinaryResult.java @@ -0,0 +1,43 @@ +package com.palantir.product; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.palantir.logsafe.Preconditions; +import java.nio.ByteBuffer; +import javax.annotation.Generated; +import javax.annotation.Nonnull; + +@Generated("com.palantir.conjure.java.types.AliasGenerator") +public final class AliasedBinaryResult { + private final ByteBuffer value; + + private AliasedBinaryResult(@Nonnull ByteBuffer value) { + this.value = Preconditions.checkNotNull(value, "value cannot be null"); + } + + @JsonValue + public ByteBuffer get() { + return value; + } + + @Override + public String toString() { + return value.toString(); + } + + @Override + public boolean equals(Object other) { + return this == other + || (other instanceof AliasedBinaryResult && this.value.equals(((AliasedBinaryResult) other).value)); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @JsonCreator + public static AliasedBinaryResult of(@Nonnull ByteBuffer value) { + return new AliasedBinaryResult(value); + } +} diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/DialogueEteBinaryEndpoints.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/DialogueEteBinaryEndpoints.java index 19633e7db..7d66deaac 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/DialogueEteBinaryEndpoints.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/DialogueEteBinaryEndpoints.java @@ -164,6 +164,36 @@ public String endpointName() { return "getBinaryFailure"; } + @Override + public String version() { + return "1.2.3"; + } + }, + + getAliased { + private final PathTemplate pathTemplate = + PathTemplate.builder().fixed("binary").fixed("aliased").build(); + + @Override + public void renderPath(Map params, UrlBuilder url) { + pathTemplate.fill(params, url); + } + + @Override + public HttpMethod httpMethod() { + return HttpMethod.GET; + } + + @Override + public String serviceName() { + return "EteBinaryService"; + } + + @Override + public String endpointName() { + return "getAliased"; + } + @Override public String version() { return "1.2.3"; diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/DoubleAliasedBinaryResult.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/DoubleAliasedBinaryResult.java new file mode 100644 index 000000000..34589c61d --- /dev/null +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/DoubleAliasedBinaryResult.java @@ -0,0 +1,43 @@ +package com.palantir.product; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; +import com.palantir.logsafe.Preconditions; +import javax.annotation.Generated; +import javax.annotation.Nonnull; + +@Generated("com.palantir.conjure.java.types.AliasGenerator") +public final class DoubleAliasedBinaryResult { + private final AliasedBinaryResult value; + + private DoubleAliasedBinaryResult(@Nonnull AliasedBinaryResult value) { + this.value = Preconditions.checkNotNull(value, "value cannot be null"); + } + + @JsonValue + public AliasedBinaryResult get() { + return value; + } + + @Override + public String toString() { + return value.toString(); + } + + @Override + public boolean equals(Object other) { + return this == other + || (other instanceof DoubleAliasedBinaryResult + && this.value.equals(((DoubleAliasedBinaryResult) other).value)); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @JsonCreator + public static DoubleAliasedBinaryResult of(@Nonnull AliasedBinaryResult value) { + return new DoubleAliasedBinaryResult(value); + } +} diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryService.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryService.java index da7ebb039..e628cd601 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryService.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryService.java @@ -53,4 +53,8 @@ StreamingOutput postBinaryThrows( @Produces(MediaType.APPLICATION_OCTET_STREAM) StreamingOutput getBinaryFailure( @HeaderParam("Authorization") @NotNull AuthHeader authHeader, @QueryParam("numBytes") int numBytes); + + @GET + @Path("binary/aliased") + AliasOptionalDoubleAliasedBinaryResult getAliased(@HeaderParam("Authorization") @NotNull AuthHeader authHeader); } diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceAsync.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceAsync.java index 614eb6fd0..db1c8c015 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceAsync.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceAsync.java @@ -4,11 +4,13 @@ import com.palantir.dialogue.BinaryRequestBody; import com.palantir.dialogue.Channel; import com.palantir.dialogue.ConjureRuntime; +import com.palantir.dialogue.Deserializer; import com.palantir.dialogue.Endpoint; import com.palantir.dialogue.EndpointChannel; import com.palantir.dialogue.EndpointChannelFactory; import com.palantir.dialogue.PlainSerDe; import com.palantir.dialogue.Request; +import com.palantir.dialogue.TypeMarker; import com.palantir.tokens.auth.AuthHeader; import java.io.InputStream; import java.lang.Override; @@ -44,6 +46,11 @@ public interface EteBinaryServiceAsync { */ ListenableFuture getBinaryFailure(AuthHeader authHeader, int numBytes); + /** + * @apiNote {@code GET /binary/aliased} + */ + ListenableFuture getAliased(AuthHeader authHeader); + /** * Creates an asynchronous/non-blocking client for a EteBinaryService service. */ @@ -66,6 +73,12 @@ static EteBinaryServiceAsync of(EndpointChannelFactory _endpointChannelFactory, private final EndpointChannel getBinaryFailureChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getBinaryFailure); + private final EndpointChannel getAliasedChannel = + _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getAliased); + + private final Deserializer getAliasedDeserializer = + _runtime.bodySerDe().deserializer(new TypeMarker() {}); + @Override public ListenableFuture postBinary(AuthHeader authHeader, BinaryRequestBody body) { Request.Builder _request = Request.builder(); @@ -126,6 +139,13 @@ public ListenableFuture getBinaryFailure(AuthHeader authHeader, int _runtime.bodySerDe().inputStreamDeserializer()); } + @Override + public ListenableFuture getAliased(AuthHeader authHeader) { + Request.Builder _request = Request.builder(); + _request.putHeaderParams("Authorization", authHeader.toString()); + return _runtime.clients().call(getAliasedChannel, _request.build(), getAliasedDeserializer); + } + @Override public String toString() { return "EteBinaryServiceAsync{_endpointChannelFactory=" + _endpointChannelFactory + ", runtime=" diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceBlocking.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceBlocking.java index cd2d62095..1077bde03 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceBlocking.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceBlocking.java @@ -45,6 +45,11 @@ public interface EteBinaryServiceBlocking { @MustBeClosed InputStream getBinaryFailure(AuthHeader authHeader, int numBytes); + /** + * @apiNote {@code GET /binary/aliased} + */ + AliasOptionalDoubleAliasedBinaryResult getAliased(AuthHeader authHeader); + /** * Creates a synchronous/blocking client for a EteBinaryService service. */ @@ -76,6 +81,11 @@ public InputStream getBinaryFailure(AuthHeader authHeader, int numBytes) { return _runtime.clients().block(delegate.getBinaryFailure(authHeader, numBytes)); } + @Override + public AliasOptionalDoubleAliasedBinaryResult getAliased(AuthHeader authHeader) { + return _runtime.clients().block(delegate.getAliased(authHeader)); + } + @Override public String toString() { return "EteBinaryServiceBlocking{_endpointChannelFactory=" + _endpointChannelFactory + ", runtime=" diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceEndpoints.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceEndpoints.java index 81a04d40d..963e78365 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceEndpoints.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceEndpoints.java @@ -2,6 +2,8 @@ import com.palantir.conjure.java.undertow.lib.BinaryResponseBody; import com.palantir.conjure.java.undertow.lib.Endpoint; +import com.palantir.conjure.java.undertow.lib.Serializer; +import com.palantir.conjure.java.undertow.lib.TypeMarker; import com.palantir.conjure.java.undertow.lib.UndertowRuntime; import com.palantir.conjure.java.undertow.lib.UndertowService; import com.palantir.tokens.auth.AuthHeader; @@ -39,7 +41,8 @@ public List endpoints(UndertowRuntime runtime) { new PostBinaryThrowsEndpoint(runtime, delegate), new GetOptionalBinaryPresentEndpoint(runtime, delegate), new GetOptionalBinaryEmptyEndpoint(runtime, delegate), - new GetBinaryFailureEndpoint(runtime, delegate))); + new GetBinaryFailureEndpoint(runtime, delegate), + new GetAliasedEndpoint(runtime, delegate))); } private static final class PostBinaryEndpoint implements HttpHandler, Endpoint { @@ -270,4 +273,54 @@ public HttpHandler handler() { return this; } } + + private static final class GetAliasedEndpoint implements HttpHandler, Endpoint { + private final UndertowRuntime runtime; + + private final UndertowEteBinaryService delegate; + + private final Serializer> serializer; + + GetAliasedEndpoint(UndertowRuntime runtime, UndertowEteBinaryService delegate) { + this.runtime = runtime; + this.delegate = delegate; + this.serializer = runtime.bodySerDe().serializer(new TypeMarker>() {}); + } + + @Override + public void handleRequest(HttpServerExchange exchange) throws IOException { + AuthHeader authHeader = runtime.auth().header(exchange); + Optional result = delegate.getAliased(authHeader); + if (result.isPresent()) { + runtime.bodySerDe().serialize(result.get(), exchange); + } else { + exchange.setStatusCode(StatusCodes.NO_CONTENT); + } + } + + @Override + public HttpString method() { + return Methods.GET; + } + + @Override + public String template() { + return "/binary/aliased"; + } + + @Override + public String serviceName() { + return "EteBinaryService"; + } + + @Override + public String name() { + return "getAliased"; + } + + @Override + public HttpHandler handler() { + return this; + } + } } diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceRetrofit.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceRetrofit.java index 9aa71e153..b0fe87e27 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceRetrofit.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceRetrofit.java @@ -47,4 +47,8 @@ ListenableFuture postBinaryThrows( @Streaming ListenableFuture getBinaryFailure( @Header("Authorization") AuthHeader authHeader, @Query("numBytes") int numBytes); + + @GET("./binary/aliased") + @Headers({"hr-path-template: /binary/aliased", "Accept: application/json"}) + ListenableFuture getAliased(@Header("Authorization") AuthHeader authHeader); } diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/UndertowEteBinaryService.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/UndertowEteBinaryService.java index 11c22d149..5e4293f75 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/UndertowEteBinaryService.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/UndertowEteBinaryService.java @@ -33,4 +33,9 @@ public interface UndertowEteBinaryService { * @apiNote {@code GET /binary/failure} */ BinaryResponseBody getBinaryFailure(AuthHeader authHeader, int numBytes); + + /** + * @apiNote {@code GET /binary/aliased} + */ + Optional getAliased(AuthHeader authHeader); } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java index 9c9a8df52..fd23a66eb 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java @@ -26,6 +26,7 @@ import com.palantir.conjure.spec.OptionalType; import com.palantir.conjure.spec.PrimitiveType; import com.palantir.conjure.spec.SetType; +import com.palantir.conjure.spec.Type; import com.palantir.conjure.spec.TypeDefinition; import com.palantir.conjure.visitor.TypeVisitor; import com.squareup.javapoet.ClassName; @@ -37,8 +38,10 @@ public final class UndertowReturnValueClassNameVisitor implements ClassNameVisitor { private final ClassNameVisitor delegate; + private final List types; public UndertowReturnValueClassNameVisitor(List types, Options featureFlags) { + this.types = types; delegate = new DefaultClassNameVisitor(types, featureFlags); } @@ -57,9 +60,9 @@ public TypeName visitPrimitive(PrimitiveType primitiveType) { @Override public TypeName visitOptional(OptionalType optionalType) { - if (optionalType.getItemType().accept(TypeVisitor.IS_BINARY)) { - return ParameterizedTypeName.get( - ClassName.get(Optional.class), optionalType.getItemType().accept(this)); + Type dealiased = dealiasBinary(optionalType.getItemType()); + if (dealiased.accept(TypeVisitor.IS_BINARY)) { + return ParameterizedTypeName.get(ClassName.get(Optional.class), dealiased.accept(this)); } return delegate.visitOptional(optionalType); } @@ -81,6 +84,13 @@ public TypeName visitMap(MapType mapType) { @Override public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { + Optional type = UndertowTypeFunctions.getAliasedType(typeName, types); + if (type.isPresent()) { + Type dealiased = dealiasBinary(type.get()); + if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + return dealiased.accept(this); + } + } return delegate.visitReference(typeName); } @@ -88,4 +98,12 @@ public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { public TypeName visitExternal(ExternalReference externalReference) { return delegate.visitExternal(externalReference); } + + private Type dealiasBinary(Type input) { + Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(input, types); + if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + return dealiased; + } + return input; + } } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java index 3ec706f70..73744b5a5 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java @@ -452,31 +452,41 @@ private CodeBlock generateReturnValueCodeBlock( if (endpointDefinition.getReturns().isPresent()) { Type returnType = endpointDefinition.getReturns().get(); // optional<> handling - // TODO(ckozak): Support aliased binary types - if (UndertowTypeFunctions.toConjureTypeWithoutAliases(returnType, typeDefinitions) - .accept(TypeVisitor.IS_OPTIONAL)) { - CodeBlock serializer = UndertowTypeFunctions.isOptionalBinary(returnType) - ? CodeBlock.builder() - .add( - "$1N.bodySerDe().serialize($2N.get(), $3N)", - RUNTIME_VAR_NAME, - RESULT_VAR_NAME, - EXCHANGE_VAR_NAME) - .build() - : CodeBlock.builder() - .add("$1N.serialize($2N, $3N)", SERIALIZER_VAR_NAME, RESULT_VAR_NAME, EXCHANGE_VAR_NAME) - .build(); + Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(returnType, typeDefinitions); + if (dealiased.accept(TypeVisitor.IS_OPTIONAL)) { + CodeBlock serializer; + if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + serializer = CodeBlock.builder() + .add( + dealiased.accept(TypeVisitor.IS_BINARY) + ? "$1N.bodySerDe().serialize($2N, $3N)" + : "$1N.bodySerDe().serialize($2N.get(), $3N)", + RUNTIME_VAR_NAME, + RESULT_VAR_NAME, + EXCHANGE_VAR_NAME) + .build(); + } else { + serializer = CodeBlock.builder() + .add("$1N.serialize($2N, $3N)", SERIALIZER_VAR_NAME, RESULT_VAR_NAME, EXCHANGE_VAR_NAME) + .build(); + } // For optional<>: set response code to 204/NO_CONTENT if result is absent code.add(CodeBlock.builder() .beginControlFlow( - "if ($1L)", createIsOptionalPresentCall(returnType, RESULT_VAR_NAME, typeDefinitions)) + "if ($1L)", + createIsOptionalPresentCall( + UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased) + ? dealiased + : returnType, + RESULT_VAR_NAME, + typeDefinitions)) .addStatement(serializer) .nextControlFlow("else") .addStatement("$1N.setStatusCode($2T.NO_CONTENT)", EXCHANGE_VAR_NAME, StatusCodes.class) .endControlFlow() .build()); } else { - if (returnType.accept(TypeVisitor.IS_BINARY)) { + if (dealiased.accept(TypeVisitor.IS_BINARY)) { code.addStatement( "$1N.bodySerDe().serialize($2N, $3N)", RUNTIME_VAR_NAME, diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java index f1726200f..162935f44 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java @@ -60,6 +60,10 @@ public Boolean visitOptional(OptionalType value) { }); } + static boolean isBinaryOrOptionalBinary(Type type) { + return type.accept(TypeVisitor.IS_BINARY) || isOptionalBinary(type); + } + static boolean isCollectionType(Type type) { return type.accept(TypeVisitor.IS_LIST) || type.accept(TypeVisitor.IS_SET); } @@ -70,16 +74,7 @@ static boolean isCollectionType(Type type) { static Type getAliasedType(Type type, List typeDefinitions) { com.palantir.logsafe.Preconditions.checkArgument( isAliasType(type), "Expected an alias", SafeArg.of("type", type)); - return getAliasedType( - type.accept(new AbstractTypeVisitor() { - @Override - public com.palantir.conjure.spec.TypeName visitReference( - com.palantir.conjure.spec.TypeName value) { - return value; - } - }), - typeDefinitions) - .get(); + return maybeGetAliasedType(type, typeDefinitions).get(); } static Optional getAliasedType( @@ -101,6 +96,22 @@ static Optional getAliasedType( return Optional.empty(); } + // Dealias the given type if possible, otherwise returns empty. This may occur if the type cannot be + // located, or if it is not an alias. + static Optional maybeGetAliasedType(Type type, List typeDefinitions) { + if (!isAliasType(type)) { + return Optional.empty(); + } + return getAliasedType( + type.accept(new AbstractTypeVisitor() { + @Override + public com.palantir.conjure.spec.TypeName visitReference(com.palantir.conjure.spec.TypeName value) { + return value; + } + }), + typeDefinitions); + } + private static final ImmutableMap PRIMITIVE_TO_TYPE_NAME = new ImmutableMap.Builder< PrimitiveType.Value, String>() .put(PrimitiveType.Value.BEARERTOKEN, "BearerToken") diff --git a/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java b/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java index 9059b9f52..aec2c0fb4 100644 --- a/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java +++ b/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java @@ -22,6 +22,7 @@ import com.palantir.conjure.java.api.errors.ServiceException; import com.palantir.logsafe.SafeArg; import com.palantir.logsafe.exceptions.SafeRuntimeException; +import com.palantir.product.AliasOptionalDoubleAliasedBinaryResult; import com.palantir.product.EteBinaryService; import com.palantir.tokens.auth.AuthHeader; import java.io.IOException; @@ -71,4 +72,9 @@ public StreamingOutput getBinaryFailure(AuthHeader _authHeader, int numBytes) { throw new SafeRuntimeException("failure"); }; } + + @Override + public AliasOptionalDoubleAliasedBinaryResult getAliased(@NotNull AuthHeader authHeader) { + return AliasOptionalDoubleAliasedBinaryResult.of(Optional.empty()); + } } diff --git a/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowBinaryResource.java b/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowBinaryResource.java index 2eef7934e..e1599a5ff 100644 --- a/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowBinaryResource.java +++ b/conjure-java-core/src/test/java/com/palantir/conjure/java/UndertowBinaryResource.java @@ -71,4 +71,9 @@ public BinaryResponseBody getBinaryFailure(AuthHeader _authHeader, int numBytes) throw new SafeRuntimeException("failure"); }; } + + @Override + public Optional getAliased(AuthHeader _authHeader) { + return Optional.empty(); + } } diff --git a/conjure-java-core/src/test/resources/ete-binary.yml b/conjure-java-core/src/test/resources/ete-binary.yml index 0a65850cc..c89b7fac7 100644 --- a/conjure-java-core/src/test/resources/ete-binary.yml +++ b/conjure-java-core/src/test/resources/ete-binary.yml @@ -1,3 +1,14 @@ +types: + definitions: + default-package: com.palantir.product + objects: + AliasedBinaryResult: + alias: binary + DoubleAliasedBinaryResult: + alias: AliasedBinaryResult + AliasOptionalDoubleAliasedBinaryResult: + alias: optional + services: EteBinaryService: default-auth: header @@ -32,3 +43,6 @@ services: param-type: query docs: Throws an exception after partially writing a binary response. returns: binary + getAliased: + http: GET /aliased + returns: AliasOptionalDoubleAliasedBinaryResult diff --git a/conjure-java-core/src/test/resources/test/api/TestService.java.undertow b/conjure-java-core/src/test/resources/test/api/TestService.java.undertow index dab8d4890..1f084e380 100644 --- a/conjure-java-core/src/test/resources/test/api/TestService.java.undertow +++ b/conjure-java-core/src/test/resources/test/api/TestService.java.undertow @@ -46,7 +46,7 @@ public interface TestService { /** * @apiNote {@code GET /catalog/datasets/{datasetRid}/raw-aliased} */ - NestedAliasedBinary getAliasedRawData(AuthHeader authHeader, ResourceIdentifier datasetRid); + BinaryResponseBody getAliasedRawData(AuthHeader authHeader, ResourceIdentifier datasetRid); /** * @apiNote {@code GET /catalog/datasets/{datasetRid}/raw-maybe} diff --git a/conjure-java-core/src/test/resources/test/api/TestService.java.undertow.prefix b/conjure-java-core/src/test/resources/test/api/TestService.java.undertow.prefix index bd7a298c1..ebd2c8a28 100644 --- a/conjure-java-core/src/test/resources/test/api/TestService.java.undertow.prefix +++ b/conjure-java-core/src/test/resources/test/api/TestService.java.undertow.prefix @@ -46,7 +46,7 @@ public interface TestService { /** * @apiNote {@code GET /catalog/datasets/{datasetRid}/raw-aliased} */ - NestedAliasedBinary getAliasedRawData(AuthHeader authHeader, ResourceIdentifier datasetRid); + BinaryResponseBody getAliasedRawData(AuthHeader authHeader, ResourceIdentifier datasetRid); /** * @apiNote {@code GET /catalog/datasets/{datasetRid}/raw-maybe} diff --git a/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow b/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow index 91b04eda9..c5c590348 100644 --- a/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow +++ b/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow @@ -277,12 +277,12 @@ public final class TestServiceEndpoints implements UndertowService { private final TestService delegate; - private final Serializer serializer; + private final Serializer serializer; GetAliasedRawDataEndpoint(UndertowRuntime runtime, TestService delegate) { this.runtime = runtime; this.delegate = delegate; - this.serializer = runtime.bodySerDe().serializer(new TypeMarker() {}); + this.serializer = runtime.bodySerDe().serializer(new TypeMarker() {}); } @Override @@ -292,8 +292,8 @@ public final class TestServiceEndpoints implements UndertowService { exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters(); ResourceIdentifier datasetRid = runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid")); runtime.markers().param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange); - NestedAliasedBinary result = delegate.getAliasedRawData(authHeader, datasetRid); - serializer.serialize(result, exchange); + BinaryResponseBody result = delegate.getAliasedRawData(authHeader, datasetRid); + runtime.bodySerDe().serialize(result, exchange); } @Override diff --git a/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow.prefix b/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow.prefix index fdf398b5b..b8cdd4c39 100644 --- a/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow.prefix +++ b/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow.prefix @@ -277,12 +277,12 @@ public final class TestServiceEndpoints implements UndertowService { private final TestService delegate; - private final Serializer serializer; + private final Serializer serializer; GetAliasedRawDataEndpoint(UndertowRuntime runtime, TestService delegate) { this.runtime = runtime; this.delegate = delegate; - this.serializer = runtime.bodySerDe().serializer(new TypeMarker() {}); + this.serializer = runtime.bodySerDe().serializer(new TypeMarker() {}); } @Override @@ -292,8 +292,8 @@ public final class TestServiceEndpoints implements UndertowService { exchange.getAttachment(PathTemplateMatch.ATTACHMENT_KEY).getParameters(); ResourceIdentifier datasetRid = runtime.plainSerDe().deserializeRid(pathParams.get("datasetRid")); runtime.markers().param("com.palantir.redaction.Safe", "datasetRid", datasetRid, exchange); - NestedAliasedBinary result = delegate.getAliasedRawData(authHeader, datasetRid); - serializer.serialize(result, exchange); + BinaryResponseBody result = delegate.getAliasedRawData(authHeader, datasetRid); + runtime.bodySerDe().serialize(result, exchange); } @Override From df57d6274d2bead75286338e6fd41b6577558893 Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Fri, 2 Oct 2020 16:14:41 -0400 Subject: [PATCH 02/12] reduce diff --- .../java/services/UndertowTypeFunctions.java | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java index 162935f44..deec0a682 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java @@ -74,7 +74,16 @@ static boolean isCollectionType(Type type) { static Type getAliasedType(Type type, List typeDefinitions) { com.palantir.logsafe.Preconditions.checkArgument( isAliasType(type), "Expected an alias", SafeArg.of("type", type)); - return maybeGetAliasedType(type, typeDefinitions).get(); + return getAliasedType( + type.accept(new AbstractTypeVisitor() { + @Override + public com.palantir.conjure.spec.TypeName visitReference( + com.palantir.conjure.spec.TypeName value) { + return value; + } + }), + typeDefinitions) + .get(); } static Optional getAliasedType( @@ -96,22 +105,6 @@ static Optional getAliasedType( return Optional.empty(); } - // Dealias the given type if possible, otherwise returns empty. This may occur if the type cannot be - // located, or if it is not an alias. - static Optional maybeGetAliasedType(Type type, List typeDefinitions) { - if (!isAliasType(type)) { - return Optional.empty(); - } - return getAliasedType( - type.accept(new AbstractTypeVisitor() { - @Override - public com.palantir.conjure.spec.TypeName visitReference(com.palantir.conjure.spec.TypeName value) { - return value; - } - }), - typeDefinitions); - } - private static final ImmutableMap PRIMITIVE_TO_TYPE_NAME = new ImmutableMap.Builder< PrimitiveType.Value, String>() .put(PrimitiveType.Value.BEARERTOKEN, "BearerToken") From 7965ffab21dbdb142c9a63fd04ef86b20bdccee3 Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Fri, 2 Oct 2020 16:15:21 -0400 Subject: [PATCH 03/12] comment a bug --- .../test/java/com/palantir/conjure/java/EteBinaryResource.java | 1 + 1 file changed, 1 insertion(+) diff --git a/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java b/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java index aec2c0fb4..cd3a36cdd 100644 --- a/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java +++ b/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java @@ -75,6 +75,7 @@ public StreamingOutput getBinaryFailure(AuthHeader _authHeader, int numBytes) { @Override public AliasOptionalDoubleAliasedBinaryResult getAliased(@NotNull AuthHeader authHeader) { + // BUG: This should be dealiased to return Optional return AliasOptionalDoubleAliasedBinaryResult.of(Optional.empty()); } } From 00af756b3b69e1f033b72b132e0d720cd8be6a7b Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Fri, 2 Oct 2020 19:03:48 +0000 Subject: [PATCH 04/12] Add generated changelog entries --- changelog/@unreleased/pr-1102.v2.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/@unreleased/pr-1102.v2.yml diff --git a/changelog/@unreleased/pr-1102.v2.yml b/changelog/@unreleased/pr-1102.v2.yml new file mode 100644 index 000000000..ca5ea0a2f --- /dev/null +++ b/changelog/@unreleased/pr-1102.v2.yml @@ -0,0 +1,5 @@ +type: fix +fix: + description: conjure-undertow correctly dealiases binary response types + links: + - https://github.com/palantir/conjure-java/pull/1102 From f0053fb4558500bd205741f4159fb13392a01dfa Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Mon, 5 Oct 2020 09:57:16 -0400 Subject: [PATCH 05/12] properly dealias request bodies --- .../product/EteBinaryServiceEndpoints.java | 5 ---- .../UndertowRequestBodyClassNameVisitor.java | 26 ++++++++++++++++++- .../UndertowServiceHandlerGenerator.java | 14 +++++++--- .../test/api/TestService.java.undertow | 3 +-- .../test/api/TestService.java.undertow.prefix | 3 +-- .../api/TestServiceEndpoints.java.undertow | 9 +------ .../TestServiceEndpoints.java.undertow.prefix | 9 +------ 7 files changed, 39 insertions(+), 30 deletions(-) diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceEndpoints.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceEndpoints.java index 963e78365..3a6ec70df 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceEndpoints.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceEndpoints.java @@ -2,8 +2,6 @@ import com.palantir.conjure.java.undertow.lib.BinaryResponseBody; import com.palantir.conjure.java.undertow.lib.Endpoint; -import com.palantir.conjure.java.undertow.lib.Serializer; -import com.palantir.conjure.java.undertow.lib.TypeMarker; import com.palantir.conjure.java.undertow.lib.UndertowRuntime; import com.palantir.conjure.java.undertow.lib.UndertowService; import com.palantir.tokens.auth.AuthHeader; @@ -279,12 +277,9 @@ private static final class GetAliasedEndpoint implements HttpHandler, Endpoint { private final UndertowEteBinaryService delegate; - private final Serializer> serializer; - GetAliasedEndpoint(UndertowRuntime runtime, UndertowEteBinaryService delegate) { this.runtime = runtime; this.delegate = delegate; - this.serializer = runtime.bodySerDe().serializer(new TypeMarker>() {}); } @Override diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowRequestBodyClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowRequestBodyClassNameVisitor.java index ec8aa49e0..3dc0ae1a9 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowRequestBodyClassNameVisitor.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowRequestBodyClassNameVisitor.java @@ -25,17 +25,23 @@ import com.palantir.conjure.spec.OptionalType; import com.palantir.conjure.spec.PrimitiveType; import com.palantir.conjure.spec.SetType; +import com.palantir.conjure.spec.Type; import com.palantir.conjure.spec.TypeDefinition; +import com.palantir.conjure.visitor.TypeVisitor; import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import java.io.InputStream; import java.util.List; +import java.util.Optional; public final class UndertowRequestBodyClassNameVisitor implements ClassNameVisitor { private final ClassNameVisitor delegate; + private final List types; public UndertowRequestBodyClassNameVisitor(List types, Options options) { + this.types = types; delegate = new DefaultClassNameVisitor(types, options); } @@ -54,7 +60,10 @@ public TypeName visitPrimitive(PrimitiveType primitiveType) { @Override public TypeName visitOptional(OptionalType optionalType) { - // TODO(ckozak): Support this? I don't know that jersey does. + Type dealiased = dealiasBinary(optionalType.getItemType()); + if (dealiased.accept(TypeVisitor.IS_BINARY)) { + return ParameterizedTypeName.get(ClassName.get(Optional.class), dealiased.accept(this)); + } return delegate.visitOptional(optionalType); } @@ -75,6 +84,13 @@ public TypeName visitMap(MapType mapType) { @Override public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { + Optional type = UndertowTypeFunctions.getAliasedType(typeName, types); + if (type.isPresent()) { + Type dealiased = dealiasBinary(type.get()); + if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + return dealiased.accept(this); + } + } return delegate.visitReference(typeName); } @@ -82,4 +98,12 @@ public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { public TypeName visitExternal(ExternalReference externalReference) { return delegate.visitExternal(externalReference); } + + private Type dealiasBinary(Type input) { + Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(input, types); + if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + return dealiased; + } + return input; + } } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java index 73744b5a5..f1ad6e3d0 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java @@ -240,7 +240,12 @@ private TypeSpec generateEndpointHandler( getBodyParamTypeArgument(endpointDefinition.getArgs()) .map(ArgumentDefinition::getType) // Filter out binary data - .flatMap(type -> type.accept(TypeVisitor.IS_BINARY) ? Optional.empty() : Optional.of(type)) + .flatMap(type -> { + Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(type, typeDefinitions); + return UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased) + ? Optional.empty() + : Optional.of(type); + }) .map(typeMapper::getClassName) .map(TypeName::box) .map(this::immutableCollection) @@ -257,7 +262,8 @@ private TypeSpec generateEndpointHandler( }); endpointDefinition.getReturns().ifPresent(returnType -> { - if (!UndertowTypeFunctions.isOptionalBinary(returnType) && !returnType.accept(TypeVisitor.IS_BINARY)) { + Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(returnType, typeDefinitions); + if (!UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { TypeName typeName = returnTypeMapper.getClassName(returnType).box(); TypeName type = ParameterizedTypeName.get(ClassName.get(Serializer.class), typeName); endpointBuilder.addField(FieldSpec.builder(type, SERIALIZER_VAR_NAME, Modifier.PRIVATE, Modifier.FINAL) @@ -381,8 +387,8 @@ private CodeBlock endpointInvocation( // body parameter getBodyParamTypeArgument(endpointDefinition.getArgs()).ifPresent(bodyParam -> { String paramName = sanitizeVarName(bodyParam.getArgName().get(), endpointDefinition); - if (bodyParam.getType().accept(TypeVisitor.IS_BINARY)) { - // TODO(ckozak): Support aliased and optional binary types + Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(bodyParam.getType(), typeDefinitions); + if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { code.addStatement( "$1T $2N = $3N.bodySerDe().deserializeInputStream($4N)", InputStream.class, diff --git a/conjure-java-core/src/test/resources/test/api/TestService.java.undertow b/conjure-java-core/src/test/resources/test/api/TestService.java.undertow index 1f084e380..829a824ae 100644 --- a/conjure-java-core/src/test/resources/test/api/TestService.java.undertow +++ b/conjure-java-core/src/test/resources/test/api/TestService.java.undertow @@ -3,7 +3,6 @@ package com.palantir.another; import com.palantir.conjure.java.undertow.lib.BinaryResponseBody; import com.palantir.product.AliasedString; import com.palantir.product.CreateDatasetRequest; -import com.palantir.product.NestedAliasedBinary; import com.palantir.product.datasets.BackingFileSystem; import com.palantir.product.datasets.Dataset; import com.palantir.ri.ResourceIdentifier; @@ -66,7 +65,7 @@ public interface TestService { /** * @apiNote {@code POST /catalog/datasets/upload-raw-aliased} */ - void uploadAliasedRawData(AuthHeader authHeader, NestedAliasedBinary input); + void uploadAliasedRawData(AuthHeader authHeader, InputStream input); /** * @apiNote {@code GET /catalog/datasets/{datasetRid}/branches} diff --git a/conjure-java-core/src/test/resources/test/api/TestService.java.undertow.prefix b/conjure-java-core/src/test/resources/test/api/TestService.java.undertow.prefix index ebd2c8a28..7836eefbd 100644 --- a/conjure-java-core/src/test/resources/test/api/TestService.java.undertow.prefix +++ b/conjure-java-core/src/test/resources/test/api/TestService.java.undertow.prefix @@ -12,7 +12,6 @@ import java.util.Set; import javax.annotation.Generated; import test.prefix.com.palantir.product.AliasedString; import test.prefix.com.palantir.product.CreateDatasetRequest; -import test.prefix.com.palantir.product.NestedAliasedBinary; import test.prefix.com.palantir.product.datasets.BackingFileSystem; import test.prefix.com.palantir.product.datasets.Dataset; @@ -66,7 +65,7 @@ public interface TestService { /** * @apiNote {@code POST /catalog/datasets/upload-raw-aliased} */ - void uploadAliasedRawData(AuthHeader authHeader, NestedAliasedBinary input); + void uploadAliasedRawData(AuthHeader authHeader, InputStream input); /** * @apiNote {@code GET /catalog/datasets/{datasetRid}/branches} diff --git a/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow b/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow index c5c590348..23b4e5a1a 100644 --- a/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow +++ b/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow @@ -9,7 +9,6 @@ import com.palantir.conjure.java.undertow.lib.UndertowRuntime; import com.palantir.conjure.java.undertow.lib.UndertowService; import com.palantir.product.AliasedString; import com.palantir.product.CreateDatasetRequest; -import com.palantir.product.NestedAliasedBinary; import com.palantir.product.datasets.BackingFileSystem; import com.palantir.product.datasets.Dataset; import com.palantir.ri.ResourceIdentifier; @@ -277,12 +276,9 @@ public final class TestServiceEndpoints implements UndertowService { private final TestService delegate; - private final Serializer serializer; - GetAliasedRawDataEndpoint(UndertowRuntime runtime, TestService delegate) { this.runtime = runtime; this.delegate = delegate; - this.serializer = runtime.bodySerDe().serializer(new TypeMarker() {}); } @Override @@ -474,18 +470,15 @@ public final class TestServiceEndpoints implements UndertowService { private final TestService delegate; - private final Deserializer deserializer; - UploadAliasedRawDataEndpoint(UndertowRuntime runtime, TestService delegate) { this.runtime = runtime; this.delegate = delegate; - this.deserializer = runtime.bodySerDe().deserializer(new TypeMarker() {}); } @Override public void handleRequest(HttpServerExchange exchange) throws IOException { AuthHeader authHeader = runtime.auth().header(exchange); - NestedAliasedBinary input = deserializer.deserialize(exchange); + InputStream input = runtime.bodySerDe().deserializeInputStream(exchange); delegate.uploadAliasedRawData(authHeader, input); exchange.setStatusCode(StatusCodes.NO_CONTENT); } diff --git a/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow.prefix b/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow.prefix index b8cdd4c39..40c0e2e3f 100644 --- a/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow.prefix +++ b/conjure-java-core/src/test/resources/test/api/TestServiceEndpoints.java.undertow.prefix @@ -30,7 +30,6 @@ import java.util.Set; import javax.annotation.Generated; import test.prefix.com.palantir.product.AliasedString; import test.prefix.com.palantir.product.CreateDatasetRequest; -import test.prefix.com.palantir.product.NestedAliasedBinary; import test.prefix.com.palantir.product.datasets.BackingFileSystem; import test.prefix.com.palantir.product.datasets.Dataset; @@ -277,12 +276,9 @@ public final class TestServiceEndpoints implements UndertowService { private final TestService delegate; - private final Serializer serializer; - GetAliasedRawDataEndpoint(UndertowRuntime runtime, TestService delegate) { this.runtime = runtime; this.delegate = delegate; - this.serializer = runtime.bodySerDe().serializer(new TypeMarker() {}); } @Override @@ -474,18 +470,15 @@ public final class TestServiceEndpoints implements UndertowService { private final TestService delegate; - private final Deserializer deserializer; - UploadAliasedRawDataEndpoint(UndertowRuntime runtime, TestService delegate) { this.runtime = runtime; this.delegate = delegate; - this.deserializer = runtime.bodySerDe().deserializer(new TypeMarker() {}); } @Override public void handleRequest(HttpServerExchange exchange) throws IOException { AuthHeader authHeader = runtime.auth().header(exchange); - NestedAliasedBinary input = deserializer.deserialize(exchange); + InputStream input = runtime.bodySerDe().deserializeInputStream(exchange); delegate.uploadAliasedRawData(authHeader, input); exchange.setStatusCode(StatusCodes.NO_CONTENT); } From b8b162d45fb19fcec693264f37cb85d3d2c4ae6e Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Mon, 5 Oct 2020 12:37:04 -0400 Subject: [PATCH 06/12] apply fixes to dialogue as well --- .../product/EteBinaryServiceAsync.java | 15 +- .../product/EteBinaryServiceBlocking.java | 4 +- .../UndertowRequestBodyClassNameVisitor.java | 9 +- .../UndertowReturnValueClassNameVisitor.java | 9 +- .../UndertowServiceHandlerGenerator.java | 44 ++-- .../java/services/UndertowTypeFunctions.java | 185 +--------------- .../conjure/java/util/TypeFunctions.java | 208 ++++++++++++++++++ .../java/visitor/DialogueClassVisitor.java | 42 ++-- 8 files changed, 274 insertions(+), 242 deletions(-) create mode 100644 conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceAsync.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceAsync.java index db1c8c015..f5b42c391 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceAsync.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceAsync.java @@ -4,13 +4,11 @@ import com.palantir.dialogue.BinaryRequestBody; import com.palantir.dialogue.Channel; import com.palantir.dialogue.ConjureRuntime; -import com.palantir.dialogue.Deserializer; import com.palantir.dialogue.Endpoint; import com.palantir.dialogue.EndpointChannel; import com.palantir.dialogue.EndpointChannelFactory; import com.palantir.dialogue.PlainSerDe; import com.palantir.dialogue.Request; -import com.palantir.dialogue.TypeMarker; import com.palantir.tokens.auth.AuthHeader; import java.io.InputStream; import java.lang.Override; @@ -49,7 +47,7 @@ public interface EteBinaryServiceAsync { /** * @apiNote {@code GET /binary/aliased} */ - ListenableFuture getAliased(AuthHeader authHeader); + ListenableFuture> getAliased(AuthHeader authHeader); /** * Creates an asynchronous/non-blocking client for a EteBinaryService service. @@ -76,9 +74,6 @@ static EteBinaryServiceAsync of(EndpointChannelFactory _endpointChannelFactory, private final EndpointChannel getAliasedChannel = _endpointChannelFactory.endpoint(DialogueEteBinaryEndpoints.getAliased); - private final Deserializer getAliasedDeserializer = - _runtime.bodySerDe().deserializer(new TypeMarker() {}); - @Override public ListenableFuture postBinary(AuthHeader authHeader, BinaryRequestBody body) { Request.Builder _request = Request.builder(); @@ -140,10 +135,14 @@ public ListenableFuture getBinaryFailure(AuthHeader authHeader, int } @Override - public ListenableFuture getAliased(AuthHeader authHeader) { + public ListenableFuture> getAliased(AuthHeader authHeader) { Request.Builder _request = Request.builder(); _request.putHeaderParams("Authorization", authHeader.toString()); - return _runtime.clients().call(getAliasedChannel, _request.build(), getAliasedDeserializer); + return _runtime.clients() + .call( + getAliasedChannel, + _request.build(), + _runtime.bodySerDe().optionalInputStreamDeserializer()); } @Override diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceBlocking.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceBlocking.java index 1077bde03..3e62ac828 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceBlocking.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceBlocking.java @@ -48,7 +48,7 @@ public interface EteBinaryServiceBlocking { /** * @apiNote {@code GET /binary/aliased} */ - AliasOptionalDoubleAliasedBinaryResult getAliased(AuthHeader authHeader); + Optional getAliased(AuthHeader authHeader); /** * Creates a synchronous/blocking client for a EteBinaryService service. @@ -82,7 +82,7 @@ public InputStream getBinaryFailure(AuthHeader authHeader, int numBytes) { } @Override - public AliasOptionalDoubleAliasedBinaryResult getAliased(AuthHeader authHeader) { + public Optional getAliased(AuthHeader authHeader) { return _runtime.clients().block(delegate.getAliased(authHeader)); } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowRequestBodyClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowRequestBodyClassNameVisitor.java index 3dc0ae1a9..a615dc850 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowRequestBodyClassNameVisitor.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowRequestBodyClassNameVisitor.java @@ -19,6 +19,7 @@ import com.palantir.conjure.java.Options; import com.palantir.conjure.java.types.ClassNameVisitor; import com.palantir.conjure.java.types.DefaultClassNameVisitor; +import com.palantir.conjure.java.util.TypeFunctions; import com.palantir.conjure.spec.ExternalReference; import com.palantir.conjure.spec.ListType; import com.palantir.conjure.spec.MapType; @@ -84,10 +85,10 @@ public TypeName visitMap(MapType mapType) { @Override public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { - Optional type = UndertowTypeFunctions.getAliasedType(typeName, types); + Optional type = TypeFunctions.getAliasedType(typeName, types); if (type.isPresent()) { Type dealiased = dealiasBinary(type.get()); - if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { return dealiased.accept(this); } } @@ -100,8 +101,8 @@ public TypeName visitExternal(ExternalReference externalReference) { } private Type dealiasBinary(Type input) { - Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(input, types); - if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(input, types); + if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { return dealiased; } return input; diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java index fd23a66eb..a3825ec5c 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java @@ -20,6 +20,7 @@ import com.palantir.conjure.java.types.ClassNameVisitor; import com.palantir.conjure.java.types.DefaultClassNameVisitor; import com.palantir.conjure.java.undertow.lib.BinaryResponseBody; +import com.palantir.conjure.java.util.TypeFunctions; import com.palantir.conjure.spec.ExternalReference; import com.palantir.conjure.spec.ListType; import com.palantir.conjure.spec.MapType; @@ -84,10 +85,10 @@ public TypeName visitMap(MapType mapType) { @Override public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { - Optional type = UndertowTypeFunctions.getAliasedType(typeName, types); + Optional type = TypeFunctions.getAliasedType(typeName, types); if (type.isPresent()) { Type dealiased = dealiasBinary(type.get()); - if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { return dealiased.accept(this); } } @@ -100,8 +101,8 @@ public TypeName visitExternal(ExternalReference externalReference) { } private Type dealiasBinary(Type input) { - Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(input, types); - if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(input, types); + if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { return dealiased; } return input; diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java index f1ad6e3d0..857967ee8 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java @@ -35,6 +35,7 @@ import com.palantir.conjure.java.util.JavaNameSanitizer; import com.palantir.conjure.java.util.Packages; import com.palantir.conjure.java.util.ParameterOrder; +import com.palantir.conjure.java.util.TypeFunctions; import com.palantir.conjure.java.visitor.DefaultTypeVisitor; import com.palantir.conjure.java.visitor.MoreVisitors; import com.palantir.conjure.spec.ArgumentDefinition; @@ -241,10 +242,8 @@ private TypeSpec generateEndpointHandler( .map(ArgumentDefinition::getType) // Filter out binary data .flatMap(type -> { - Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(type, typeDefinitions); - return UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased) - ? Optional.empty() - : Optional.of(type); + Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(type, typeDefinitions); + return TypeFunctions.isBinaryOrOptionalBinary(dealiased) ? Optional.empty() : Optional.of(type); }) .map(typeMapper::getClassName) .map(TypeName::box) @@ -262,8 +261,8 @@ private TypeSpec generateEndpointHandler( }); endpointDefinition.getReturns().ifPresent(returnType -> { - Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(returnType, typeDefinitions); - if (!UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(returnType, typeDefinitions); + if (!TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { TypeName typeName = returnTypeMapper.getClassName(returnType).box(); TypeName type = ParameterizedTypeName.get(ClassName.get(Serializer.class), typeName); endpointBuilder.addField(FieldSpec.builder(type, SERIALIZER_VAR_NAME, Modifier.PRIVATE, Modifier.FINAL) @@ -387,8 +386,8 @@ private CodeBlock endpointInvocation( // body parameter getBodyParamTypeArgument(endpointDefinition.getArgs()).ifPresent(bodyParam -> { String paramName = sanitizeVarName(bodyParam.getArgName().get(), endpointDefinition); - Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(bodyParam.getType(), typeDefinitions); - if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(bodyParam.getType(), typeDefinitions); + if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { code.addStatement( "$1T $2N = $3N.bodySerDe().deserializeInputStream($4N)", InputStream.class, @@ -458,10 +457,10 @@ private CodeBlock generateReturnValueCodeBlock( if (endpointDefinition.getReturns().isPresent()) { Type returnType = endpointDefinition.getReturns().get(); // optional<> handling - Type dealiased = UndertowTypeFunctions.toConjureTypeWithoutAliases(returnType, typeDefinitions); + Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(returnType, typeDefinitions); if (dealiased.accept(TypeVisitor.IS_OPTIONAL)) { CodeBlock serializer; - if (UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { serializer = CodeBlock.builder() .add( dealiased.accept(TypeVisitor.IS_BINARY) @@ -481,9 +480,7 @@ private CodeBlock generateReturnValueCodeBlock( .beginControlFlow( "if ($1L)", createIsOptionalPresentCall( - UndertowTypeFunctions.isBinaryOrOptionalBinary(dealiased) - ? dealiased - : returnType, + TypeFunctions.isBinaryOrOptionalBinary(dealiased) ? dealiased : returnType, RESULT_VAR_NAME, typeDefinitions)) .addStatement(serializer) @@ -682,13 +679,12 @@ private CodeBlock generateParameterCodeBlock( return CodeBlocks.of(endpoint.getArgs().stream() .filter(param -> param.getParamType().accept(paramTypeVisitor)) .map(arg -> { - Type normalizedType = - UndertowTypeFunctions.toConjureTypeWithoutAliases(arg.getType(), typeDefinitions); + Type normalizedType = TypeFunctions.toConjureTypeWithoutAliases(arg.getType(), typeDefinitions); String paramName = sanitizeVarName(arg.getArgName().get(), endpoint); final CodeBlock retrieveParam; if (normalizedType.equals(arg.getType()) // Collections of alias types are handled the same way as external imports - || UndertowTypeFunctions.isCollectionType(arg.getType())) { + || TypeFunctions.isCollectionType(arg.getType())) { // type is not an alias or optional of an alias retrieveParam = decodePlainParameterCodeBlock( arg.getType(), typeMapper, paramName, paramsVarName, toParamId.apply(arg)); @@ -843,9 +839,9 @@ private static CodeBlock createIsOptionalPresentCall( if (inType.accept(TypeVisitor.IS_OPTIONAL)) { // current type is optional type: call isPresent return CodeBlock.of("$1N.isPresent()", varName); - } else if (UndertowTypeFunctions.isAliasType(inType)) { + } else if (TypeFunctions.isAliasType(inType)) { // current type is an alias type: call "get()" to resolve alias and generate recursively on aliased type - Type aliasedType = UndertowTypeFunctions.getAliasedType(inType, typeDefinitions); + Type aliasedType = TypeFunctions.getAliasedType(inType, typeDefinitions); return createIsOptionalPresentCall(aliasedType, varName + ".get()", typeDefinitions); } else { throw new IllegalArgumentException("inType must be either an optional or alias type, was " + inType); @@ -886,7 +882,7 @@ private static CodeBlock createConstructorForTypeWithReference( // * optional // * optional // * alias that follows one of these rules (recursive definition) - Type aliasedType = UndertowTypeFunctions.getAliasedType(inType, typeDefinitions); + Type aliasedType = TypeFunctions.getAliasedType(inType, typeDefinitions); if (aliasedType.accept(TypeVisitor.IS_PRIMITIVE) || aliasedType.accept(MoreVisitors.IS_EXTERNAL)) { // primitive ofContent = CodeBlock.of("$1N", decodedVarName); @@ -915,14 +911,12 @@ private static CodeBlock createConstructorForTypeWithReference( private static String deserializeFunctionName(Type type) { if (type.accept(TypeVisitor.IS_PRIMITIVE)) { - return "deserialize" - + UndertowTypeFunctions.primitiveTypeName(type.accept(UndertowTypeFunctions.PRIMITIVE_VISITOR)); + return "deserialize" + TypeFunctions.primitiveTypeName(type.accept(TypeFunctions.PRIMITIVE_VISITOR)); } else if (type.accept(TypeVisitor.IS_OPTIONAL) && type.accept(TypeVisitor.OPTIONAL).getItemType().accept(TypeVisitor.IS_PRIMITIVE)) { - PrimitiveType innerPrimitiveType = type.accept(UndertowTypeFunctions.OPTIONAL_VISITOR) - .getItemType() - .accept(UndertowTypeFunctions.PRIMITIVE_VISITOR); - return "deserializeOptional" + UndertowTypeFunctions.primitiveTypeName(innerPrimitiveType); + PrimitiveType innerPrimitiveType = + type.accept(TypeFunctions.OPTIONAL_VISITOR).getItemType().accept(TypeFunctions.PRIMITIVE_VISITOR); + return "deserializeOptional" + TypeFunctions.primitiveTypeName(innerPrimitiveType); } else if (type.accept(TypeVisitor.IS_LIST) && type.accept(TypeVisitor.LIST).getItemType().accept(TypeVisitor.IS_PRIMITIVE)) { Type subtype = type.accept(TypeVisitor.LIST).getItemType(); diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java index deec0a682..2c4318ac6 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowTypeFunctions.java @@ -1,5 +1,5 @@ /* - * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * (c) Copyright 2020 Palantir Technologies Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,199 +17,16 @@ package com.palantir.conjure.java.services; import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.ListenableFuture; import com.palantir.conjure.java.Options; import com.palantir.conjure.java.types.TypeMapper; -import com.palantir.conjure.java.visitor.DefaultTypeVisitor; -import com.palantir.conjure.spec.AliasDefinition; import com.palantir.conjure.spec.EndpointDefinition; -import com.palantir.conjure.spec.ExternalReference; -import com.palantir.conjure.spec.ListType; -import com.palantir.conjure.spec.MapType; -import com.palantir.conjure.spec.OptionalType; -import com.palantir.conjure.spec.PrimitiveType; -import com.palantir.conjure.spec.SetType; -import com.palantir.conjure.spec.Type; -import com.palantir.conjure.spec.TypeDefinition; -import com.palantir.conjure.visitor.TypeDefinitionVisitor; -import com.palantir.conjure.visitor.TypeVisitor; import com.palantir.logsafe.SafeArg; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.ParameterizedTypeName; -import java.util.List; -import java.util.Optional; final class UndertowTypeFunctions { - static boolean isAliasType(Type type) { - return type.accept(new IsTypeVisitor() { - @Override - public Boolean visitReference(com.palantir.conjure.spec.TypeName _value) { - return true; - } - }); - } - - static boolean isOptionalBinary(Type type) { - return type.accept(new IsTypeVisitor() { - @Override - public Boolean visitOptional(OptionalType value) { - return value.getItemType().accept(TypeVisitor.IS_BINARY); - } - }); - } - - static boolean isBinaryOrOptionalBinary(Type type) { - return type.accept(TypeVisitor.IS_BINARY) || isOptionalBinary(type); - } - - static boolean isCollectionType(Type type) { - return type.accept(TypeVisitor.IS_LIST) || type.accept(TypeVisitor.IS_SET); - } - - // Returns the type that the given alias type refers to. For example, if the input type is defined as - // "alias: integer", the returned type will be the type for "integer". The provided type must be an alias - // (reference) type. - static Type getAliasedType(Type type, List typeDefinitions) { - com.palantir.logsafe.Preconditions.checkArgument( - isAliasType(type), "Expected an alias", SafeArg.of("type", type)); - return getAliasedType( - type.accept(new AbstractTypeVisitor() { - @Override - public com.palantir.conjure.spec.TypeName visitReference( - com.palantir.conjure.spec.TypeName value) { - return value; - } - }), - typeDefinitions) - .get(); - } - - static Optional getAliasedType( - com.palantir.conjure.spec.TypeName typeName, List typeDefinitions) { - // return type definition for the provided alias type - TypeDefinition typeDefinition = typeDefinitions.stream() - .filter(typeDef -> { - com.palantir.conjure.spec.TypeName currName = typeDef.accept(TypeDefinitionVisitor.TYPE_NAME); - String currClassName = currName.getPackage() + "." + currName.getName(); - return currClassName.equals(typeName.getPackage() + "." + typeName.getName()); - }) - .findFirst() - .get(); - - if (typeDefinition.accept(TypeDefinitionVisitor.IS_ALIAS)) { - AliasDefinition aliasDefinition = typeDefinition.accept(TypeDefinitionVisitor.ALIAS); - return Optional.of(aliasDefinition.getAlias()); - } - return Optional.empty(); - } - - private static final ImmutableMap PRIMITIVE_TO_TYPE_NAME = new ImmutableMap.Builder< - PrimitiveType.Value, String>() - .put(PrimitiveType.Value.BEARERTOKEN, "BearerToken") - .put(PrimitiveType.Value.BOOLEAN, "Boolean") - .put(PrimitiveType.Value.DATETIME, "DateTime") - .put(PrimitiveType.Value.DOUBLE, "Double") - .put(PrimitiveType.Value.INTEGER, "Integer") - .put(PrimitiveType.Value.RID, "Rid") - .put(PrimitiveType.Value.SAFELONG, "SafeLong") - .put(PrimitiveType.Value.STRING, "String") - .put(PrimitiveType.Value.UUID, "Uuid") - .build(); - - static String primitiveTypeName(PrimitiveType in) { - String typeName = PRIMITIVE_TO_TYPE_NAME.get(in.get()); - if (typeName == null) { - throw new IllegalStateException("unrecognized primitive type: " + in); - } - return typeName; - } - - static Type toConjureTypeWithoutAliases(final Type in, final List typeDefinitions) { - return in.accept(new Type.Visitor() { - @Override - public Type visitPrimitive(PrimitiveType _value) { - return in; - } - - @Override - public Type visitOptional(OptionalType value) { - return Type.optional( - OptionalType.of(toConjureTypeWithoutAliases(value.getItemType(), typeDefinitions))); - } - - @Override - public Type visitList(ListType value) { - return Type.list(ListType.of(toConjureTypeWithoutAliases(value.getItemType(), typeDefinitions))); - } - - @Override - public Type visitSet(SetType value) { - return Type.set(SetType.of(toConjureTypeWithoutAliases(value.getItemType(), typeDefinitions))); - } - - @Override - public Type visitMap(MapType value) { - return Type.map(MapType.of( - toConjureTypeWithoutAliases(value.getKeyType(), typeDefinitions), - toConjureTypeWithoutAliases(value.getValueType(), typeDefinitions))); - } - - @Override - public Type visitReference(com.palantir.conjure.spec.TypeName value) { - return getAliasedType(value, typeDefinitions) - .map(aliasedType -> toConjureTypeWithoutAliases(aliasedType, typeDefinitions)) - .orElse(in); - } - - @Override - public Type visitExternal(ExternalReference _value) { - return in; - } - - @Override - public Type visitUnknown(String _unknownType) { - return in; - } - }); - } - - static final GetTypeVisitor PRIMITIVE_VISITOR = new GetTypeVisitor() { - @Override - public PrimitiveType visitPrimitive(PrimitiveType value) { - return value; - } - }; - - static final GetTypeVisitor OPTIONAL_VISITOR = new GetTypeVisitor() { - @Override - public OptionalType visitOptional(OptionalType value) { - return value; - } - }; - - private abstract static class GetTypeVisitor extends DefaultTypeVisitor { - @Override - public T visitUnknown(String _unknownType) { - throw new UnsupportedOperationException(); - } - } - - private abstract static class AbstractTypeVisitor extends DefaultTypeVisitor { - @Override - public T visitDefault() { - throw new UnsupportedOperationException(); - } - } - - private abstract static class IsTypeVisitor extends DefaultTypeVisitor { - @Override - public final Boolean visitDefault() { - return false; - } - } - /** * Asynchronous-processing capable endpoints are generated if either of the following are true. * diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java new file mode 100644 index 000000000..d3723a093 --- /dev/null +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java @@ -0,0 +1,208 @@ +/* + * (c) Copyright 2020 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.conjure.java.util; + +import com.google.common.collect.ImmutableMap; +import com.palantir.conjure.java.visitor.DefaultTypeVisitor; +import com.palantir.conjure.spec.AliasDefinition; +import com.palantir.conjure.spec.ExternalReference; +import com.palantir.conjure.spec.ListType; +import com.palantir.conjure.spec.MapType; +import com.palantir.conjure.spec.OptionalType; +import com.palantir.conjure.spec.PrimitiveType; +import com.palantir.conjure.spec.SetType; +import com.palantir.conjure.spec.Type; +import com.palantir.conjure.spec.TypeDefinition; +import com.palantir.conjure.visitor.TypeDefinitionVisitor; +import com.palantir.conjure.visitor.TypeVisitor; +import com.palantir.logsafe.SafeArg; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +public final class TypeFunctions { + + public static boolean isAliasType(Type type) { + return type.accept(new IsTypeVisitor() { + @Override + public Boolean visitReference(com.palantir.conjure.spec.TypeName _value) { + return true; + } + }); + } + + public static boolean isOptionalBinary(Type type) { + return type.accept(new IsTypeVisitor() { + @Override + public Boolean visitOptional(OptionalType value) { + return value.getItemType().accept(TypeVisitor.IS_BINARY); + } + }); + } + + public static boolean isBinaryOrOptionalBinary(Type type) { + return type.accept(TypeVisitor.IS_BINARY) || isOptionalBinary(type); + } + + public static boolean isCollectionType(Type type) { + return type.accept(TypeVisitor.IS_LIST) || type.accept(TypeVisitor.IS_SET); + } + + // Returns the type that the given alias type refers to. For example, if the input type is defined as + // "alias: integer", the returned type will be the type for "integer". The provided type must be an alias + // (reference) type. + public static Type getAliasedType(Type type, List typeDefinitions) { + com.palantir.logsafe.Preconditions.checkArgument( + isAliasType(type), "Expected an alias", SafeArg.of("type", type)); + return getAliasedType( + type.accept(new AbstractTypeVisitor() { + @Override + public com.palantir.conjure.spec.TypeName visitReference( + com.palantir.conjure.spec.TypeName value) { + return value; + } + }), + typeDefinitions) + .get(); + } + + public static Optional getAliasedType( + com.palantir.conjure.spec.TypeName typeName, Collection typeDefinitions) { + // return type definition for the provided alias type + TypeDefinition typeDefinition = typeDefinitions.stream() + .filter(typeDef -> { + com.palantir.conjure.spec.TypeName currName = typeDef.accept(TypeDefinitionVisitor.TYPE_NAME); + String currClassName = currName.getPackage() + "." + currName.getName(); + return currClassName.equals(typeName.getPackage() + "." + typeName.getName()); + }) + .findFirst() + .get(); + + if (typeDefinition.accept(TypeDefinitionVisitor.IS_ALIAS)) { + AliasDefinition aliasDefinition = typeDefinition.accept(TypeDefinitionVisitor.ALIAS); + return Optional.of(aliasDefinition.getAlias()); + } + return Optional.empty(); + } + + private static final ImmutableMap PRIMITIVE_TO_TYPE_NAME = new ImmutableMap.Builder< + PrimitiveType.Value, String>() + .put(PrimitiveType.Value.BEARERTOKEN, "BearerToken") + .put(PrimitiveType.Value.BOOLEAN, "Boolean") + .put(PrimitiveType.Value.DATETIME, "DateTime") + .put(PrimitiveType.Value.DOUBLE, "Double") + .put(PrimitiveType.Value.INTEGER, "Integer") + .put(PrimitiveType.Value.RID, "Rid") + .put(PrimitiveType.Value.SAFELONG, "SafeLong") + .put(PrimitiveType.Value.STRING, "String") + .put(PrimitiveType.Value.UUID, "Uuid") + .build(); + + public static String primitiveTypeName(PrimitiveType in) { + String typeName = PRIMITIVE_TO_TYPE_NAME.get(in.get()); + if (typeName == null) { + throw new IllegalStateException("unrecognized primitive type: " + in); + } + return typeName; + } + + public static Type toConjureTypeWithoutAliases(final Type in, final Collection typeDefinitions) { + return in.accept(new Type.Visitor() { + @Override + public Type visitPrimitive(PrimitiveType _value) { + return in; + } + + @Override + public Type visitOptional(OptionalType value) { + return Type.optional( + OptionalType.of(toConjureTypeWithoutAliases(value.getItemType(), typeDefinitions))); + } + + @Override + public Type visitList(ListType value) { + return Type.list(ListType.of(toConjureTypeWithoutAliases(value.getItemType(), typeDefinitions))); + } + + @Override + public Type visitSet(SetType value) { + return Type.set(SetType.of(toConjureTypeWithoutAliases(value.getItemType(), typeDefinitions))); + } + + @Override + public Type visitMap(MapType value) { + return Type.map(MapType.of( + toConjureTypeWithoutAliases(value.getKeyType(), typeDefinitions), + toConjureTypeWithoutAliases(value.getValueType(), typeDefinitions))); + } + + @Override + public Type visitReference(com.palantir.conjure.spec.TypeName value) { + return getAliasedType(value, typeDefinitions) + .map(aliasedType -> toConjureTypeWithoutAliases(aliasedType, typeDefinitions)) + .orElse(in); + } + + @Override + public Type visitExternal(ExternalReference _value) { + return in; + } + + @Override + public Type visitUnknown(String _unknownType) { + return in; + } + }); + } + + public static final GetTypeVisitor PRIMITIVE_VISITOR = new GetTypeVisitor() { + @Override + public PrimitiveType visitPrimitive(PrimitiveType value) { + return value; + } + }; + + public static final GetTypeVisitor OPTIONAL_VISITOR = new GetTypeVisitor() { + @Override + public OptionalType visitOptional(OptionalType value) { + return value; + } + }; + + private abstract static class GetTypeVisitor extends DefaultTypeVisitor { + @Override + public T visitUnknown(String _unknownType) { + throw new UnsupportedOperationException(); + } + } + + private abstract static class AbstractTypeVisitor extends DefaultTypeVisitor { + @Override + public T visitDefault() { + throw new UnsupportedOperationException(); + } + } + + private abstract static class IsTypeVisitor extends DefaultTypeVisitor { + @Override + public final Boolean visitDefault() { + return false; + } + } + + private TypeFunctions() {} +} diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/visitor/DialogueClassVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/visitor/DialogueClassVisitor.java index b4b6c9a45..8ebcf83e3 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/visitor/DialogueClassVisitor.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/visitor/DialogueClassVisitor.java @@ -19,6 +19,7 @@ import com.palantir.conjure.java.Options; import com.palantir.conjure.java.types.ClassNameVisitor; import com.palantir.conjure.java.types.DefaultClassNameVisitor; +import com.palantir.conjure.java.util.TypeFunctions; import com.palantir.conjure.spec.ExternalReference; import com.palantir.conjure.spec.ListType; import com.palantir.conjure.spec.MapType; @@ -74,16 +75,16 @@ public TypeName visitPrimitive(PrimitiveType value) { @Override public TypeName visitOptional(OptionalType value) { Type itemType = value.getItemType(); - if (itemType.accept(TypeVisitor.IS_BINARY) || itemType.accept(TypeVisitor.IS_REFERENCE)) { + Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(itemType, types.values()); + if (dealiased.accept(TypeVisitor.IS_BINARY)) { + return ParameterizedTypeName.get(ClassName.get(Optional.class), dealiased.accept(this)); + } + if (itemType.accept(TypeVisitor.IS_REFERENCE)) { return ParameterizedTypeName.get(ClassName.get(Optional.class), box(itemType.accept(this))); } return delegate.visitOptional(value); } - private static TypeName box(TypeName input) { - return input.isPrimitive() ? input.box() : input; - } - @Override public TypeName visitList(ListType value) { return delegate.visitList(value); @@ -100,25 +101,36 @@ public TypeName visitMap(MapType value) { } @Override - public TypeName visitReference(com.palantir.conjure.spec.TypeName type) { - if (!types.containsKey(type)) { - throw new IllegalStateException("Unknown LocalReferenceType type: " + type); + public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { + if (!types.containsKey(typeName)) { + throw new IllegalStateException("Unknown LocalReferenceType type: " + typeName); } - TypeDefinition def = types.get(type); - if (def.accept(TypeDefinitionVisitor.IS_ALIAS)) { - Type aliasType = def.accept(TypeDefinitionVisitor.ALIAS).getAlias(); - TypeName aliasTypeName = aliasType.accept(this); - if (aliasTypeName.equals(visitPrimitive(PrimitiveType.BINARY))) { - return aliasTypeName; + Optional type = TypeFunctions.getAliasedType(typeName, types.values()); + if (type.isPresent()) { + Type dealiased = dealiasBinary(type.get()); + if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + return dealiased.accept(this); } } - return delegate.visitReference(type); + return delegate.visitReference(typeName); } @Override public TypeName visitExternal(ExternalReference value) { return delegate.visitExternal(value); } + + private static TypeName box(TypeName input) { + return input.isPrimitive() ? input.box() : input; + } + + private Type dealiasBinary(Type input) { + Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(input, types.values()); + if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + return dealiased; + } + return input; + } } From 8be78406e1e1b791d9ccf113cb93ae27ff0cdaf6 Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Mon, 5 Oct 2020 12:47:06 -0400 Subject: [PATCH 07/12] fix jersey and retrofit while we're here --- .../palantir/product/EteBinaryService.java | 3 +- .../product/EteBinaryServiceRetrofit.java | 5 +-- .../types/ReturnTypeClassNameVisitor.java | 34 ++++++++++++------- .../conjure/java/EteBinaryResource.java | 6 ++-- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryService.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryService.java index e628cd601..1b4cc9a1f 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryService.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryService.java @@ -56,5 +56,6 @@ StreamingOutput getBinaryFailure( @GET @Path("binary/aliased") - AliasOptionalDoubleAliasedBinaryResult getAliased(@HeaderParam("Authorization") @NotNull AuthHeader authHeader); + @Produces(MediaType.APPLICATION_OCTET_STREAM) + Optional getAliased(@HeaderParam("Authorization") @NotNull AuthHeader authHeader); } diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceRetrofit.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceRetrofit.java index b0fe87e27..36c31b235 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceRetrofit.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/EteBinaryServiceRetrofit.java @@ -49,6 +49,7 @@ ListenableFuture getBinaryFailure( @Header("Authorization") AuthHeader authHeader, @Query("numBytes") int numBytes); @GET("./binary/aliased") - @Headers({"hr-path-template: /binary/aliased", "Accept: application/json"}) - ListenableFuture getAliased(@Header("Authorization") AuthHeader authHeader); + @Headers({"hr-path-template: /binary/aliased", "Accept: application/octet-stream"}) + @Streaming + ListenableFuture> getAliased(@Header("Authorization") AuthHeader authHeader); } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ReturnTypeClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ReturnTypeClassNameVisitor.java index 9836acbc7..2b7ebbbd5 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ReturnTypeClassNameVisitor.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ReturnTypeClassNameVisitor.java @@ -17,6 +17,7 @@ package com.palantir.conjure.java.types; import com.palantir.conjure.java.Options; +import com.palantir.conjure.java.util.TypeFunctions; import com.palantir.conjure.spec.ExternalReference; import com.palantir.conjure.spec.ListType; import com.palantir.conjure.spec.MapType; @@ -31,6 +32,7 @@ import com.squareup.javapoet.TypeName; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; @@ -65,8 +67,9 @@ public TypeName visitMap(MapType type) { @Override public TypeName visitOptional(OptionalType type) { - if (type.getItemType().accept(TypeVisitor.IS_PRIMITIVE) - && type.getItemType().accept(TypeVisitor.PRIMITIVE).equals(PrimitiveType.BINARY)) { + Type itemType = type.getItemType(); + Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(itemType, types.values()); + if (dealiased.accept(TypeVisitor.IS_BINARY)) { return optionalBinaryTypeName; } return delegate.visitOptional(type); @@ -82,21 +85,20 @@ public TypeName visitPrimitive(PrimitiveType type) { } @Override - public TypeName visitReference(com.palantir.conjure.spec.TypeName type) { - if (!types.containsKey(type)) { - throw new IllegalStateException("Unknown LocalReferenceType type: " + type); + public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { + if (!types.containsKey(typeName)) { + throw new IllegalStateException("Unknown LocalReferenceType type: " + typeName); } - TypeDefinition def = types.get(type); - if (def.accept(TypeDefinitionVisitor.IS_ALIAS)) { - Type aliasType = def.accept(TypeDefinitionVisitor.ALIAS).getAlias(); - TypeName aliasTypeName = aliasType.accept(this); - if (aliasTypeName.equals(binaryClassName)) { - return aliasTypeName; + Optional type = TypeFunctions.getAliasedType(typeName, types.values()); + if (type.isPresent()) { + Type dealiased = dealiasBinary(type.get()); + if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + return dealiased.accept(this); } } - return delegate.visitReference(type); + return delegate.visitReference(typeName); } @Override @@ -108,4 +110,12 @@ public TypeName visitExternal(ExternalReference type) { public TypeName visitSet(SetType type) { return delegate.visitSet(type); } + + private Type dealiasBinary(Type input) { + Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(input, types.values()); + if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + return dealiased; + } + return input; + } } diff --git a/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java b/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java index cd3a36cdd..49c1e9bb6 100644 --- a/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java +++ b/conjure-java-core/src/test/java/com/palantir/conjure/java/EteBinaryResource.java @@ -22,7 +22,6 @@ import com.palantir.conjure.java.api.errors.ServiceException; import com.palantir.logsafe.SafeArg; import com.palantir.logsafe.exceptions.SafeRuntimeException; -import com.palantir.product.AliasOptionalDoubleAliasedBinaryResult; import com.palantir.product.EteBinaryService; import com.palantir.tokens.auth.AuthHeader; import java.io.IOException; @@ -74,8 +73,7 @@ public StreamingOutput getBinaryFailure(AuthHeader _authHeader, int numBytes) { } @Override - public AliasOptionalDoubleAliasedBinaryResult getAliased(@NotNull AuthHeader authHeader) { - // BUG: This should be dealiased to return Optional - return AliasOptionalDoubleAliasedBinaryResult.of(Optional.empty()); + public Optional getAliased(@NotNull AuthHeader authHeader) { + return Optional.empty(); } } From 24fada3ab73ca5dc52e95085d5f3654e08909257 Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Mon, 12 Oct 2020 11:06:35 -0400 Subject: [PATCH 08/12] deduplicate visitors --- .../java/services/JerseyServiceGenerator.java | 9 +- .../services/Retrofit2ServiceGenerator.java | 11 +- .../UndertowRequestBodyClassNameVisitor.java | 110 -------------- .../UndertowReturnValueClassNameVisitor.java | 110 -------------- .../services/UndertowServiceGenerator.java | 19 ++- .../dialogue/DialogueServiceGenerator.java | 18 ++- .../types/ReturnTypeClassNameVisitor.java | 121 ---------------- .../SpecializeBinaryClassNameVisitor.java | 78 +++++++--- .../java/visitor/DialogueClassVisitor.java | 136 ------------------ 9 files changed, 94 insertions(+), 518 deletions(-) delete mode 100644 conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowRequestBodyClassNameVisitor.java delete mode 100644 conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java delete mode 100644 conjure-java-core/src/main/java/com/palantir/conjure/java/types/ReturnTypeClassNameVisitor.java delete mode 100644 conjure-java-core/src/main/java/com/palantir/conjure/java/visitor/DialogueClassVisitor.java diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/JerseyServiceGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/JerseyServiceGenerator.java index 9349d5f87..33b5cfd54 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/JerseyServiceGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/JerseyServiceGenerator.java @@ -19,8 +19,8 @@ import com.google.common.collect.ImmutableList; import com.palantir.conjure.java.ConjureAnnotations; import com.palantir.conjure.java.Options; +import com.palantir.conjure.java.types.ClassNameVisitor; import com.palantir.conjure.java.types.DefaultClassNameVisitor; -import com.palantir.conjure.java.types.ReturnTypeClassNameVisitor; import com.palantir.conjure.java.types.SpecializeBinaryClassNameVisitor; import com.palantir.conjure.java.types.TypeMapper; import com.palantir.conjure.java.util.Javadoc; @@ -82,15 +82,16 @@ public Set generate(ConjureDefinition conjureDefinition) { TypeName optionalBinaryReturnType = options.jerseyBinaryAsResponse() ? BINARY_RETURN_TYPE_RESPONSE : OPTIONAL_BINARY_RETURN_TYPE; + ClassNameVisitor defaultVisitor = new DefaultClassNameVisitor(conjureDefinition.getTypes(), options); TypeMapper returnTypeMapper = new TypeMapper( conjureDefinition.getTypes(), - new ReturnTypeClassNameVisitor( - conjureDefinition.getTypes(), binaryReturnType, optionalBinaryReturnType, options)); + new SpecializeBinaryClassNameVisitor( + defaultVisitor, conjureDefinition.getTypes(), binaryReturnType, optionalBinaryReturnType)); TypeMapper argumentTypeMapper = new TypeMapper( conjureDefinition.getTypes(), new SpecializeBinaryClassNameVisitor( - new DefaultClassNameVisitor(conjureDefinition.getTypes(), options), BINARY_ARGUMENT_TYPE)); + defaultVisitor, conjureDefinition.getTypes(), BINARY_ARGUMENT_TYPE)); return conjureDefinition.getServices().stream() .map(serviceDef -> generateService(serviceDef, returnTypeMapper, argumentTypeMapper)) diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/Retrofit2ServiceGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/Retrofit2ServiceGenerator.java index a447a7aed..74bc8e13b 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/Retrofit2ServiceGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/Retrofit2ServiceGenerator.java @@ -21,8 +21,8 @@ import com.google.common.collect.ImmutableSet; import com.palantir.conjure.java.ConjureAnnotations; import com.palantir.conjure.java.Options; +import com.palantir.conjure.java.types.ClassNameVisitor; import com.palantir.conjure.java.types.DefaultClassNameVisitor; -import com.palantir.conjure.java.types.ReturnTypeClassNameVisitor; import com.palantir.conjure.java.types.SpecializeBinaryClassNameVisitor; import com.palantir.conjure.java.types.TypeMapper; import com.palantir.conjure.java.util.Javadoc; @@ -72,7 +72,7 @@ public final class Retrofit2ServiceGenerator extends ServiceGenerator { private static final ClassName BINARY_ARGUMENT_TYPE = ClassName.get("okhttp3", "RequestBody"); private static final ClassName BINARY_RETURN_TYPE = ClassName.get("okhttp3", "ResponseBody"); private static final TypeName OPTIONAL_BINARY_RETURN_TYPE = - ParameterizedTypeName.get(ClassName.get(Optional.class), ClassName.get("okhttp3", "ResponseBody")); + ParameterizedTypeName.get(ClassName.get(Optional.class), BINARY_RETURN_TYPE); private static final Logger log = LoggerFactory.getLogger(Retrofit2ServiceGenerator.class); @@ -84,15 +84,16 @@ public Retrofit2ServiceGenerator(Options options) { @Override public Set generate(ConjureDefinition conjureDefinition) { + ClassNameVisitor defaultVisitor = new DefaultClassNameVisitor(conjureDefinition.getTypes(), options); TypeMapper returnTypeMapper = new TypeMapper( conjureDefinition.getTypes(), - new ReturnTypeClassNameVisitor( - conjureDefinition.getTypes(), BINARY_RETURN_TYPE, OPTIONAL_BINARY_RETURN_TYPE, options)); + new SpecializeBinaryClassNameVisitor( + defaultVisitor, conjureDefinition.getTypes(), BINARY_RETURN_TYPE, OPTIONAL_BINARY_RETURN_TYPE)); TypeMapper argumentTypeMapper = new TypeMapper( conjureDefinition.getTypes(), new SpecializeBinaryClassNameVisitor( - new DefaultClassNameVisitor(conjureDefinition.getTypes(), options), BINARY_ARGUMENT_TYPE)); + defaultVisitor, conjureDefinition.getTypes(), BINARY_ARGUMENT_TYPE)); return conjureDefinition.getServices().stream() .map(serviceDef -> generateService(serviceDef, returnTypeMapper, argumentTypeMapper)) diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowRequestBodyClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowRequestBodyClassNameVisitor.java deleted file mode 100644 index a615dc850..000000000 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowRequestBodyClassNameVisitor.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.palantir.conjure.java.services; - -import com.palantir.conjure.java.Options; -import com.palantir.conjure.java.types.ClassNameVisitor; -import com.palantir.conjure.java.types.DefaultClassNameVisitor; -import com.palantir.conjure.java.util.TypeFunctions; -import com.palantir.conjure.spec.ExternalReference; -import com.palantir.conjure.spec.ListType; -import com.palantir.conjure.spec.MapType; -import com.palantir.conjure.spec.OptionalType; -import com.palantir.conjure.spec.PrimitiveType; -import com.palantir.conjure.spec.SetType; -import com.palantir.conjure.spec.Type; -import com.palantir.conjure.spec.TypeDefinition; -import com.palantir.conjure.visitor.TypeVisitor; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.ParameterizedTypeName; -import com.squareup.javapoet.TypeName; -import java.io.InputStream; -import java.util.List; -import java.util.Optional; - -public final class UndertowRequestBodyClassNameVisitor implements ClassNameVisitor { - - private final ClassNameVisitor delegate; - private final List types; - - public UndertowRequestBodyClassNameVisitor(List types, Options options) { - this.types = types; - delegate = new DefaultClassNameVisitor(types, options); - } - - @Override - public TypeName visitUnknown(String unknownType) { - return delegate.visitUnknown(unknownType); - } - - @Override - public TypeName visitPrimitive(PrimitiveType primitiveType) { - if (PrimitiveType.BINARY.equals(primitiveType)) { - return ClassName.get(InputStream.class); - } - return delegate.visitPrimitive(primitiveType); - } - - @Override - public TypeName visitOptional(OptionalType optionalType) { - Type dealiased = dealiasBinary(optionalType.getItemType()); - if (dealiased.accept(TypeVisitor.IS_BINARY)) { - return ParameterizedTypeName.get(ClassName.get(Optional.class), dealiased.accept(this)); - } - return delegate.visitOptional(optionalType); - } - - @Override - public TypeName visitList(ListType listType) { - return delegate.visitList(listType); - } - - @Override - public TypeName visitSet(SetType setType) { - return delegate.visitSet(setType); - } - - @Override - public TypeName visitMap(MapType mapType) { - return delegate.visitMap(mapType); - } - - @Override - public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { - Optional type = TypeFunctions.getAliasedType(typeName, types); - if (type.isPresent()) { - Type dealiased = dealiasBinary(type.get()); - if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { - return dealiased.accept(this); - } - } - return delegate.visitReference(typeName); - } - - @Override - public TypeName visitExternal(ExternalReference externalReference) { - return delegate.visitExternal(externalReference); - } - - private Type dealiasBinary(Type input) { - Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(input, types); - if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { - return dealiased; - } - return input; - } -} diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java deleted file mode 100644 index a3825ec5c..000000000 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowReturnValueClassNameVisitor.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.palantir.conjure.java.services; - -import com.palantir.conjure.java.Options; -import com.palantir.conjure.java.types.ClassNameVisitor; -import com.palantir.conjure.java.types.DefaultClassNameVisitor; -import com.palantir.conjure.java.undertow.lib.BinaryResponseBody; -import com.palantir.conjure.java.util.TypeFunctions; -import com.palantir.conjure.spec.ExternalReference; -import com.palantir.conjure.spec.ListType; -import com.palantir.conjure.spec.MapType; -import com.palantir.conjure.spec.OptionalType; -import com.palantir.conjure.spec.PrimitiveType; -import com.palantir.conjure.spec.SetType; -import com.palantir.conjure.spec.Type; -import com.palantir.conjure.spec.TypeDefinition; -import com.palantir.conjure.visitor.TypeVisitor; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.ParameterizedTypeName; -import com.squareup.javapoet.TypeName; -import java.util.List; -import java.util.Optional; - -public final class UndertowReturnValueClassNameVisitor implements ClassNameVisitor { - - private final ClassNameVisitor delegate; - private final List types; - - public UndertowReturnValueClassNameVisitor(List types, Options featureFlags) { - this.types = types; - delegate = new DefaultClassNameVisitor(types, featureFlags); - } - - @Override - public TypeName visitUnknown(String unknownType) { - return delegate.visitUnknown(unknownType); - } - - @Override - public TypeName visitPrimitive(PrimitiveType primitiveType) { - if (PrimitiveType.BINARY.equals(primitiveType)) { - return ClassName.get(BinaryResponseBody.class); - } - return delegate.visitPrimitive(primitiveType); - } - - @Override - public TypeName visitOptional(OptionalType optionalType) { - Type dealiased = dealiasBinary(optionalType.getItemType()); - if (dealiased.accept(TypeVisitor.IS_BINARY)) { - return ParameterizedTypeName.get(ClassName.get(Optional.class), dealiased.accept(this)); - } - return delegate.visitOptional(optionalType); - } - - @Override - public TypeName visitList(ListType listType) { - return delegate.visitList(listType); - } - - @Override - public TypeName visitSet(SetType setType) { - return delegate.visitSet(setType); - } - - @Override - public TypeName visitMap(MapType mapType) { - return delegate.visitMap(mapType); - } - - @Override - public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { - Optional type = TypeFunctions.getAliasedType(typeName, types); - if (type.isPresent()) { - Type dealiased = dealiasBinary(type.get()); - if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { - return dealiased.accept(this); - } - } - return delegate.visitReference(typeName); - } - - @Override - public TypeName visitExternal(ExternalReference externalReference) { - return delegate.visitExternal(externalReference); - } - - private Type dealiasBinary(Type input) { - Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(input, types); - if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { - return dealiased; - } - return input; - } -} diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceGenerator.java index 94624cc74..6685bc66c 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceGenerator.java @@ -18,11 +18,17 @@ import com.google.common.collect.ImmutableList; import com.palantir.conjure.java.Options; +import com.palantir.conjure.java.types.ClassNameVisitor; +import com.palantir.conjure.java.types.DefaultClassNameVisitor; +import com.palantir.conjure.java.types.SpecializeBinaryClassNameVisitor; import com.palantir.conjure.java.types.TypeMapper; +import com.palantir.conjure.java.undertow.lib.BinaryResponseBody; import com.palantir.conjure.spec.ConjureDefinition; import com.palantir.conjure.spec.ServiceDefinition; import com.palantir.conjure.spec.TypeDefinition; +import com.squareup.javapoet.ClassName; import com.squareup.javapoet.JavaFile; +import java.io.InputStream; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -37,16 +43,17 @@ public UndertowServiceGenerator(Options options) { @Override public Set generate(ConjureDefinition conjureDefinition) { + ClassNameVisitor defaultVisitor = new DefaultClassNameVisitor(conjureDefinition.getTypes(), options); + ClassNameVisitor argumentVisitor = new SpecializeBinaryClassNameVisitor( + defaultVisitor, conjureDefinition.getTypes(), ClassName.get(InputStream.class)); + ClassNameVisitor returnVisitor = new SpecializeBinaryClassNameVisitor( + defaultVisitor, conjureDefinition.getTypes(), ClassName.get(BinaryResponseBody.class)); return conjureDefinition.getServices().stream() .flatMap(serviceDef -> generateService( serviceDef, conjureDefinition.getTypes(), - new TypeMapper( - conjureDefinition.getTypes(), - new UndertowRequestBodyClassNameVisitor(conjureDefinition.getTypes(), options)), - new TypeMapper( - conjureDefinition.getTypes(), - new UndertowReturnValueClassNameVisitor(conjureDefinition.getTypes(), options))) + new TypeMapper(conjureDefinition.getTypes(), argumentVisitor), + new TypeMapper(conjureDefinition.getTypes(), returnVisitor)) .stream()) .collect(Collectors.toSet()); } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DialogueServiceGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DialogueServiceGenerator.java index 1dbb82d50..1c4513a3a 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DialogueServiceGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DialogueServiceGenerator.java @@ -18,14 +18,18 @@ import com.palantir.conjure.java.Options; import com.palantir.conjure.java.services.ServiceGenerator; +import com.palantir.conjure.java.types.DefaultClassNameVisitor; +import com.palantir.conjure.java.types.SpecializeBinaryClassNameVisitor; import com.palantir.conjure.java.types.TypeMapper; -import com.palantir.conjure.java.visitor.DialogueClassVisitor; import com.palantir.conjure.spec.ConjureDefinition; import com.palantir.conjure.spec.TypeDefinition; import com.palantir.conjure.visitor.TypeDefinitionVisitor; +import com.palantir.dialogue.BinaryRequestBody; import com.palantir.logsafe.Preconditions; import com.palantir.logsafe.SafeArg; +import com.squareup.javapoet.ClassName; import com.squareup.javapoet.JavaFile; +import java.io.InputStream; import java.util.Map; import java.util.Set; import java.util.function.Function; @@ -44,14 +48,18 @@ public DialogueServiceGenerator(Options options) { @Override public Set generate(ConjureDefinition conjureDefinition) { DialogueEndpointsGenerator endpoints = new DialogueEndpointsGenerator(options); - TypeMapper parameterTypes = new TypeMapper( conjureDefinition.getTypes(), - new DialogueClassVisitor(conjureDefinition.getTypes(), options, DialogueClassVisitor.Mode.PARAMETER)); + new SpecializeBinaryClassNameVisitor( + new DefaultClassNameVisitor(conjureDefinition.getTypes(), options), + conjureDefinition.getTypes(), + ClassName.get(BinaryRequestBody.class))); TypeMapper returnTypes = new TypeMapper( conjureDefinition.getTypes(), - new DialogueClassVisitor( - conjureDefinition.getTypes(), options, DialogueClassVisitor.Mode.RETURN_VALUE)); + new SpecializeBinaryClassNameVisitor( + new DefaultClassNameVisitor(conjureDefinition.getTypes(), options), + conjureDefinition.getTypes(), + ClassName.get(InputStream.class))); Map typeDefinitionsByName = conjureDefinition.getTypes().stream() .collect(Collectors.toMap( diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ReturnTypeClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ReturnTypeClassNameVisitor.java deleted file mode 100644 index 2b7ebbbd5..000000000 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ReturnTypeClassNameVisitor.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.palantir.conjure.java.types; - -import com.palantir.conjure.java.Options; -import com.palantir.conjure.java.util.TypeFunctions; -import com.palantir.conjure.spec.ExternalReference; -import com.palantir.conjure.spec.ListType; -import com.palantir.conjure.spec.MapType; -import com.palantir.conjure.spec.OptionalType; -import com.palantir.conjure.spec.PrimitiveType; -import com.palantir.conjure.spec.SetType; -import com.palantir.conjure.spec.Type; -import com.palantir.conjure.spec.TypeDefinition; -import com.palantir.conjure.visitor.TypeDefinitionVisitor; -import com.palantir.conjure.visitor.TypeVisitor; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.TypeName; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; - -public final class ReturnTypeClassNameVisitor implements ClassNameVisitor { - - private final DefaultClassNameVisitor delegate; - private final Map types; - private final ClassName binaryClassName; - private final TypeName optionalBinaryTypeName; - - public ReturnTypeClassNameVisitor( - List types, - ClassName binaryClassName, - TypeName optionalBinaryTypeName, - Options featureFlags) { - this.delegate = new DefaultClassNameVisitor(types, featureFlags); - this.types = types.stream() - .collect(Collectors.toMap(t -> t.accept(TypeDefinitionVisitor.TYPE_NAME), Function.identity())); - this.binaryClassName = binaryClassName; - this.optionalBinaryTypeName = optionalBinaryTypeName; - } - - @Override - public TypeName visitList(ListType type) { - return delegate.visitList(type); - } - - @Override - public TypeName visitMap(MapType type) { - return delegate.visitMap(type); - } - - @Override - public TypeName visitOptional(OptionalType type) { - Type itemType = type.getItemType(); - Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(itemType, types.values()); - if (dealiased.accept(TypeVisitor.IS_BINARY)) { - return optionalBinaryTypeName; - } - return delegate.visitOptional(type); - } - - @Override - public TypeName visitPrimitive(PrimitiveType type) { - if (type.get() == PrimitiveType.Value.BINARY) { - return binaryClassName; - } else { - return delegate.visitPrimitive(type); - } - } - - @Override - public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { - if (!types.containsKey(typeName)) { - throw new IllegalStateException("Unknown LocalReferenceType type: " + typeName); - } - - Optional type = TypeFunctions.getAliasedType(typeName, types.values()); - if (type.isPresent()) { - Type dealiased = dealiasBinary(type.get()); - if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { - return dealiased.accept(this); - } - } - - return delegate.visitReference(typeName); - } - - @Override - public TypeName visitExternal(ExternalReference type) { - return delegate.visitExternal(type); - } - - @Override - public TypeName visitSet(SetType type) { - return delegate.visitSet(type); - } - - private Type dealiasBinary(Type input) { - Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(input, types.values()); - if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { - return dealiased; - } - return input; - } -} diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java index a0ce6ce7f..e1b86eb74 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java @@ -1,5 +1,5 @@ /* - * (c) Copyright 2019 Palantir Technologies Inc. All rights reserved. + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,60 +16,96 @@ package com.palantir.conjure.java.types; +import com.palantir.conjure.java.util.TypeFunctions; import com.palantir.conjure.spec.ExternalReference; import com.palantir.conjure.spec.ListType; import com.palantir.conjure.spec.MapType; import com.palantir.conjure.spec.OptionalType; import com.palantir.conjure.spec.PrimitiveType; import com.palantir.conjure.spec.SetType; +import com.palantir.conjure.spec.Type; +import com.palantir.conjure.spec.TypeDefinition; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; +import java.util.List; +import java.util.Optional; public final class SpecializeBinaryClassNameVisitor implements ClassNameVisitor { private final ClassNameVisitor delegate; - private final TypeName binaryClassName; + private final List types; + private final ClassName binaryClassName; + private final TypeName optionalBinaryTypeName; - public SpecializeBinaryClassNameVisitor(ClassNameVisitor delegate, TypeName binaryClassName) { + public SpecializeBinaryClassNameVisitor( + ClassNameVisitor delegate, List types, ClassName binaryClassName) { this.delegate = delegate; + this.types = types; this.binaryClassName = binaryClassName; + this.optionalBinaryTypeName = ParameterizedTypeName.get(ClassName.get(Optional.class), binaryClassName); + } + + public SpecializeBinaryClassNameVisitor( + ClassNameVisitor delegate, + List types, + ClassName binaryClassName, + TypeName optionalBinaryTypeName) { + this.delegate = delegate; + this.types = types; + this.binaryClassName = binaryClassName; + this.optionalBinaryTypeName = optionalBinaryTypeName; } @Override - public TypeName visitPrimitive(PrimitiveType value) { - if (value.get() == PrimitiveType.Value.BINARY) { - return binaryClassName; - } else { - return delegate.visitPrimitive(value); - } + public TypeName visitList(ListType type) { + return delegate.visitList(type); } @Override - public TypeName visitOptional(OptionalType value) { - return delegate.visitOptional(value); + public TypeName visitMap(MapType type) { + return delegate.visitMap(type); } @Override - public TypeName visitList(ListType value) { - return delegate.visitList(value); + public TypeName visitOptional(OptionalType type) { + return dealiasBinary(type.getItemType()) + .map(_ignored -> optionalBinaryTypeName) + .orElseGet(() -> delegate.visitOptional(type)); } @Override - public TypeName visitSet(SetType value) { - return delegate.visitSet(value); + public TypeName visitPrimitive(PrimitiveType type) { + if (type.get() == PrimitiveType.Value.BINARY) { + return binaryClassName; + } else { + return delegate.visitPrimitive(type); + } } @Override - public TypeName visitMap(MapType value) { - return delegate.visitMap(value); + public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { + return TypeFunctions.getAliasedType(typeName, types) + .flatMap(this::dealiasBinary) + .map(value -> value.accept(SpecializeBinaryClassNameVisitor.this)) + .orElseGet(() -> delegate.visitReference(typeName)); } @Override - public TypeName visitReference(com.palantir.conjure.spec.TypeName value) { - return delegate.visitReference(value); + public TypeName visitExternal(ExternalReference type) { + return delegate.visitExternal(type); } @Override - public TypeName visitExternal(ExternalReference value) { - return delegate.visitExternal(value); + public TypeName visitSet(SetType type) { + return delegate.visitSet(type); + } + + private Optional dealiasBinary(Type input) { + Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(input, types); + if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { + return Optional.of(dealiased); + } + return Optional.empty(); } } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/visitor/DialogueClassVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/visitor/DialogueClassVisitor.java deleted file mode 100644 index 8ebcf83e3..000000000 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/visitor/DialogueClassVisitor.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.palantir.conjure.java.visitor; - -import com.palantir.conjure.java.Options; -import com.palantir.conjure.java.types.ClassNameVisitor; -import com.palantir.conjure.java.types.DefaultClassNameVisitor; -import com.palantir.conjure.java.util.TypeFunctions; -import com.palantir.conjure.spec.ExternalReference; -import com.palantir.conjure.spec.ListType; -import com.palantir.conjure.spec.MapType; -import com.palantir.conjure.spec.OptionalType; -import com.palantir.conjure.spec.PrimitiveType; -import com.palantir.conjure.spec.SetType; -import com.palantir.conjure.spec.Type; -import com.palantir.conjure.spec.TypeDefinition; -import com.palantir.conjure.visitor.TypeDefinitionVisitor; -import com.palantir.conjure.visitor.TypeVisitor; -import com.palantir.dialogue.BinaryRequestBody; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.ParameterizedTypeName; -import com.squareup.javapoet.TypeName; -import java.io.InputStream; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; - -public final class DialogueClassVisitor implements ClassNameVisitor { - - public enum Mode { - RETURN_VALUE, - PARAMETER - } - - private final DefaultClassNameVisitor delegate; - private final Mode mode; - private final Map types; - - public DialogueClassVisitor(List types, Options options, Mode mode) { - this.delegate = new DefaultClassNameVisitor(types, options); - this.mode = mode; - this.types = types.stream() - .collect(Collectors.toMap(t -> t.accept(TypeDefinitionVisitor.TYPE_NAME), Function.identity())); - } - - @Override - public TypeName visitPrimitive(PrimitiveType value) { - if (!value.equals(PrimitiveType.BINARY)) { - return delegate.visitPrimitive(value); - } - - if (mode == Mode.RETURN_VALUE) { - return TypeName.get(InputStream.class); - } else { - return TypeName.get(BinaryRequestBody.class); - } - } - - @Override - public TypeName visitOptional(OptionalType value) { - Type itemType = value.getItemType(); - Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(itemType, types.values()); - if (dealiased.accept(TypeVisitor.IS_BINARY)) { - return ParameterizedTypeName.get(ClassName.get(Optional.class), dealiased.accept(this)); - } - if (itemType.accept(TypeVisitor.IS_REFERENCE)) { - return ParameterizedTypeName.get(ClassName.get(Optional.class), box(itemType.accept(this))); - } - return delegate.visitOptional(value); - } - - @Override - public TypeName visitList(ListType value) { - return delegate.visitList(value); - } - - @Override - public TypeName visitSet(SetType value) { - return delegate.visitSet(value); - } - - @Override - public TypeName visitMap(MapType value) { - return delegate.visitMap(value); - } - - @Override - public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { - if (!types.containsKey(typeName)) { - throw new IllegalStateException("Unknown LocalReferenceType type: " + typeName); - } - - Optional type = TypeFunctions.getAliasedType(typeName, types.values()); - if (type.isPresent()) { - Type dealiased = dealiasBinary(type.get()); - if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { - return dealiased.accept(this); - } - } - - return delegate.visitReference(typeName); - } - - @Override - public TypeName visitExternal(ExternalReference value) { - return delegate.visitExternal(value); - } - - private static TypeName box(TypeName input) { - return input.isPrimitive() ? input.box() : input; - } - - private Type dealiasBinary(Type input) { - Type dealiased = TypeFunctions.toConjureTypeWithoutAliases(input, types.values()); - if (TypeFunctions.isBinaryOrOptionalBinary(dealiased)) { - return dealiased; - } - return input; - } -} From 6ac8ad8e63c4e7119aa741b6ccb4305557b5ab98 Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Mon, 12 Oct 2020 11:28:13 -0400 Subject: [PATCH 09/12] Fix --- .../src/test/resources/test/api/TestService.java.jersey | 5 ++--- .../test/resources/test/api/TestService.java.jersey.prefix | 4 ++-- .../test/api/TestService.java.jersey_require_not_null | 5 ++--- .../resources/test/api/TestServiceRetrofit.java.retrofit | 3 +-- .../test/api/TestServiceRetrofit.java.retrofit.prefix | 3 +-- 5 files changed, 8 insertions(+), 12 deletions(-) diff --git a/conjure-java-core/src/test/resources/test/api/TestService.java.jersey b/conjure-java-core/src/test/resources/test/api/TestService.java.jersey index 368353564..ea54fffc9 100644 --- a/conjure-java-core/src/test/resources/test/api/TestService.java.jersey +++ b/conjure-java-core/src/test/resources/test/api/TestService.java.jersey @@ -2,7 +2,6 @@ package com.palantir.another; import com.palantir.product.AliasedString; import com.palantir.product.CreateDatasetRequest; -import com.palantir.product.NestedAliasedBinary; import com.palantir.product.datasets.BackingFileSystem; import com.palantir.product.datasets.Dataset; import com.palantir.redaction.Safe; @@ -94,8 +93,8 @@ public interface TestService { @POST @Path("catalog/datasets/upload-raw-aliased") - void uploadAliasedRawData( - @HeaderParam("Authorization") @NotNull AuthHeader authHeader, @NotNull NestedAliasedBinary input); + @Consumes(MediaType.APPLICATION_OCTET_STREAM) + void uploadAliasedRawData(@HeaderParam("Authorization") @NotNull AuthHeader authHeader, @NotNull InputStream input); /** * @param datasetRid A valid dataset resource identifier. diff --git a/conjure-java-core/src/test/resources/test/api/TestService.java.jersey.prefix b/conjure-java-core/src/test/resources/test/api/TestService.java.jersey.prefix index ff81acf98..574d1b333 100644 --- a/conjure-java-core/src/test/resources/test/api/TestService.java.jersey.prefix +++ b/conjure-java-core/src/test/resources/test/api/TestService.java.jersey.prefix @@ -24,7 +24,6 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.StreamingOutput; import test.prefix.com.palantir.product.AliasedString; import test.prefix.com.palantir.product.CreateDatasetRequest; -import test.prefix.com.palantir.product.NestedAliasedBinary; import test.prefix.com.palantir.product.datasets.BackingFileSystem; import test.prefix.com.palantir.product.datasets.Dataset; @@ -93,7 +92,8 @@ public interface TestService { @POST @Path("catalog/datasets/upload-raw-aliased") - void uploadAliasedRawData(@HeaderParam("Authorization") AuthHeader authHeader, NestedAliasedBinary input); + @Consumes(MediaType.APPLICATION_OCTET_STREAM) + void uploadAliasedRawData(@HeaderParam("Authorization") AuthHeader authHeader, InputStream input); /** * @param datasetRid A valid dataset resource identifier. diff --git a/conjure-java-core/src/test/resources/test/api/TestService.java.jersey_require_not_null b/conjure-java-core/src/test/resources/test/api/TestService.java.jersey_require_not_null index 368353564..ea54fffc9 100644 --- a/conjure-java-core/src/test/resources/test/api/TestService.java.jersey_require_not_null +++ b/conjure-java-core/src/test/resources/test/api/TestService.java.jersey_require_not_null @@ -2,7 +2,6 @@ package com.palantir.another; import com.palantir.product.AliasedString; import com.palantir.product.CreateDatasetRequest; -import com.palantir.product.NestedAliasedBinary; import com.palantir.product.datasets.BackingFileSystem; import com.palantir.product.datasets.Dataset; import com.palantir.redaction.Safe; @@ -94,8 +93,8 @@ public interface TestService { @POST @Path("catalog/datasets/upload-raw-aliased") - void uploadAliasedRawData( - @HeaderParam("Authorization") @NotNull AuthHeader authHeader, @NotNull NestedAliasedBinary input); + @Consumes(MediaType.APPLICATION_OCTET_STREAM) + void uploadAliasedRawData(@HeaderParam("Authorization") @NotNull AuthHeader authHeader, @NotNull InputStream input); /** * @param datasetRid A valid dataset resource identifier. diff --git a/conjure-java-core/src/test/resources/test/api/TestServiceRetrofit.java.retrofit b/conjure-java-core/src/test/resources/test/api/TestServiceRetrofit.java.retrofit index e1f7a727e..fda7a406c 100644 --- a/conjure-java-core/src/test/resources/test/api/TestServiceRetrofit.java.retrofit +++ b/conjure-java-core/src/test/resources/test/api/TestServiceRetrofit.java.retrofit @@ -3,7 +3,6 @@ package com.palantir.another; import com.google.common.util.concurrent.ListenableFuture; import com.palantir.product.AliasedString; import com.palantir.product.CreateDatasetRequest; -import com.palantir.product.NestedAliasedBinary; import com.palantir.product.datasets.BackingFileSystem; import com.palantir.product.datasets.Dataset; import com.palantir.ri.ResourceIdentifier; @@ -83,7 +82,7 @@ public interface TestServiceRetrofit { @POST("./catalog/datasets/upload-raw-aliased") @Headers({"hr-path-template: /catalog/datasets/upload-raw-aliased", "Accept: application/json"}) ListenableFuture uploadAliasedRawData( - @Header("Authorization") AuthHeader authHeader, @Body NestedAliasedBinary input); + @Header("Authorization") AuthHeader authHeader, @Body RequestBody input); /** * @param datasetRid A valid dataset resource identifier. diff --git a/conjure-java-core/src/test/resources/test/api/TestServiceRetrofit.java.retrofit.prefix b/conjure-java-core/src/test/resources/test/api/TestServiceRetrofit.java.retrofit.prefix index 05f5dc190..8c54e2590 100644 --- a/conjure-java-core/src/test/resources/test/api/TestServiceRetrofit.java.retrofit.prefix +++ b/conjure-java-core/src/test/resources/test/api/TestServiceRetrofit.java.retrofit.prefix @@ -22,7 +22,6 @@ import retrofit2.http.Query; import retrofit2.http.Streaming; import test.prefix.com.palantir.product.AliasedString; import test.prefix.com.palantir.product.CreateDatasetRequest; -import test.prefix.com.palantir.product.NestedAliasedBinary; import test.prefix.com.palantir.product.datasets.BackingFileSystem; import test.prefix.com.palantir.product.datasets.Dataset; @@ -83,7 +82,7 @@ public interface TestServiceRetrofit { @POST("./catalog/datasets/upload-raw-aliased") @Headers({"hr-path-template: /catalog/datasets/upload-raw-aliased", "Accept: application/json"}) ListenableFuture uploadAliasedRawData( - @Header("Authorization") AuthHeader authHeader, @Body NestedAliasedBinary input); + @Header("Authorization") AuthHeader authHeader, @Body RequestBody input); /** * @param datasetRid A valid dataset resource identifier. From 5c8d3e2ee5345227da2d120cb8be2e0136f11835 Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Wed, 14 Oct 2020 11:19:43 -0400 Subject: [PATCH 10/12] cleanup --- .../java/services/JerseyServiceGenerator.java | 18 +++-- .../services/Retrofit2ServiceGenerator.java | 18 +++-- .../java/services/ServiceGenerator.java | 3 +- .../services/UndertowServiceGenerator.java | 26 +++---- .../UndertowServiceHandlerGenerator.java | 36 +++++---- .../dialogue/DialogueServiceGenerator.java | 31 ++++---- .../java/types/DefaultClassNameVisitor.java | 14 +--- .../conjure/java/types/ErrorGenerator.java | 5 +- .../conjure/java/types/ObjectGenerator.java | 16 ++-- .../SpecializeBinaryClassNameVisitor.java | 10 ++- .../conjure/java/types/TypeGenerator.java | 10 +-- .../conjure/java/types/TypeMapper.java | 14 ++-- .../conjure/java/util/TypeFunctions.java | 73 +++++++++++-------- 13 files changed, 142 insertions(+), 132 deletions(-) diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/JerseyServiceGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/JerseyServiceGenerator.java index 33b5cfd54..86122c6bf 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/JerseyServiceGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/JerseyServiceGenerator.java @@ -26,6 +26,7 @@ import com.palantir.conjure.java.util.Javadoc; import com.palantir.conjure.java.util.Packages; import com.palantir.conjure.java.util.ParameterOrder; +import com.palantir.conjure.java.util.TypeFunctions; import com.palantir.conjure.spec.ArgumentDefinition; import com.palantir.conjure.spec.AuthType; import com.palantir.conjure.spec.ConjureDefinition; @@ -34,6 +35,7 @@ import com.palantir.conjure.spec.ParameterType; import com.palantir.conjure.spec.ServiceDefinition; import com.palantir.conjure.spec.Type; +import com.palantir.conjure.spec.TypeDefinition; import com.palantir.conjure.visitor.AuthTypeVisitor; import com.palantir.conjure.visitor.ParameterTypeVisitor; import com.palantir.conjure.visitor.TypeVisitor; @@ -50,6 +52,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -75,27 +78,26 @@ public JerseyServiceGenerator(Options options) { } @Override - public Set generate(ConjureDefinition conjureDefinition) { + public List generate(ConjureDefinition conjureDefinition) { ClassName binaryReturnType = options.jerseyBinaryAsResponse() ? BINARY_RETURN_TYPE_RESPONSE : BINARY_RETURN_TYPE_OUTPUT; TypeName optionalBinaryReturnType = options.jerseyBinaryAsResponse() ? BINARY_RETURN_TYPE_RESPONSE : OPTIONAL_BINARY_RETURN_TYPE; - ClassNameVisitor defaultVisitor = new DefaultClassNameVisitor(conjureDefinition.getTypes(), options); + Map types = TypeFunctions.toTypesMap(conjureDefinition); + ClassNameVisitor defaultVisitor = new DefaultClassNameVisitor(types.keySet(), options); TypeMapper returnTypeMapper = new TypeMapper( - conjureDefinition.getTypes(), + types, new SpecializeBinaryClassNameVisitor( - defaultVisitor, conjureDefinition.getTypes(), binaryReturnType, optionalBinaryReturnType)); + defaultVisitor, types, binaryReturnType, optionalBinaryReturnType)); TypeMapper argumentTypeMapper = new TypeMapper( - conjureDefinition.getTypes(), - new SpecializeBinaryClassNameVisitor( - defaultVisitor, conjureDefinition.getTypes(), BINARY_ARGUMENT_TYPE)); + types, new SpecializeBinaryClassNameVisitor(defaultVisitor, types, BINARY_ARGUMENT_TYPE)); return conjureDefinition.getServices().stream() .map(serviceDef -> generateService(serviceDef, returnTypeMapper, argumentTypeMapper)) - .collect(Collectors.toSet()); + .collect(Collectors.toList()); } private JavaFile generateService( diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/Retrofit2ServiceGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/Retrofit2ServiceGenerator.java index 74bc8e13b..5012494e4 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/Retrofit2ServiceGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/Retrofit2ServiceGenerator.java @@ -28,6 +28,7 @@ import com.palantir.conjure.java.util.Javadoc; import com.palantir.conjure.java.util.Packages; import com.palantir.conjure.java.util.ParameterOrder; +import com.palantir.conjure.java.util.TypeFunctions; import com.palantir.conjure.spec.ArgumentDefinition; import com.palantir.conjure.spec.ArgumentName; import com.palantir.conjure.spec.AuthType; @@ -37,6 +38,7 @@ import com.palantir.conjure.spec.ParameterId; import com.palantir.conjure.spec.ParameterType; import com.palantir.conjure.spec.ServiceDefinition; +import com.palantir.conjure.spec.TypeDefinition; import com.palantir.conjure.visitor.AuthTypeVisitor; import com.palantir.conjure.visitor.ParameterTypeVisitor; import com.palantir.util.syntacticpath.Path; @@ -52,6 +54,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.regex.Matcher; @@ -83,21 +86,20 @@ public Retrofit2ServiceGenerator(Options options) { } @Override - public Set generate(ConjureDefinition conjureDefinition) { - ClassNameVisitor defaultVisitor = new DefaultClassNameVisitor(conjureDefinition.getTypes(), options); + public List generate(ConjureDefinition conjureDefinition) { + Map types = TypeFunctions.toTypesMap(conjureDefinition); + ClassNameVisitor defaultVisitor = new DefaultClassNameVisitor(types.keySet(), options); TypeMapper returnTypeMapper = new TypeMapper( - conjureDefinition.getTypes(), + types, new SpecializeBinaryClassNameVisitor( - defaultVisitor, conjureDefinition.getTypes(), BINARY_RETURN_TYPE, OPTIONAL_BINARY_RETURN_TYPE)); + defaultVisitor, types, BINARY_RETURN_TYPE, OPTIONAL_BINARY_RETURN_TYPE)); TypeMapper argumentTypeMapper = new TypeMapper( - conjureDefinition.getTypes(), - new SpecializeBinaryClassNameVisitor( - defaultVisitor, conjureDefinition.getTypes(), BINARY_ARGUMENT_TYPE)); + types, new SpecializeBinaryClassNameVisitor(defaultVisitor, types, BINARY_ARGUMENT_TYPE)); return conjureDefinition.getServices().stream() .map(serviceDef -> generateService(serviceDef, returnTypeMapper, argumentTypeMapper)) - .collect(Collectors.toSet()); + .collect(Collectors.toList()); } private JavaFile generateService( diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/ServiceGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/ServiceGenerator.java index e02eb3fb1..365017c2c 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/ServiceGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/ServiceGenerator.java @@ -28,13 +28,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; public abstract class ServiceGenerator { /** Returns the set of Java files generated from the service definitions in the given conjure specification. */ - public abstract Set generate(ConjureDefinition conjureDefinition); + public abstract List generate(ConjureDefinition conjureDefinition); /** * Generates and emits to the given output directory all services and types of the given conjure definition, using diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceGenerator.java index 6685bc66c..17dd2af8f 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceGenerator.java @@ -23,14 +23,16 @@ import com.palantir.conjure.java.types.SpecializeBinaryClassNameVisitor; import com.palantir.conjure.java.types.TypeMapper; import com.palantir.conjure.java.undertow.lib.BinaryResponseBody; +import com.palantir.conjure.java.util.TypeFunctions; import com.palantir.conjure.spec.ConjureDefinition; import com.palantir.conjure.spec.ServiceDefinition; import com.palantir.conjure.spec.TypeDefinition; +import com.palantir.conjure.spec.TypeName; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.JavaFile; import java.io.InputStream; import java.util.List; -import java.util.Set; +import java.util.Map; import java.util.stream.Collectors; public final class UndertowServiceGenerator extends ServiceGenerator { @@ -42,25 +44,23 @@ public UndertowServiceGenerator(Options options) { } @Override - public Set generate(ConjureDefinition conjureDefinition) { - ClassNameVisitor defaultVisitor = new DefaultClassNameVisitor(conjureDefinition.getTypes(), options); - ClassNameVisitor argumentVisitor = new SpecializeBinaryClassNameVisitor( - defaultVisitor, conjureDefinition.getTypes(), ClassName.get(InputStream.class)); - ClassNameVisitor returnVisitor = new SpecializeBinaryClassNameVisitor( - defaultVisitor, conjureDefinition.getTypes(), ClassName.get(BinaryResponseBody.class)); + public List generate(ConjureDefinition conjureDefinition) { + Map types = TypeFunctions.toTypesMap(conjureDefinition); + ClassNameVisitor defaultVisitor = new DefaultClassNameVisitor(types.keySet(), options); + ClassNameVisitor argumentVisitor = + new SpecializeBinaryClassNameVisitor(defaultVisitor, types, ClassName.get(InputStream.class)); + ClassNameVisitor returnVisitor = + new SpecializeBinaryClassNameVisitor(defaultVisitor, types, ClassName.get(BinaryResponseBody.class)); return conjureDefinition.getServices().stream() .flatMap(serviceDef -> generateService( - serviceDef, - conjureDefinition.getTypes(), - new TypeMapper(conjureDefinition.getTypes(), argumentVisitor), - new TypeMapper(conjureDefinition.getTypes(), returnVisitor)) + serviceDef, types, new TypeMapper(types, argumentVisitor), new TypeMapper(types, returnVisitor)) .stream()) - .collect(Collectors.toSet()); + .collect(Collectors.toList()); } private List generateService( ServiceDefinition serviceDefinition, - List typeDefinitions, + Map typeDefinitions, TypeMapper typeMapper, TypeMapper returnTypeMapper) { return ImmutableList.of( diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java index 857967ee8..dffec93d5 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java @@ -109,7 +109,7 @@ final class UndertowServiceHandlerGenerator { public JavaFile generateServiceHandler( ServiceDefinition serviceDefinition, - List typeDefinitions, + Map typeDefinitions, TypeMapper typeMapper, TypeMapper returnTypeMapper) { String serviceName = serviceDefinition.getServiceName().getName(); @@ -205,7 +205,7 @@ private TypeSpec generateEndpointHandler( EndpointDefinition endpointDefinition, ServiceDefinition serviceDefinition, ClassName serviceClass, - List typeDefinitions, + Map typeDefinitions, TypeMapper typeMapper, TypeMapper returnTypeMapper) { MethodSpec.Builder handleMethodBuilder = MethodSpec.methodBuilder("handleRequest") @@ -375,7 +375,7 @@ private TypeName immutableCollection(TypeName input) { private CodeBlock endpointInvocation( EndpointDefinition endpointDefinition, - List typeDefinitions, + Map typeDefinitions, TypeMapper typeMapper, TypeMapper returnTypeMapper) { CodeBlock.Builder code = CodeBlock.builder(); @@ -452,7 +452,8 @@ private CodeBlock endpointInvocation( } private CodeBlock generateReturnValueCodeBlock( - EndpointDefinition endpointDefinition, List typeDefinitions) { + EndpointDefinition endpointDefinition, + Map typeDefinitions) { CodeBlock.Builder code = CodeBlock.builder(); if (endpointDefinition.getReturns().isPresent()) { Type returnType = endpointDefinition.getReturns().get(); @@ -571,7 +572,7 @@ public Optional visitUnknown(String unknownType) { private void addPathParamsCode( CodeBlock.Builder code, EndpointDefinition endpointDefinition, - List typeDefinitions, + Map typeDefinitions, TypeMapper typeMapper) { if (hasPathArgument(endpointDefinition.getArgs())) { code.addStatement( @@ -588,7 +589,7 @@ private void addPathParamsCode( private void addHeaderParamsCode( CodeBlock.Builder code, EndpointDefinition endpointDefinition, - List typeDefinitions, + Map typeDefinitions, TypeMapper typeMapper) { if (hasHeaderArgument(endpointDefinition.getArgs())) { code.addStatement( @@ -603,7 +604,7 @@ private void addHeaderParamsCode( private void addQueryParamsCode( CodeBlock.Builder code, EndpointDefinition endpointDefinition, - List typeDefinitions, + Map typeDefinitions, TypeMapper typeMapper) { if (hasQueryArgument(endpointDefinition.getArgs())) { code.addStatement( @@ -631,7 +632,9 @@ private boolean hasHeaderArgument(List args) { } private CodeBlock generatePathParameterCodeBlock( - EndpointDefinition endpoint, List typeDefinitions, TypeMapper typeMapper) { + EndpointDefinition endpoint, + Map typeDefinitions, + TypeMapper typeMapper) { return generateParameterCodeBlock( endpoint, ParameterTypeVisitor.IS_PATH, @@ -642,7 +645,9 @@ private CodeBlock generatePathParameterCodeBlock( } private CodeBlock generateQueryParameterCodeBlock( - EndpointDefinition endpoint, List typeDefinitions, TypeMapper typeMapper) { + EndpointDefinition endpoint, + Map typeDefinitions, + TypeMapper typeMapper) { return generateParameterCodeBlock( endpoint, ParameterTypeVisitor.IS_QUERY, @@ -656,7 +661,9 @@ private CodeBlock generateQueryParameterCodeBlock( } private CodeBlock generateHeaderParameterCodeBlock( - EndpointDefinition endpoint, List typeDefinitions, TypeMapper typeMapper) { + EndpointDefinition endpoint, + Map typeDefinitions, + TypeMapper typeMapper) { return generateParameterCodeBlock( endpoint, ParameterTypeVisitor.IS_HEADER, @@ -674,7 +681,7 @@ private CodeBlock generateParameterCodeBlock( ParameterType.Visitor paramTypeVisitor, String paramsVarName, Function toParamId, - List typeDefinitions, + Map typeDefinitions, TypeMapper typeMapper) { return CodeBlocks.of(endpoint.getArgs().stream() .filter(param -> param.getParamType().accept(paramTypeVisitor)) @@ -835,7 +842,7 @@ public Optional visitDefault() { * optional. */ private static CodeBlock createIsOptionalPresentCall( - Type inType, String varName, List typeDefinitions) { + Type inType, String varName, Map typeDefinitions) { if (inType.accept(TypeVisitor.IS_OPTIONAL)) { // current type is optional type: call isPresent return CodeBlock.of("$1N.isPresent()", varName); @@ -862,7 +869,10 @@ private static CodeBlock createIsOptionalPresentCall( * these rules (recursive definition). */ private static CodeBlock createConstructorForTypeWithReference( - Type inType, String decodedVarName, List typeDefinitions, TypeMapper typeMapper) { + Type inType, + String decodedVarName, + Map typeDefinitions, + TypeMapper typeMapper) { // "in" must be 1 of 2 types: optional or alias if (inType.accept(TypeVisitor.IS_OPTIONAL)) { // optional diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DialogueServiceGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DialogueServiceGenerator.java index 1c4513a3a..9ef66d12c 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DialogueServiceGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/dialogue/DialogueServiceGenerator.java @@ -21,8 +21,10 @@ import com.palantir.conjure.java.types.DefaultClassNameVisitor; import com.palantir.conjure.java.types.SpecializeBinaryClassNameVisitor; import com.palantir.conjure.java.types.TypeMapper; +import com.palantir.conjure.java.util.TypeFunctions; import com.palantir.conjure.spec.ConjureDefinition; import com.palantir.conjure.spec.TypeDefinition; +import com.palantir.conjure.spec.TypeName; import com.palantir.conjure.visitor.TypeDefinitionVisitor; import com.palantir.dialogue.BinaryRequestBody; import com.palantir.logsafe.Preconditions; @@ -30,8 +32,8 @@ import com.squareup.javapoet.ClassName; import com.squareup.javapoet.JavaFile; import java.io.InputStream; +import java.util.List; import java.util.Map; -import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -46,20 +48,19 @@ public DialogueServiceGenerator(Options options) { } @Override - public Set generate(ConjureDefinition conjureDefinition) { + public List generate(ConjureDefinition conjureDefinition) { + Map types = TypeFunctions.toTypesMap(conjureDefinition); DialogueEndpointsGenerator endpoints = new DialogueEndpointsGenerator(options); TypeMapper parameterTypes = new TypeMapper( - conjureDefinition.getTypes(), + types, new SpecializeBinaryClassNameVisitor( - new DefaultClassNameVisitor(conjureDefinition.getTypes(), options), - conjureDefinition.getTypes(), + new DefaultClassNameVisitor(types.keySet(), options), + types, ClassName.get(BinaryRequestBody.class))); TypeMapper returnTypes = new TypeMapper( - conjureDefinition.getTypes(), + types, new SpecializeBinaryClassNameVisitor( - new DefaultClassNameVisitor(conjureDefinition.getTypes(), options), - conjureDefinition.getTypes(), - ClassName.get(InputStream.class))); + new DefaultClassNameVisitor(types.keySet(), options), types, ClassName.get(InputStream.class))); Map typeDefinitionsByName = conjureDefinition.getTypes().stream() .collect(Collectors.toMap( @@ -78,12 +79,10 @@ public Set generate(ConjureDefinition conjureDefinition) { options, new ParameterTypeMapper(parameterTypes), new ReturnTypeMapper(returnTypes)); return conjureDefinition.getServices().stream() - .flatMap(serviceDef -> { - return Stream.of( - endpoints.endpointsClass(serviceDef), - interfaceGenerator.generateBlocking(serviceDef, blockingGenerator), - interfaceGenerator.generateAsync(serviceDef, asyncGenerator)); - }) - .collect(Collectors.toSet()); + .flatMap(serviceDef -> Stream.of( + endpoints.endpointsClass(serviceDef), + interfaceGenerator.generateBlocking(serviceDef, blockingGenerator), + interfaceGenerator.generateAsync(serviceDef, asyncGenerator))) + .collect(Collectors.toList()); } } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/DefaultClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/DefaultClassNameVisitor.java index 05e96ab12..8f01c802b 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/DefaultClassNameVisitor.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/DefaultClassNameVisitor.java @@ -26,8 +26,6 @@ import com.palantir.conjure.spec.OptionalType; import com.palantir.conjure.spec.PrimitiveType; import com.palantir.conjure.spec.SetType; -import com.palantir.conjure.spec.TypeDefinition; -import com.palantir.conjure.visitor.TypeDefinitionVisitor; import com.palantir.conjure.visitor.TypeVisitor; import com.palantir.ri.ResourceIdentifier; import com.palantir.tokens.auth.BearerToken; @@ -36,13 +34,11 @@ import com.squareup.javapoet.TypeName; import java.nio.ByteBuffer; import java.time.OffsetDateTime; -import java.util.List; import java.util.Optional; import java.util.OptionalDouble; import java.util.OptionalInt; import java.util.Set; import java.util.UUID; -import java.util.stream.Collectors; /** * Maps the conjure type into the 'standard' java type i.e. the type one would use in beans/normal variables (as opposed @@ -50,13 +46,11 @@ */ public final class DefaultClassNameVisitor implements ClassNameVisitor { - private final Set typesByName; + private final Set typeNames; private final Options options; - public DefaultClassNameVisitor(List types, Options options) { - this.typesByName = types.stream() - .map(type -> type.accept(TypeDefinitionVisitor.TYPE_NAME)) - .collect(Collectors.toSet()); + public DefaultClassNameVisitor(Set typeNames, Options options) { + this.typeNames = typeNames; this.options = options; } @@ -144,7 +138,7 @@ public TypeName visitPrimitive(PrimitiveType type) { @Override public TypeName visitReference(com.palantir.conjure.spec.TypeName type) { // Types without namespace are either defined locally in this conjure definition, or raw imports. - if (typesByName.contains(type)) { + if (typeNames.contains(type)) { return ClassName.get( Packages.getPrefixedPackage(type.getPackage(), options.packagePrefix()), type.getName()); } else { diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ErrorGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ErrorGenerator.java index c659b7315..4b609c785 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ErrorGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ErrorGenerator.java @@ -40,7 +40,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -51,7 +50,7 @@ public final class ErrorGenerator { private ErrorGenerator() {} - public static Set generateErrorTypes( + public static List generateErrorTypes( TypeMapper typeMapper, List errorTypeNameToDef, Options options) { return splitErrorDefsByNamespace(errorTypeNameToDef).entrySet().stream() .flatMap(entry -> entry.getValue().entrySet().stream() @@ -60,7 +59,7 @@ public static Set generateErrorTypes( Packages.getPrefixedPackage(entry.getKey(), options.packagePrefix()), innerEntry.getKey(), innerEntry.getValue()))) - .collect(Collectors.toSet()); + .collect(Collectors.toList()); } private static Map>> splitErrorDefsByNamespace( diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ObjectGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ObjectGenerator.java index 3f362956f..cc243e4fa 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ObjectGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/ObjectGenerator.java @@ -16,14 +16,14 @@ package com.palantir.conjure.java.types; -import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableList; import com.palantir.conjure.java.Options; +import com.palantir.conjure.java.util.TypeFunctions; import com.palantir.conjure.spec.ErrorDefinition; import com.palantir.conjure.spec.TypeDefinition; import com.palantir.conjure.visitor.TypeDefinitionVisitor; import com.squareup.javapoet.JavaFile; import java.util.List; -import java.util.Set; import java.util.stream.Collectors; public final class ObjectGenerator implements TypeGenerator { @@ -35,8 +35,8 @@ public ObjectGenerator(Options options) { } @Override - public Set generateTypes(List types) { - TypeMapper typeMapper = new TypeMapper(types, options); + public List generateTypes(List types) { + TypeMapper typeMapper = new TypeMapper(TypeFunctions.toTypesMap(types), options); return types.stream() .map(typeDef -> { @@ -55,16 +55,16 @@ public Set generateTypes(List types) { throw new IllegalArgumentException("Unknown object definition type " + typeDef.getClass()); } }) - .collect(Collectors.toSet()); + .collect(Collectors.toList()); } @Override - public Set generateErrors(List types, List errors) { + public List generateErrors(List types, List errors) { if (errors.isEmpty()) { - return ImmutableSet.of(); + return ImmutableList.of(); } - TypeMapper typeMapper = new TypeMapper(types, options); + TypeMapper typeMapper = new TypeMapper(TypeFunctions.toTypesMap(types), options); return ErrorGenerator.generateErrorTypes(typeMapper, errors, options); } } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java index e1b86eb74..6973bf4d4 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java @@ -28,18 +28,20 @@ import com.squareup.javapoet.ClassName; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; -import java.util.List; +import java.util.Map; import java.util.Optional; public final class SpecializeBinaryClassNameVisitor implements ClassNameVisitor { private final ClassNameVisitor delegate; - private final List types; + private final Map types; private final ClassName binaryClassName; private final TypeName optionalBinaryTypeName; public SpecializeBinaryClassNameVisitor( - ClassNameVisitor delegate, List types, ClassName binaryClassName) { + ClassNameVisitor delegate, + Map types, + ClassName binaryClassName) { this.delegate = delegate; this.types = types; this.binaryClassName = binaryClassName; @@ -48,7 +50,7 @@ public SpecializeBinaryClassNameVisitor( public SpecializeBinaryClassNameVisitor( ClassNameVisitor delegate, - List types, + Map types, ClassName binaryClassName, TypeName optionalBinaryTypeName) { this.delegate = delegate; diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/TypeGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/TypeGenerator.java index 80848e6e6..0e7485105 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/TypeGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/TypeGenerator.java @@ -24,14 +24,12 @@ import java.io.File; import java.nio.file.Path; import java.util.ArrayList; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Set; public interface TypeGenerator { - default Set generate(ConjureDefinition conjureDefinition) { - Set files = new LinkedHashSet<>(); + default List generate(ConjureDefinition conjureDefinition) { + List files = new ArrayList<>(conjureDefinition.getTypes().size()); // Generate java files for type definitions generateTypes(conjureDefinition.getTypes()).forEach(files::add); @@ -56,7 +54,7 @@ default List emit(ConjureDefinition conjureDefinition, File outputDir) { return emittedPaths; } - Set generateTypes(List types); + List generateTypes(List types); - Set generateErrors(List types, List errors); + List generateErrors(List types, List errors); } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/TypeMapper.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/TypeMapper.java index 9eb536a11..edc43eb6e 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/TypeMapper.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/TypeMapper.java @@ -19,26 +19,22 @@ import com.palantir.conjure.java.Options; import com.palantir.conjure.spec.Type; import com.palantir.conjure.spec.TypeDefinition; -import com.palantir.conjure.visitor.TypeDefinitionVisitor; import com.squareup.javapoet.TypeName; -import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; public final class TypeMapper { private final Map types; private final ClassNameVisitor classNameVisitor; - public TypeMapper(List types, Options options) { - this(types, new DefaultClassNameVisitor(types, options)); + public TypeMapper(Map types, Options options) { + this(types, new DefaultClassNameVisitor(types.keySet(), options)); } - public TypeMapper(List types, ClassNameVisitor classNameVisitor) { - this.types = types.stream() - .collect(Collectors.toMap(t -> t.accept(TypeDefinitionVisitor.TYPE_NAME), Function.identity())); + public TypeMapper( + Map types, ClassNameVisitor classNameVisitor) { + this.types = types; this.classNameVisitor = classNameVisitor; } diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java index d3723a093..e1bbb0d57 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java @@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableMap; import com.palantir.conjure.java.visitor.DefaultTypeVisitor; import com.palantir.conjure.spec.AliasDefinition; +import com.palantir.conjure.spec.ConjureDefinition; import com.palantir.conjure.spec.ExternalReference; import com.palantir.conjure.spec.ListType; import com.palantir.conjure.spec.MapType; @@ -27,19 +28,34 @@ import com.palantir.conjure.spec.SetType; import com.palantir.conjure.spec.Type; import com.palantir.conjure.spec.TypeDefinition; +import com.palantir.conjure.spec.TypeName; import com.palantir.conjure.visitor.TypeDefinitionVisitor; import com.palantir.conjure.visitor.TypeVisitor; import com.palantir.logsafe.SafeArg; -import java.util.Collection; +import com.palantir.logsafe.exceptions.SafeIllegalStateException; import java.util.List; +import java.util.Map; import java.util.Optional; public final class TypeFunctions { + private static final ImmutableMap PRIMITIVE_TO_TYPE_NAME = new ImmutableMap.Builder< + PrimitiveType.Value, String>() + .put(PrimitiveType.Value.BEARERTOKEN, "BearerToken") + .put(PrimitiveType.Value.BOOLEAN, "Boolean") + .put(PrimitiveType.Value.DATETIME, "DateTime") + .put(PrimitiveType.Value.DOUBLE, "Double") + .put(PrimitiveType.Value.INTEGER, "Integer") + .put(PrimitiveType.Value.RID, "Rid") + .put(PrimitiveType.Value.SAFELONG, "SafeLong") + .put(PrimitiveType.Value.STRING, "String") + .put(PrimitiveType.Value.UUID, "Uuid") + .build(); + public static boolean isAliasType(Type type) { return type.accept(new IsTypeVisitor() { @Override - public Boolean visitReference(com.palantir.conjure.spec.TypeName _value) { + public Boolean visitReference(TypeName _value) { return true; } }); @@ -65,14 +81,13 @@ public static boolean isCollectionType(Type type) { // Returns the type that the given alias type refers to. For example, if the input type is defined as // "alias: integer", the returned type will be the type for "integer". The provided type must be an alias // (reference) type. - public static Type getAliasedType(Type type, List typeDefinitions) { + public static Type getAliasedType(Type type, Map typeDefinitions) { com.palantir.logsafe.Preconditions.checkArgument( isAliasType(type), "Expected an alias", SafeArg.of("type", type)); return getAliasedType( - type.accept(new AbstractTypeVisitor() { + type.accept(new AbstractTypeVisitor() { @Override - public com.palantir.conjure.spec.TypeName visitReference( - com.palantir.conjure.spec.TypeName value) { + public TypeName visitReference(TypeName value) { return value; } }), @@ -80,18 +95,12 @@ public com.palantir.conjure.spec.TypeName visitReference( .get(); } - public static Optional getAliasedType( - com.palantir.conjure.spec.TypeName typeName, Collection typeDefinitions) { + public static Optional getAliasedType(TypeName typeName, Map typeDefinitions) { // return type definition for the provided alias type - TypeDefinition typeDefinition = typeDefinitions.stream() - .filter(typeDef -> { - com.palantir.conjure.spec.TypeName currName = typeDef.accept(TypeDefinitionVisitor.TYPE_NAME); - String currClassName = currName.getPackage() + "." + currName.getName(); - return currClassName.equals(typeName.getPackage() + "." + typeName.getName()); - }) - .findFirst() - .get(); - + TypeDefinition typeDefinition = typeDefinitions.get(typeName); + if (typeDefinition == null) { + throw new SafeIllegalStateException("Failed to find definition for type", SafeArg.of("name", typeName)); + } if (typeDefinition.accept(TypeDefinitionVisitor.IS_ALIAS)) { AliasDefinition aliasDefinition = typeDefinition.accept(TypeDefinitionVisitor.ALIAS); return Optional.of(aliasDefinition.getAlias()); @@ -99,19 +108,6 @@ public static Optional getAliasedType( return Optional.empty(); } - private static final ImmutableMap PRIMITIVE_TO_TYPE_NAME = new ImmutableMap.Builder< - PrimitiveType.Value, String>() - .put(PrimitiveType.Value.BEARERTOKEN, "BearerToken") - .put(PrimitiveType.Value.BOOLEAN, "Boolean") - .put(PrimitiveType.Value.DATETIME, "DateTime") - .put(PrimitiveType.Value.DOUBLE, "Double") - .put(PrimitiveType.Value.INTEGER, "Integer") - .put(PrimitiveType.Value.RID, "Rid") - .put(PrimitiveType.Value.SAFELONG, "SafeLong") - .put(PrimitiveType.Value.STRING, "String") - .put(PrimitiveType.Value.UUID, "Uuid") - .build(); - public static String primitiveTypeName(PrimitiveType in) { String typeName = PRIMITIVE_TO_TYPE_NAME.get(in.get()); if (typeName == null) { @@ -120,7 +116,8 @@ public static String primitiveTypeName(PrimitiveType in) { return typeName; } - public static Type toConjureTypeWithoutAliases(final Type in, final Collection typeDefinitions) { + public static Type toConjureTypeWithoutAliases( + final Type in, final Map typeDefinitions) { return in.accept(new Type.Visitor() { @Override public Type visitPrimitive(PrimitiveType _value) { @@ -151,7 +148,7 @@ public Type visitMap(MapType value) { } @Override - public Type visitReference(com.palantir.conjure.spec.TypeName value) { + public Type visitReference(TypeName value) { return getAliasedType(value, typeDefinitions) .map(aliasedType -> toConjureTypeWithoutAliases(aliasedType, typeDefinitions)) .orElse(in); @@ -169,6 +166,18 @@ public Type visitUnknown(String _unknownType) { }); } + public static Map toTypesMap(ConjureDefinition definition) { + return toTypesMap(definition.getTypes()); + } + + public static Map toTypesMap( + List typeDefinitions) { + ImmutableMap.Builder builder = + ImmutableMap.builderWithExpectedSize(typeDefinitions.size()); + typeDefinitions.forEach(def -> builder.put(def.accept(TypeDefinitionVisitor.TYPE_NAME), def)); + return builder.build(); + } + public static final GetTypeVisitor PRIMITIVE_VISITOR = new GetTypeVisitor() { @Override public PrimitiveType visitPrimitive(PrimitiveType value) { From 20719ea631521bf47583138f2f4ba2902a4efcd4 Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Wed, 14 Oct 2020 11:37:23 -0400 Subject: [PATCH 11/12] cleanup --- .../UndertowServiceHandlerGenerator.java | 4 +-- .../SpecializeBinaryClassNameVisitor.java | 9 ++--- .../conjure/java/util/TypeFunctions.java | 34 +++++++++++-------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java index dffec93d5..024792f93 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java @@ -691,7 +691,7 @@ private CodeBlock generateParameterCodeBlock( final CodeBlock retrieveParam; if (normalizedType.equals(arg.getType()) // Collections of alias types are handled the same way as external imports - || TypeFunctions.isCollectionType(arg.getType())) { + || TypeFunctions.isListOrSet(arg.getType())) { // type is not an alias or optional of an alias retrieveParam = decodePlainParameterCodeBlock( arg.getType(), typeMapper, paramName, paramsVarName, toParamId.apply(arg)); @@ -846,7 +846,7 @@ private static CodeBlock createIsOptionalPresentCall( if (inType.accept(TypeVisitor.IS_OPTIONAL)) { // current type is optional type: call isPresent return CodeBlock.of("$1N.isPresent()", varName); - } else if (TypeFunctions.isAliasType(inType)) { + } else if (TypeFunctions.isReferenceType(inType)) { // current type is an alias type: call "get()" to resolve alias and generate recursively on aliased type Type aliasedType = TypeFunctions.getAliasedType(inType, typeDefinitions); return createIsOptionalPresentCall(aliasedType, varName + ".get()", typeDefinitions); diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java index 6973bf4d4..00f9e2e9f 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java @@ -42,10 +42,11 @@ public SpecializeBinaryClassNameVisitor( ClassNameVisitor delegate, Map types, ClassName binaryClassName) { - this.delegate = delegate; - this.types = types; - this.binaryClassName = binaryClassName; - this.optionalBinaryTypeName = ParameterizedTypeName.get(ClassName.get(Optional.class), binaryClassName); + this( + delegate, + types, + binaryClassName, + ParameterizedTypeName.get(ClassName.get(Optional.class), binaryClassName)); } public SpecializeBinaryClassNameVisitor( diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java index e1bbb0d57..567454ba6 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java @@ -52,29 +52,19 @@ public final class TypeFunctions { .put(PrimitiveType.Value.UUID, "Uuid") .build(); - public static boolean isAliasType(Type type) { - return type.accept(new IsTypeVisitor() { - @Override - public Boolean visitReference(TypeName _value) { - return true; - } - }); + public static boolean isReferenceType(Type type) { + return type.accept(IS_REFERENCE_VISITOR); } public static boolean isOptionalBinary(Type type) { - return type.accept(new IsTypeVisitor() { - @Override - public Boolean visitOptional(OptionalType value) { - return value.getItemType().accept(TypeVisitor.IS_BINARY); - } - }); + return type.accept(IS_OPTIONAL_BINARY_VISITOR); } public static boolean isBinaryOrOptionalBinary(Type type) { return type.accept(TypeVisitor.IS_BINARY) || isOptionalBinary(type); } - public static boolean isCollectionType(Type type) { + public static boolean isListOrSet(Type type) { return type.accept(TypeVisitor.IS_LIST) || type.accept(TypeVisitor.IS_SET); } @@ -83,7 +73,7 @@ public static boolean isCollectionType(Type type) { // (reference) type. public static Type getAliasedType(Type type, Map typeDefinitions) { com.palantir.logsafe.Preconditions.checkArgument( - isAliasType(type), "Expected an alias", SafeArg.of("type", type)); + isReferenceType(type), "Expected an alias", SafeArg.of("type", type)); return getAliasedType( type.accept(new AbstractTypeVisitor() { @Override @@ -192,6 +182,20 @@ public OptionalType visitOptional(OptionalType value) { } }; + public static final IsTypeVisitor IS_REFERENCE_VISITOR = new IsTypeVisitor() { + @Override + public Boolean visitReference(TypeName _value) { + return true; + } + }; + + public static final IsTypeVisitor IS_OPTIONAL_BINARY_VISITOR = new IsTypeVisitor() { + @Override + public Boolean visitOptional(OptionalType value) { + return value.getItemType().accept(TypeVisitor.IS_BINARY); + } + }; + private abstract static class GetTypeVisitor extends DefaultTypeVisitor { @Override public T visitUnknown(String _unknownType) { From 34310041a78127bf41b4c105954814918395c11b Mon Sep 17 00:00:00 2001 From: Carter Kozak Date: Wed, 14 Oct 2020 11:40:30 -0400 Subject: [PATCH 12/12] renames --- .../services/UndertowServiceHandlerGenerator.java | 4 ++-- .../java/types/SpecializeBinaryClassNameVisitor.java | 2 +- .../palantir/conjure/java/util/TypeFunctions.java | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java index 024792f93..a9d225a67 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/services/UndertowServiceHandlerGenerator.java @@ -848,7 +848,7 @@ private static CodeBlock createIsOptionalPresentCall( return CodeBlock.of("$1N.isPresent()", varName); } else if (TypeFunctions.isReferenceType(inType)) { // current type is an alias type: call "get()" to resolve alias and generate recursively on aliased type - Type aliasedType = TypeFunctions.getAliasedType(inType, typeDefinitions); + Type aliasedType = TypeFunctions.getReferencedType(inType, typeDefinitions); return createIsOptionalPresentCall(aliasedType, varName + ".get()", typeDefinitions); } else { throw new IllegalArgumentException("inType must be either an optional or alias type, was " + inType); @@ -892,7 +892,7 @@ private static CodeBlock createConstructorForTypeWithReference( // * optional // * optional // * alias that follows one of these rules (recursive definition) - Type aliasedType = TypeFunctions.getAliasedType(inType, typeDefinitions); + Type aliasedType = TypeFunctions.getReferencedType(inType, typeDefinitions); if (aliasedType.accept(TypeVisitor.IS_PRIMITIVE) || aliasedType.accept(MoreVisitors.IS_EXTERNAL)) { // primitive ofContent = CodeBlock.of("$1N", decodedVarName); diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java index 00f9e2e9f..eddb83ebc 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/SpecializeBinaryClassNameVisitor.java @@ -88,7 +88,7 @@ public TypeName visitPrimitive(PrimitiveType type) { @Override public TypeName visitReference(com.palantir.conjure.spec.TypeName typeName) { - return TypeFunctions.getAliasedType(typeName, types) + return TypeFunctions.getReferencedType(typeName, types) .flatMap(this::dealiasBinary) .map(value -> value.accept(SpecializeBinaryClassNameVisitor.this)) .orElseGet(() -> delegate.visitReference(typeName)); diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java index 567454ba6..b4ec7092e 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/util/TypeFunctions.java @@ -68,13 +68,13 @@ public static boolean isListOrSet(Type type) { return type.accept(TypeVisitor.IS_LIST) || type.accept(TypeVisitor.IS_SET); } - // Returns the type that the given alias type refers to. For example, if the input type is defined as + // Returns the type that the given reference type refers to. For example, if the input type is defined as // "alias: integer", the returned type will be the type for "integer". The provided type must be an alias // (reference) type. - public static Type getAliasedType(Type type, Map typeDefinitions) { + public static Type getReferencedType(Type type, Map typeDefinitions) { com.palantir.logsafe.Preconditions.checkArgument( - isReferenceType(type), "Expected an alias", SafeArg.of("type", type)); - return getAliasedType( + isReferenceType(type), "Expected a reference", SafeArg.of("type", type)); + return getReferencedType( type.accept(new AbstractTypeVisitor() { @Override public TypeName visitReference(TypeName value) { @@ -85,7 +85,7 @@ public TypeName visitReference(TypeName value) { .get(); } - public static Optional getAliasedType(TypeName typeName, Map typeDefinitions) { + public static Optional getReferencedType(TypeName typeName, Map typeDefinitions) { // return type definition for the provided alias type TypeDefinition typeDefinition = typeDefinitions.get(typeName); if (typeDefinition == null) { @@ -139,7 +139,7 @@ public Type visitMap(MapType value) { @Override public Type visitReference(TypeName value) { - return getAliasedType(value, typeDefinitions) + return getReferencedType(value, typeDefinitions) .map(aliasedType -> toConjureTypeWithoutAliases(aliasedType, typeDefinitions)) .orElse(in); }