Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
import com.google.common.collect.Lists;
import com.palantir.conjure.java.ConjureAnnotations;
import com.palantir.conjure.java.FeatureFlags;
import com.palantir.conjure.java.types.JerseyMethodTypeClassNameVisitor;
import com.palantir.conjure.java.types.JerseyReturnTypeClassNameVisitor;
import com.palantir.conjure.java.types.BinaryResolvingClassNameVisitor;
import com.palantir.conjure.java.types.TypeMapper;
import com.palantir.conjure.spec.ArgumentDefinition;
import com.palantir.conjure.spec.AuthType;
Expand Down Expand Up @@ -53,6 +52,7 @@
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeSpec;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -65,9 +65,12 @@
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.lang.model.element.Modifier;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import org.apache.commons.lang3.StringUtils;

public final class JerseyServiceGenerator implements ServiceGenerator {

private static final ClassName NOT_NULL = ClassName.get("javax.validation.constraints", "NotNull");

private final Set<FeatureFlags> experimentalFeatures;
Expand All @@ -82,11 +85,15 @@ public JerseyServiceGenerator(Set<FeatureFlags> experimentalFeatures) {

@Override
public Set<JavaFile> generate(ConjureDefinition conjureDefinition) {
Class<?> binaryReturnType = experimentalFeatures.contains(FeatureFlags.JerseyBinaryAsResponse)
? Response.class
: StreamingOutput.class;
TypeMapper returnTypeMapper = new TypeMapper(
conjureDefinition.getTypes(),
types -> new JerseyReturnTypeClassNameVisitor(types, experimentalFeatures));
BinaryResolvingClassNameVisitor.createFactory(binaryReturnType));
TypeMapper methodTypeMapper = new TypeMapper(
conjureDefinition.getTypes(), JerseyMethodTypeClassNameVisitor::new);
conjureDefinition.getTypes(),
BinaryResolvingClassNameVisitor.createFactory(InputStream.class));
return conjureDefinition.getServices().stream()
.map(serviceDef -> generateService(serviceDef, returnTypeMapper, methodTypeMapper))
.collect(Collectors.toSet());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
import com.google.common.collect.Lists;
import com.palantir.conjure.java.ConjureAnnotations;
import com.palantir.conjure.java.FeatureFlags;
import com.palantir.conjure.java.types.Retrofit2MethodTypeClassNameVisitor;
import com.palantir.conjure.java.types.Retrofit2ReturnTypeClassNameVisitor;
import com.palantir.conjure.java.types.BinaryResolvingClassNameVisitor;
import com.palantir.conjure.java.types.TypeMapper;
import com.palantir.conjure.spec.ArgumentDefinition;
import com.palantir.conjure.spec.ArgumentName;
Expand All @@ -47,6 +46,7 @@
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import java.util.List;
import java.util.Optional;
Expand All @@ -68,8 +68,8 @@ public final class Retrofit2ServiceGenerator implements ServiceGenerator {
private static final ClassName CALL_TYPE = ClassName.get("retrofit2", "Call");
private static final String AUTH_HEADER_NAME = "Authorization";

private static final String JSON_MEDIA_TYPE = MediaType.APPLICATION_JSON;
private static final String OCTET_STREAM_MEDIA_TYPE = MediaType.APPLICATION_OCTET_STREAM;
private static final ClassName BINARY_METHOD_TYPE = ClassName.get("okhttp3", "RequestBody");
private static final ClassName BINARY_RETURN_TYPE = ClassName.get("okhttp3", "ResponseBody");

private static final Logger log = LoggerFactory.getLogger(Retrofit2ServiceGenerator.class);

Expand All @@ -85,10 +85,12 @@ public Retrofit2ServiceGenerator(Set<FeatureFlags> experimentalFeatures) {

@Override
public Set<JavaFile> generate(ConjureDefinition conjureDefinition) {
TypeMapper returnTypeMapper =
new TypeMapper(conjureDefinition.getTypes(), Retrofit2ReturnTypeClassNameVisitor::new);
TypeMapper methodTypeMapper =
new TypeMapper(conjureDefinition.getTypes(), Retrofit2MethodTypeClassNameVisitor::new);
TypeMapper returnTypeMapper = new TypeMapper(
conjureDefinition.getTypes(),
BinaryResolvingClassNameVisitor.createFactory(BINARY_RETURN_TYPE));
TypeMapper methodTypeMapper = new TypeMapper(
conjureDefinition.getTypes(),
BinaryResolvingClassNameVisitor.createFactory(BINARY_METHOD_TYPE));
return conjureDefinition.getServices().stream()
.map(serviceDef -> generateService(serviceDef, returnTypeMapper, methodTypeMapper))
.collect(Collectors.toSet());
Expand Down Expand Up @@ -131,25 +133,23 @@ private MethodSpec generateServiceMethod(
EndpointDefinition endpointDef,
TypeMapper returnTypeMapper,
TypeMapper methodTypeMapper) {
TypeName returnType = endpointDef.getReturns()
.map(returnTypeMapper::getClassName)
.orElse(ClassName.VOID);

Set<ArgumentName> encodedPathArgs = extractEncodedPathArgs(endpointDef.getHttpPath());
HttpPath endpointPathWithoutRegex = replaceEncodedPathArgs(endpointDef.getHttpPath());
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(endpointDef.getEndpointName().get())
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addAnnotation(AnnotationSpec.builder(httpMethodToClassName(endpointDef.getHttpMethod().get().name()))
.addMember("value", "$S", "." + endpointPathWithoutRegex)
.build())
.addAnnotation(AnnotationSpec.builder(ClassName.get("retrofit2.http", "Headers"))
.addMember("value", "$S", "hr-path-template: " + endpointPathWithoutRegex)
.addMember("value", "$S", "Accept: " + getReturnMediaType(returnType))
.build());

AnnotationSpec.Builder headersBuilder = AnnotationSpec.builder(ClassName.get("retrofit2.http", "Headers"))
.addMember("value", "$S", "hr-path-template: " + endpointPathWithoutRegex);
endpointDef.getReturns().ifPresent(type -> {
String mediaType = type.accept(TypeVisitor.IS_BINARY)
? MediaType.APPLICATION_OCTET_STREAM
: MediaType.APPLICATION_JSON;
headersBuilder.addMember("value", "$S", "Accept: " + mediaType);
});
methodBuilder.addAnnotation(headersBuilder.build());

if (endpointDef.getReturns().map(type -> type.accept(TypeVisitor.IS_BINARY)).orElse(false)) {
if (returnType.equals(BINARY_RETURN_TYPE)) {
methodBuilder.addAnnotation(AnnotationSpec.builder(ClassName.get("retrofit2.http", "Streaming")).build());
}

Expand All @@ -159,13 +159,7 @@ private MethodSpec generateServiceMethod(
ServiceGenerator.getJavaDoc(endpointDef).ifPresent(
content -> methodBuilder.addJavadoc("$L", content));

if (endpointDef.getReturns().isPresent()) {
methodBuilder.returns(
ParameterizedTypeName.get(getReturnType(),
returnTypeMapper.getClassName(endpointDef.getReturns().get()).box()));
} else {
methodBuilder.returns(ParameterizedTypeName.get(getReturnType(), ClassName.get(Void.class)));
}
methodBuilder.returns(ParameterizedTypeName.get(getReturnType(), returnType.box()));

getAuthParameter(endpointDef.getAuth()).ifPresent(methodBuilder::addParameter);

Expand Down Expand Up @@ -260,6 +254,12 @@ private Optional<ParameterSpec> getAuthParameter(Optional<AuthType> auth) {
throw new IllegalStateException("Unrecognized auth type: " + auth.get());
}

private static String getReturnMediaType(TypeName returnType) {
return returnType.equals(BINARY_RETURN_TYPE)
? MediaType.APPLICATION_OCTET_STREAM
: MediaType.APPLICATION_JSON;
}

private static Set<AnnotationSpec> createMarkers(TypeMapper typeMapper, List<Type> markers) {
checkArgument(markers.stream().allMatch(type -> type.accept(TypeVisitor.IS_REFERENCE)),
"Markers must refer to reference types.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@

package com.palantir.conjure.java.types;

import com.palantir.conjure.java.util.BinaryReturnTypeResolver;
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.squareup.javapoet.ClassName;
Expand All @@ -32,17 +32,26 @@
import java.util.function.Function;
import java.util.stream.Collectors;

public final class Retrofit2ReturnTypeClassNameVisitor implements ClassNameVisitor {

private static final ClassName RESPONSE_BODY_TYPE = ClassName.get("okhttp3", "ResponseBody");
public final class BinaryResolvingClassNameVisitor implements ClassNameVisitor {

private final DefaultClassNameVisitor delegate;
private final Map<com.palantir.conjure.spec.TypeName, TypeDefinition> types;
private final ClassName binaryClassName;

public static Factory createFactory(Class<?> binaryClass) {
return createFactory(ClassName.get(binaryClass));
}

public static Factory createFactory(ClassName binaryClassName) {
return types -> new BinaryResolvingClassNameVisitor(types, binaryClassName);
}

public Retrofit2ReturnTypeClassNameVisitor(List<TypeDefinition> types) {
this.types = types.stream().collect(
Collectors.toMap(t -> t.accept(TypeDefinitionVisitor.TYPE_NAME), Function.identity()));
private BinaryResolvingClassNameVisitor(List<TypeDefinition> types, ClassName binaryClassName) {
this.delegate = new DefaultClassNameVisitor(types);
this.types = types.stream().collect(Collectors.toMap(
t -> t.accept(TypeDefinitionVisitor.TYPE_NAME),
Function.identity()));
this.binaryClassName = binaryClassName;
}

@Override
Expand All @@ -63,15 +72,28 @@ public TypeName visitOptional(OptionalType type) {
@Override
public TypeName visitPrimitive(PrimitiveType type) {
if (type.get() == PrimitiveType.Value.BINARY) {
return RESPONSE_BODY_TYPE;
return binaryClassName;
} else {
return delegate.visitPrimitive(type);
}
}

@Override
public TypeName visitReference(com.palantir.conjure.spec.TypeName type) {
return BinaryReturnTypeResolver.resolveReturnReferenceType(types, type, RESPONSE_BODY_TYPE);
if (!types.containsKey(type)) {
throw new IllegalStateException("Unknown LocalReferenceType type: " + type);
}

TypeDefinition def = types.get(type);
if (def.accept(TypeDefinitionVisitor.IS_ALIAS)) {
Type aliasType = def.accept(TypeDefinitionVisitor.ALIAS).getAlias();
TypeName aliasClassName = aliasType.accept(this);
if (aliasClassName.equals(binaryClassName)) {
return binaryClassName;
}
}

return delegate.visitReference(type);
}

@Override
Expand All @@ -83,5 +105,4 @@ public TypeName visitExternal(ExternalReference type) {
public TypeName visitSet(SetType type) {
return delegate.visitSet(type);
}

}

This file was deleted.

Loading