Skip to content

Commit

Permalink
Allow null map values in ModelIO#toLinkedMap collector
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Edgar <[email protected]>
Co-authored-by: Andrew Rouse <[email protected]>
  • Loading branch information
MikeEdgar and Azquelt committed Jul 7, 2024
1 parent 7cbdf4a commit aba26e8
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 2 deletions.
23 changes: 21 additions & 2 deletions core/src/main/java/io/smallrye/openapi/runtime/io/ModelIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Predicate;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
Expand Down Expand Up @@ -139,7 +140,25 @@ protected static <T> Predicate<T> not(Predicate<? super T> predicate) {
}

protected static <T> Collector<Map.Entry<String, T>, ?, Map<String, T>> toLinkedMap() {
return Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1, LinkedHashMap::new);
BiConsumer<Map<String, T>, Map.Entry<String, T>> accumulator = (map, entry) -> {
String k = entry.getKey();
T v = entry.getValue();

if (map.containsKey(k)) {
throw new IllegalStateException(String.format(
"Duplicate key %s (attempted merging values %s and %s)",
k, map.get(k), v));
}

map.put(k, v);
};

BinaryOperator<Map<String, T>> combiner = (m1, m2) -> {
m2.entrySet().forEach(entry -> accumulator.accept(m1, entry));
return m1;
};

return Collector.of(LinkedHashMap::new, accumulator, combiner);
}

public AnnotationInstance getAnnotation(AnnotationTarget target) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.smallrye.openapi.runtime.io.security;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.microprofile.openapi.annotations.enums.SecuritySchemeType;
import org.eclipse.microprofile.openapi.annotations.security.OAuthFlow;
import org.eclipse.microprofile.openapi.annotations.security.OAuthFlows;
import org.eclipse.microprofile.openapi.annotations.security.OAuthScope;
import org.eclipse.microprofile.openapi.annotations.security.SecurityScheme;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassInfo;
import org.junit.jupiter.api.Test;

import io.smallrye.openapi.api.models.OpenAPIImpl;
import io.smallrye.openapi.runtime.io.IOContext;
import io.smallrye.openapi.runtime.scanner.FilteredIndexView;
import io.smallrye.openapi.runtime.scanner.IndexScannerTestBase;
import io.smallrye.openapi.runtime.scanner.spi.AnnotationScannerContext;

class SecuritySchemeIOTest extends IndexScannerTestBase {

@Test
void testReadFlow() {
FilteredIndexView index = new FilteredIndexView(IndexScannerTestBase.indexOf(Endpoint1.class), emptyConfig());

AnnotationScannerContext context = new AnnotationScannerContext(index, Thread.currentThread().getContextClassLoader(),
Collections.emptyList(),
emptyConfig(), new OpenAPIImpl());

ClassInfo clazz = index.getClassByName(Endpoint1.class);
AnnotationInstance annotation = clazz.annotation(SecurityScheme.class);
AnnotationInstance flowAnnotation = annotation
.value("flows").asNested()
.value("implicit").asNested();
AnnotationInstance scopeAnnotation = flowAnnotation
.value("scopes").asNestedArray()[0];

IOContext<?, ?, ?, ?, ?> ioContext = IOContext.forScanning(context);

OAuthScopeIO<?, ?, ?, ?, ?> scopeIO = ioContext.oauthScopeIO();
String value = scopeIO.read(scopeAnnotation);
assertNull(value);

OAuthFlowIO<?, ?, ?, ?, ?> flowIO = ioContext.oauthFlowIO();
org.eclipse.microprofile.openapi.models.security.OAuthFlow flow = flowIO.read(flowAnnotation);
Map<String, String> expected = new HashMap<>();
expected.put("foo", null);
assertEquals(expected, flow.getScopes());
}

@SecurityScheme(securitySchemeName = "OAuth2Authorization",
type = SecuritySchemeType.OAUTH2,
description = "authentication needed to delete a profile",
flows = @OAuthFlows(implicit = @OAuthFlow(authorizationUrl = "https://example.com",
scopes = @OAuthScope(name = "foo"))))
static class Endpoint1 {
}
}

0 comments on commit aba26e8

Please sign in to comment.