Skip to content

Commit 5275aa5

Browse files
committed
Eliminate duplicate param processing, replace more streams with loops
Signed-off-by: Michael Edgar <[email protected]>
1 parent bc965b2 commit 5275aa5

File tree

11 files changed

+127
-103
lines changed

11 files changed

+127
-103
lines changed

core/src/main/java/io/smallrye/openapi/api/constants/KotlinConstants.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
*/
1010
public class KotlinConstants {
1111

12+
public static final DotName METADATA = DotName
13+
.createSimple("kotlin.Metadata");
14+
1215
public static final DotName CONTINUATION = DotName
1316
.createSimple("kotlin.coroutines.Continuation");
1417

core/src/main/java/io/smallrye/openapi/runtime/scanner/spi/AbstractParameterProcessor.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.Set;
2020
import java.util.concurrent.ConcurrentHashMap;
2121
import java.util.function.Consumer;
22-
import java.util.function.Function;
2322
import java.util.function.Predicate;
2423
import java.util.function.Supplier;
2524
import java.util.regex.Matcher;
@@ -78,7 +77,6 @@ public abstract class AbstractParameterProcessor {
7877
protected final AnnotationScannerContext scannerContext;
7978
protected final String contextPath;
8079
protected final IndexView index;
81-
protected final Function<AnnotationInstance, Parameter> readerFunction;
8280
protected final Optional<BeanValidationScanner> beanValidationScanner;
8381
protected final ClassInfo resourceClass;
8482
protected final MethodInfo resourceMethod;
@@ -114,13 +112,11 @@ public abstract class AbstractParameterProcessor {
114112

115113
protected AbstractParameterProcessor(AnnotationScannerContext scannerContext,
116114
String contextPath,
117-
Function<AnnotationInstance, Parameter> reader,
118115
ClassInfo resourceClass,
119116
MethodInfo resourceMethod) {
120117
this.scannerContext = scannerContext;
121118
this.contextPath = contextPath;
122119
this.index = scannerContext.getIndex();
123-
this.readerFunction = reader;
124120
this.beanValidationScanner = scannerContext.getBeanValidationScanner();
125121
this.resourceClass = resourceClass;
126122
this.resourceMethod = resourceMethod;
@@ -300,7 +296,7 @@ protected void reset() {
300296
matrixParams.clear();
301297
}
302298

303-
protected ResourceParameters process() {
299+
public ResourceParameters process() {
304300

305301
ResourceParameters parameters = new ResourceParameters();
306302

@@ -397,6 +393,10 @@ protected void processFinalize(ClassInfo resourceClass, MethodInfo resourceMetho
397393
parameters.setFormBodyContent(getFormBodyContent());
398394
}
399395

396+
public void updateFormBodyContent(ResourceParameters parameters) {
397+
parameters.setFormBodyContent(getFormBodyContent());
398+
}
399+
400400
/**
401401
* Generate the paths for the provided annotation target, either a class or a method.
402402
* Add the name of any discovered matrix parameters.
@@ -1265,11 +1265,11 @@ List<String> methodPaths(MethodInfo method) {
12651265
protected abstract List<String> pathsOf(AnnotationTarget target);
12661266

12671267
protected boolean isReadableParameterAnnotation(DotName name) {
1268-
return Names.PARAMETER.equals(name) && readerFunction != null;
1268+
return Names.PARAMETER.equals(name);
12691269
}
12701270

12711271
protected void readParameterAnnotation(AnnotationInstance annotation, boolean overriddenParametersOnly) {
1272-
Parameter oaiParam = readerFunction.apply(annotation);
1272+
Parameter oaiParam = scannerContext.io().parameterIO().read(annotation);
12731273

12741274
if (oaiParam.getRef() != null) {
12751275
Parameter commonParam = ModelUtil.dereference(scannerContext.getOpenApi(), oaiParam);

core/src/main/java/io/smallrye/openapi/runtime/util/Annotations.java

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package io.smallrye.openapi.runtime.util;
22

3+
import java.util.ArrayList;
34
import java.util.Arrays;
45
import java.util.Collection;
6+
import java.util.Collections;
57
import java.util.EnumMap;
68
import java.util.HashSet;
79
import java.util.List;
@@ -74,8 +76,17 @@ private static Collection<AnnotationInstance> getDeclaredAnnotations(AnnotationT
7476
private static List<AnnotationInstance> declaredFieldAnnotations(FieldInfo field) {
7577
List<AnnotationInstance> fieldAnnotations = field.declaredAnnotations();
7678
List<AnnotationInstance> propertyAnnotations = KotlinUtil.getPropertyAnnotations(field);
77-
return Stream.concat(fieldAnnotations.stream(), propertyAnnotations.stream())
78-
.collect(Collectors.toList());
79+
80+
if (propertyAnnotations.isEmpty()) {
81+
return fieldAnnotations;
82+
} else if (fieldAnnotations.isEmpty()) {
83+
return propertyAnnotations;
84+
} else {
85+
List<AnnotationInstance> results = new ArrayList<>(fieldAnnotations.size() + propertyAnnotations.size());
86+
results.addAll(fieldAnnotations);
87+
results.addAll(propertyAnnotations);
88+
return results;
89+
}
7990
}
8091

8192
private boolean composable(DotName annotation) {
@@ -90,47 +101,56 @@ private boolean composable(DotName annotation) {
90101
return true;
91102
}
92103

93-
private Stream<AnnotationInstance> getComposedAnnotation(Collection<AnnotationInstance> declaredAnnotations,
104+
private List<AnnotationInstance> getComposedAnnotation(Collection<AnnotationInstance> declaredAnnotations,
94105
DotName name,
95106
Set<DotName> scanned) {
96107

97-
return declaredAnnotations
98-
.stream()
99-
.filter(AnnotationInstance::runtimeVisible)
100-
.map(AnnotationInstance::name)
101-
.filter(this::composable)
102-
.map(context.getAugmentedIndex()::getClassByName)
103-
.filter(Objects::nonNull)
104-
.flatMap(annotationClass -> {
105-
if (scanned.contains(annotationClass.name())) {
106-
return null;
108+
List<AnnotationInstance> results = new ArrayList<>();
109+
110+
for (AnnotationInstance annotation : declaredAnnotations) {
111+
if (annotation.runtimeVisible()) {
112+
DotName annotationName = annotation.name();
113+
if (composable(annotationName)) {
114+
ClassInfo annotationClass = context.getAugmentedIndex().getClassByName(annotationName);
115+
if (annotationClass == null || scanned.contains(annotationClass.name())) {
116+
continue;
107117
}
108118

109119
scanned.add(annotationClass.name());
110120
UtilLogging.logger.composedAnnotationSearch(name, annotationClass.name());
111-
return getDeclaredAnnotation(annotationClass, name, scanned);
112-
})
113-
.filter(Objects::nonNull);
121+
results.addAll(getDeclaredAnnotation(annotationClass, name, scanned));
122+
}
123+
}
124+
}
125+
126+
return results;
114127
}
115128

116-
private Stream<AnnotationInstance> getDeclaredAnnotation(AnnotationTarget target, DotName name, Set<DotName> scanned) {
129+
private List<AnnotationInstance> getDeclaredAnnotation(AnnotationTarget target, DotName name, Set<DotName> scanned) {
117130
if (target == null) {
118-
return Stream.empty();
131+
return Collections.emptyList();
119132
}
120133

121134
Collection<AnnotationInstance> declaredAnnotations = getDeclaredAnnotations(target);
122135

123136
if (declaredAnnotations.isEmpty()) {
124-
return Stream.empty();
137+
return Collections.emptyList();
125138
}
126139

127-
Stream<AnnotationInstance> direct = declaredAnnotations.stream().filter(a -> name.equals(a.name()));
128-
Stream<AnnotationInstance> composed = getComposedAnnotation(declaredAnnotations, name, scanned);
140+
AnnotationInstance direct = declaredAnnotations.stream().filter(a -> name.equals(a.name())).findFirst().orElse(null);
141+
Collection<AnnotationInstance> composed = getComposedAnnotation(declaredAnnotations, name, scanned);
142+
143+
List<AnnotationInstance> results = new ArrayList<>((direct != null ? 1 : 0) + composed.size());
144+
145+
if (direct != null) {
146+
results.add(direct);
147+
}
148+
results.addAll(composed);
129149

130-
return Stream.concat(direct, composed);
150+
return results;
131151
}
132152

133-
private Stream<AnnotationInstance> getDeclaredAnnotation(AnnotationTarget target, DotName name) {
153+
private List<AnnotationInstance> getDeclaredAnnotation(AnnotationTarget target, DotName name) {
134154
return getDeclaredAnnotation(target, name, new HashSet<>());
135155
}
136156

@@ -285,14 +305,15 @@ public List<AnnotationInstance> getRepeatableAnnotation(AnnotationTarget target,
285305
DotName singleAnnotationName,
286306
DotName repeatableAnnotationName) {
287307

288-
Stream<AnnotationInstance> single = getDeclaredAnnotation(target, singleAnnotationName);
308+
List<AnnotationInstance> single = getDeclaredAnnotation(target, singleAnnotationName);
289309
Stream<AnnotationInstance> wrapped = getDeclaredAnnotation(target, repeatableAnnotationName)
310+
.stream()
290311
.map(a -> this.<AnnotationInstance[]> value(a, VALUE))
291312
.filter(Objects::nonNull)
292313
.flatMap(Arrays::stream)
293314
.map(a -> AnnotationInstance.create(a.name(), target, a.values()));
294315

295-
return Stream.concat(single, wrapped).collect(Collectors.toList());
316+
return Stream.concat(single.stream(), wrapped).collect(Collectors.toList());
296317
}
297318

298319
/**
@@ -306,9 +327,10 @@ public List<AnnotationInstance> getRepeatableAnnotation(AnnotationTarget target,
306327
*/
307328
public AnnotationInstance getMethodParameterAnnotation(MethodInfo method, int parameterIndex,
308329
DotName annotationName) {
309-
return getDeclaredAnnotation(MethodParameterInfo.create(method, (short) parameterIndex), annotationName)
310-
.findFirst()
311-
.orElse(null);
330+
331+
AnnotationTarget target = MethodParameterInfo.create(method, (short) parameterIndex);
332+
List<AnnotationInstance> found = getDeclaredAnnotation(target, annotationName);
333+
return found.isEmpty() ? null : found.get(0);
312334
}
313335

314336
/**
@@ -364,10 +386,14 @@ public AnnotationInstance getAnnotation(AnnotationTarget annotationTarget, DotNa
364386
}
365387

366388
public AnnotationInstance getAnnotation(AnnotationTarget annotationTarget, Collection<DotName> annotationNames) {
367-
return annotationNames.stream()
368-
.flatMap(annotationName -> getDeclaredAnnotation(annotationTarget, annotationName))
369-
.findFirst()
370-
.orElse(null);
389+
for (DotName annotationName : annotationNames) {
390+
List<AnnotationInstance> found = getDeclaredAnnotation(annotationTarget, annotationName);
391+
if (!found.isEmpty()) {
392+
return found.get(0);
393+
}
394+
}
395+
396+
return null;
371397
}
372398

373399
/**

core/src/main/java/io/smallrye/openapi/runtime/util/KotlinUtil.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import org.jboss.jandex.FieldInfo;
1111
import org.jboss.jandex.MethodInfo;
1212

13+
import io.smallrye.openapi.api.constants.KotlinConstants;
14+
1315
/**
1416
* Some utility methods for working with Kotlin types.
1517
*
@@ -53,6 +55,10 @@ private static Optional<MethodInfo> getSyntheticPropertyAnnotationsMethod(FieldI
5355
* @return List of annotations declared on the Kotlin property, retargeted at the field
5456
*/
5557
static List<AnnotationInstance> getPropertyAnnotations(FieldInfo field) {
58+
if (!field.declaringClass().hasAnnotation(KotlinConstants.METADATA)) {
59+
return Collections.emptyList();
60+
}
61+
5662
return getSyntheticPropertyAnnotationsMethod(field)
5763
.map(methodInfo -> methodInfo.annotations().stream()
5864
.filter(a -> methodInfo.equals(a.target()))

extension-jaxrs/src/main/java/io/smallrye/openapi/jaxrs/JaxRsAnnotationScanner.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import java.util.Set;
1919
import java.util.TreeSet;
2020
import java.util.function.BinaryOperator;
21-
import java.util.function.Function;
2221
import java.util.function.Predicate;
2322
import java.util.stream.Collectors;
2423
import java.util.stream.Stream;
@@ -472,15 +471,21 @@ private void processResourceMethod(final ClassInfo resourceClass,
472471

473472
JaxRsLogging.log.processingMethod(method.toString());
474473

474+
JaxRsParameterProcessor paramProc = new JaxRsParameterProcessor(context, currentAppPath, resourceClass, method);
475+
ResourceParameters params = paramProc.process();
476+
475477
// Figure out the current @Produces and @Consumes (if any)
476-
String[] defaultConsumes = getDefaultConsumes(context, method, getResourceParameters(resourceClass, method));
478+
String[] defaultConsumes = getDefaultConsumes(context, method, params);
477479
context.setDefaultConsumes(defaultConsumes);
478480
context.setCurrentConsumes(getMediaTypes(method, JaxRsConstants.CONSUMES, defaultConsumes).orElse(null));
479481

480482
String[] defaultProduces = getDefaultProduces(context, method);
481483
context.setDefaultProduces(defaultProduces);
482484
context.setCurrentProduces(getMediaTypes(method, JaxRsConstants.PRODUCES, defaultProduces).orElse(null));
483485

486+
// Form body content requires context#currentConsumes, which itself requires a first pass of parameter processing
487+
paramProc.updateFormBodyContent(params);
488+
484489
// Process any @Operation annotation
485490
Optional<Operation> maybeOperation = processOperation(context, resourceClass, method);
486491
if (!maybeOperation.isPresent()) {
@@ -492,7 +497,6 @@ private void processResourceMethod(final ClassInfo resourceClass,
492497
processOperationTags(context, method, context.getOpenApi(), resourceTags, operation);
493498

494499
// Process @Parameter annotations.
495-
ResourceParameters params = getResourceParameters(resourceClass, method);
496500
List<Parameter> operationParams = params.getOperationParameters();
497501
operation.setParameters(operationParams);
498502
if (locatorPathParameters != null && operationParams != null) {
@@ -552,9 +556,7 @@ private void processResourceMethod(final ClassInfo resourceClass,
552556
}
553557

554558
private ResourceParameters getResourceParameters(final ClassInfo resourceClass, final MethodInfo method) {
555-
Function<AnnotationInstance, Parameter> reader = t -> context.io().parameterIO().read(t);
556-
return JaxRsParameterProcessor.process(context, currentAppPath, resourceClass, method,
557-
reader);
559+
return JaxRsParameterProcessor.process(context, currentAppPath, resourceClass, method);
558560
}
559561

560562
/**

extension-jaxrs/src/main/java/io/smallrye/openapi/jaxrs/JaxRsConstants.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import java.util.Arrays;
44
import java.util.Collections;
5-
import java.util.HashMap;
5+
import java.util.EnumMap;
66
import java.util.LinkedHashSet;
77
import java.util.Map;
88
import java.util.Set;
@@ -12,6 +12,8 @@
1212

1313
import org.eclipse.microprofile.openapi.models.PathItem;
1414
import org.eclipse.microprofile.openapi.models.PathItem.HttpMethod;
15+
import org.jboss.jandex.AnnotationInstance;
16+
import org.jboss.jandex.AnnotationValue;
1517
import org.jboss.jandex.DotName;
1618

1719
/**
@@ -120,9 +122,18 @@ public class JaxRsConstants {
120122
methods.addAll(PATCH);
121123
}
122124

125+
public static final Set<DotName> HTTP_METHODS = Collections
126+
.unmodifiableSet(methods);
127+
128+
private static final AnnotationValue[] EMPTY_VALUES = new AnnotationValue[0];
129+
public static final Set<AnnotationInstance> HTTP_METHOD_INSTANCES = methods
130+
.stream()
131+
.map(name -> AnnotationInstance.create(name, null, EMPTY_VALUES))
132+
.collect(Collectors.toUnmodifiableSet());
133+
123134
public static final Map<PathItem.HttpMethod, Set<DotName>> HTTP_METHOD_ANNOTATIONS;
124135
static {
125-
Map<PathItem.HttpMethod, Set<DotName>> annotations = new HashMap<>();
136+
Map<PathItem.HttpMethod, Set<DotName>> annotations = new EnumMap<>(PathItem.HttpMethod.class);
126137
annotations.put(HttpMethod.DELETE, DELETE);
127138
annotations.put(HttpMethod.GET, GET);
128139
annotations.put(HttpMethod.HEAD, HEAD);
@@ -133,9 +144,6 @@ public class JaxRsConstants {
133144
HTTP_METHOD_ANNOTATIONS = Collections.unmodifiableMap(annotations);
134145
}
135146

136-
public static final Set<DotName> HTTP_METHODS = Collections
137-
.unmodifiableSet(methods);
138-
139147
private JaxRsConstants() {
140148
}
141149

0 commit comments

Comments
 (0)