Skip to content

Commit

Permalink
Support generic params (#1874)
Browse files Browse the repository at this point in the history
  • Loading branch information
ricksurya authored Aug 26, 2022
1 parent b814c3e commit ab48801
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -167,15 +167,15 @@ public Optional<ParameterType> getParameterType(VariableElement variableElement,
if (annotationReflector.isAnnotation(Handle.Body.class)) {
return Optional.of(bodyParameter(variableElement, annotationReflector, safeLoggable));
} else if (annotationReflector.isAnnotation(Handle.Header.class)) {
return Optional.of(headerParameter(variableElement, annotationReflector, safeLoggable));
return Optional.of(headerParameter(variableElement, parameterType, annotationReflector, safeLoggable));
} else if (annotationReflector.isAnnotation(Handle.PathParam.class)) {
return Optional.of(pathParameter(variableElement, annotationReflector, safeLoggable));
return Optional.of(pathParameter(variableElement, annotationReflector, safeLoggable, parameterType));
} else if (annotationReflector.isAnnotation(Handle.PathMultiParam.class)) {
return Optional.of(pathMultiParameter(variableElement, annotationReflector, safeLoggable));
return Optional.of(pathMultiParameter(variableElement, parameterType, annotationReflector, safeLoggable));
} else if (annotationReflector.isAnnotation(Handle.QueryParam.class)) {
return Optional.of(queryParameter(variableElement, annotationReflector, safeLoggable));
return Optional.of(queryParameter(variableElement, parameterType, annotationReflector, safeLoggable));
} else if (annotationReflector.isAnnotation(Handle.Cookie.class)) {
return cookieParameter(variableElement, annotationReflector, safeLoggable);
return cookieParameter(variableElement, parameterType, annotationReflector, safeLoggable);
}

throw new SafeIllegalStateException("Not possible");
Expand All @@ -194,6 +194,7 @@ private ParameterType bodyParameter(

private ParameterType headerParameter(
VariableElement variableElement,
TypeMirror parameterType,
AnnotationReflector annotationReflector,
SafeLoggingAnnotation safeLoggable) {
String javaParameterName = variableElement.getSimpleName().toString();
Expand All @@ -202,38 +203,41 @@ private ParameterType headerParameter(
javaParameterName,
annotationReflector.getAnnotationValue(String.class),
deserializerName,
getCollectionParamDecoder(variableElement, annotationReflector),
getCollectionParamDecoder(variableElement, parameterType, annotationReflector),
safeLoggable);
}

private ParameterType pathParameter(
VariableElement variableElement,
AnnotationReflector annotationReflector,
SafeLoggingAnnotation safeLoggable) {
SafeLoggingAnnotation safeLoggable,
TypeMirror parameterType) {
String javaParameterName = variableElement.getSimpleName().toString();
String deserializerName = InstanceVariables.joinCamelCase(javaParameterName, "Deserializer");
return ParameterTypes.path(
javaParameterName,
deserializerName,
getParamDecoder(variableElement, annotationReflector),
getParamDecoder(variableElement, parameterType, annotationReflector),
safeLoggable);
}

private ParameterType pathMultiParameter(
VariableElement variableElement,
TypeMirror parameterType,
AnnotationReflector annotationReflector,
SafeLoggingAnnotation safeLoggable) {
String javaParameterName = variableElement.getSimpleName().toString();
String deserializerName = InstanceVariables.joinCamelCase(javaParameterName, "Deserializer");
return ParameterTypes.pathMulti(
javaParameterName,
deserializerName,
getCollectionParamDecoder(variableElement, annotationReflector),
getCollectionParamDecoder(variableElement, parameterType, annotationReflector),
safeLoggable);
}

private ParameterType queryParameter(
VariableElement variableElement,
TypeMirror parameterType,
AnnotationReflector annotationReflector,
SafeLoggingAnnotation safeLoggable) {
String javaParameterName = variableElement.getSimpleName().toString();
Expand All @@ -243,12 +247,13 @@ private ParameterType queryParameter(
javaParameterName,
annotationReflector.getAnnotationValue(String.class),
deserializerName,
getCollectionParamDecoder(variableElement, annotationReflector),
getCollectionParamDecoder(variableElement, parameterType, annotationReflector),
safeLoggable);
}

private Optional<ParameterType> cookieParameter(
VariableElement variableElement,
TypeMirror parameterType,
AnnotationReflector annotationReflector,
SafeLoggingAnnotation safeLoggable) {
String javaParameterName = variableElement.getSimpleName().toString();
Expand All @@ -270,21 +275,21 @@ private Optional<ParameterType> cookieParameter(
javaParameterName,
annotationReflector.getAnnotationValue(String.class),
deserializerName,
getParamDecoder(variableElement, annotationReflector),
getParamDecoder(variableElement, parameterType, annotationReflector),
safeLoggable));
}

private CodeBlock getParamDecoder(VariableElement variableElement, AnnotationReflector annotationReflector) {
private CodeBlock getParamDecoder(
VariableElement variableElement, TypeMirror parameterType, AnnotationReflector annotationReflector) {
// If the default marker interface is not used (overwritten by user), we want to use the user-provided decoder.
TypeMirror typeMirror = annotationReflector.getAnnotationValue("decoder", TypeMirror.class);
if (!context.isSameTypes(typeMirror, DefaultParamDecoder.class)) {
return Instantiables.instantiate(typeMirror);
}

TypeMirror variableType = variableElement.asType();
// For param decoders, we don't support list and set container types.
Optional<TypeMirror> innerOptionalType = context.getGenericInnerType(Optional.class, variableType);
TypeMirror decoderType = innerOptionalType.orElse(variableType);
Optional<TypeMirror> innerOptionalType = context.getGenericInnerType(Optional.class, parameterType);
TypeMirror decoderType = innerOptionalType.orElse(parameterType);
ContainerType decoderOutputType = getOutputType(Optional.empty(), Optional.empty(), innerOptionalType);

return getDefaultDecoderFactory(decoderType, ContainerType.NONE, decoderOutputType)
Expand All @@ -293,27 +298,26 @@ private CodeBlock getParamDecoder(VariableElement variableElement, AnnotationRef
"No default decoder exists for parameter. "
+ "Types with a valueOf(String) method are supported, as are conjure types",
variableElement,
SafeArg.of("variableType", variableType),
SafeArg.of("variableType", parameterType),
SafeArg.of("supportedTypes", SUPPORTED_CLASSES));
return CodeBlock.of("// error");
});
}

private CodeBlock getCollectionParamDecoder(
VariableElement variableElement, AnnotationReflector annotationReflector) {
VariableElement variableElement, TypeMirror parameterType, AnnotationReflector annotationReflector) {
// If the default marker interface is not used (overwritten by user), we want to use the user-provided decoder.
TypeMirror typeMirror = annotationReflector.getAnnotationValue("decoder", TypeMirror.class);
if (!context.isSameTypes(typeMirror, DefaultParamDecoder.class)) {
return Instantiables.instantiate(typeMirror);
}

TypeMirror variableType = variableElement.asType();
Optional<TypeMirror> innerListType = context.getGenericInnerType(List.class, variableType);
Optional<TypeMirror> innerSetType = context.getGenericInnerType(Set.class, variableType);
Optional<TypeMirror> innerOptionalType = context.getGenericInnerType(Optional.class, variableType);
Optional<TypeMirror> innerListType = context.getGenericInnerType(List.class, parameterType);
Optional<TypeMirror> innerSetType = context.getGenericInnerType(Set.class, parameterType);
Optional<TypeMirror> innerOptionalType = context.getGenericInnerType(Optional.class, parameterType);

TypeMirror decoderType =
innerListType.or(() -> innerSetType).or(() -> innerOptionalType).orElse(variableType);
innerListType.or(() -> innerSetType).or(() -> innerOptionalType).orElse(parameterType);
ContainerType decoderOutputType = getOutputType(innerListType, innerSetType, innerOptionalType);

return getDefaultDecoderFactory(decoderType, ContainerType.LIST, decoderOutputType)
Expand All @@ -322,7 +326,7 @@ private CodeBlock getCollectionParamDecoder(
"No default decoder exists for parameter. "
+ "Types with a valueOf(String) method are supported, as are conjure types",
variableElement,
SafeArg.of("variableType", variableType),
SafeArg.of("variableType", parameterType),
SafeArg.of("supportedTypes", SUPPORTED_CLASSES));
return CodeBlock.of("// error");
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@

import com.palantir.conjure.java.undertow.annotations.Handle;
import com.palantir.conjure.java.undertow.annotations.Handle.Body;
import com.palantir.conjure.java.undertow.annotations.Handle.PathParam;
import com.palantir.conjure.java.undertow.annotations.Handle.QueryParam;
import com.palantir.conjure.java.undertow.annotations.HttpMethod;

@Handle.Generate(false)
public interface GenericIface<I, O> {
public interface GenericIface<TBody, TQueryParam, TPathParam, TReturn> {

@Handle(method = HttpMethod.POST, path = "/generic")
O generic(@Body I input);
TReturn generic(
@Body TBody input,
@PathParam TPathParam pathParam,
@QueryParam(value = "queryParam") TQueryParam queryParam);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@
package com.palantir.conjure.java.undertow.processor.sample;

import com.palantir.conjure.java.undertow.annotations.Handle;
import com.palantir.conjure.java.undertow.processor.sample.GenericImpl.ParamExample;

@Handle.Generate
public interface GenericImpl extends GenericIface<String, Integer> {}
public interface GenericImpl extends GenericIface<String, Integer, ParamExample, Boolean> {
class ParamExample {
String value;

public ParamExample(String value) {
this.value = value;
}

public static ParamExample valueOf(String value) {
return new ParamExample(value);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit ab48801

Please sign in to comment.