Skip to content

Commit 9b36524

Browse files
authored
Use map factory in getValues (#1097)
1 parent c3c2993 commit 9b36524

File tree

4 files changed

+44
-10
lines changed

4 files changed

+44
-10
lines changed

cdi/src/main/java/io/smallrye/config/inject/ConfigProducerUtil.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ private static <T> Converter<T> resolveConverter(final Type type, final SmallRye
172172
return (Converter<T>) newCollectionConverter(resolveConverter(typeArgs[0], config), HashSet::new);
173173
} else if (rawType == Map.class) {
174174
return (Converter<T>) newMapConverter(resolveConverter(typeArgs[0], config),
175-
resolveConverter(typeArgs[1], config));
175+
resolveConverter(typeArgs[1], config), HashMap::new);
176176
} else if (rawType == Optional.class) {
177177
return (Converter<T>) newOptionalConverter(resolveConverter(typeArgs[0], config));
178178
} else if (rawType == Supplier.class) {

implementation/src/main/java/io/smallrye/config/Converters.java

+17-5
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,15 @@ public static <A, T> Converter<A> newArrayConverter(Converter<? extends T> itemC
322322
* @param <V> the type of the values
323323
* @return the new converter (not {@code null})
324324
*/
325+
@Deprecated
325326
public static <K, V> Converter<Map<K, V>> newMapConverter(Converter<? extends K> keyConverter,
326327
Converter<? extends V> valueConverter) {
327-
return new MapConverter<>(keyConverter, valueConverter);
328+
return newMapConverter(keyConverter, valueConverter, HashMap::new);
329+
}
330+
331+
public static <K, V> Converter<Map<K, V>> newMapConverter(Converter<? extends K> keyConverter,
332+
Converter<? extends V> valueConverter, IntFunction<Map<K, V>> mapFactory) {
333+
return new MapConverter<>(keyConverter, valueConverter, mapFactory);
328334
}
329335

330336
/**
@@ -1037,25 +1043,31 @@ static class MapConverter<K, V> extends AbstractConverter<Map<K, V>> {
10371043
* The converter to use the for values.
10381044
*/
10391045
private final Converter<? extends V> valueConverter;
1046+
private final IntFunction<Map<K, V>> mapFactory;
10401047

10411048
/**
10421049
* Construct a {@code MapConverter} with the given converters.
10431050
*
10441051
* @param keyConverter the converter to use the for keys
10451052
* @param valueConverter the converter to use the for values
1053+
* @param mapFactory
10461054
*/
1047-
MapConverter(Converter<? extends K> keyConverter, Converter<? extends V> valueConverter) {
1055+
MapConverter(
1056+
final Converter<? extends K> keyConverter,
1057+
final Converter<? extends V> valueConverter,
1058+
final IntFunction<Map<K, V>> mapFactory) {
10481059
this.keyConverter = keyConverter;
10491060
this.valueConverter = valueConverter;
1061+
this.mapFactory = mapFactory;
10501062
}
10511063

10521064
@Override
10531065
public Map<K, V> convert(String value) throws IllegalArgumentException, NullPointerException {
10541066
if (value == null) {
10551067
return null;
10561068
}
1057-
final Map<K, V> map = new HashMap<>();
1058-
final StringBuilder currentLine = new StringBuilder(value.length());
1069+
Map<K, V> map = mapFactory.apply(0);
1070+
StringBuilder currentLine = new StringBuilder(value.length());
10591071
int fromIndex = 0;
10601072
for (int idx; (idx = value.indexOf(';', fromIndex)) >= 0; fromIndex = idx + 1) {
10611073
if (value.charAt(idx - 1) == '\\') {
@@ -1082,7 +1094,7 @@ public Map<K, V> convert(String value) throws IllegalArgumentException, NullPoin
10821094
* @throws NoSuchElementException if the line could not be converted into an entry or doesn't have the expected format.
10831095
*/
10841096
private void processLine(Map<K, V> map, String value, String rawLine) {
1085-
final String line = rawLine.replace("\\;", ";");
1097+
String line = rawLine.replace("\\;", ";");
10861098
for (int idx, fromIndex = 0; (idx = line.indexOf('=', fromIndex)) >= 0; fromIndex = idx + 1) {
10871099
if (line.charAt(idx - 1) == '\\') {
10881100
// The key separator has been escaped

implementation/src/main/java/io/smallrye/config/SmallRyeConfig.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ public <K, V> Map<K, V> getValues(
215215
Converter<V> valueConverter,
216216
IntFunction<Map<K, V>> mapFactory) {
217217
try {
218-
return getValue(name, newMapConverter(keyConverter, valueConverter));
218+
return getValue(name, newMapConverter(keyConverter, valueConverter, mapFactory));
219219
} catch (NoSuchElementException e) {
220220
Map<String, String> mapKeys = getMapKeys(name);
221221
if (mapKeys.isEmpty()) {
@@ -246,7 +246,8 @@ public <K, V, C extends Collection<V>> Map<K, C> getValues(
246246
IntFunction<Map<K, C>> mapFactory,
247247
IntFunction<C> collectionFactory) {
248248
try {
249-
return getValue(name, newMapConverter(keyConverter, newCollectionConverter(valueConverter, collectionFactory)));
249+
return getValue(name,
250+
newMapConverter(keyConverter, newCollectionConverter(valueConverter, collectionFactory), mapFactory));
250251
} catch (NoSuchElementException e) {
251252
Map<String, String> mapCollectionKeys = getMapKeys(name);
252253
if (mapCollectionKeys.isEmpty()) {
@@ -463,7 +464,7 @@ public <K, V> Optional<Map<K, V>> getOptionalValues(String name, Converter<K> ke
463464

464465
public <K, V> Optional<Map<K, V>> getOptionalValues(String name, Converter<K> keyConverter, Converter<V> valueConverter,
465466
IntFunction<Map<K, V>> mapFactory) {
466-
Optional<Map<K, V>> optionalValue = getOptionalValue(name, newMapConverter(keyConverter, valueConverter));
467+
Optional<Map<K, V>> optionalValue = getOptionalValue(name, newMapConverter(keyConverter, valueConverter, mapFactory));
467468
if (optionalValue.isPresent()) {
468469
return optionalValue;
469470
}
@@ -491,7 +492,7 @@ public <K, V, C extends Collection<V>> Optional<Map<K, C>> getOptionalValues(
491492
IntFunction<Map<K, C>> mapFactory,
492493
IntFunction<C> collectionFactory) {
493494
Optional<Map<K, C>> optionalValue = getOptionalValue(name,
494-
newMapConverter(keyConverter, newCollectionConverter(valueConverter, collectionFactory)));
495+
newMapConverter(keyConverter, newCollectionConverter(valueConverter, collectionFactory), mapFactory));
495496
if (optionalValue.isPresent()) {
496497
return optionalValue;
497498
}

implementation/src/test/java/io/smallrye/config/SmallRyeConfigTest.java

+21
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121
import java.util.NoSuchElementException;
2222
import java.util.Optional;
2323
import java.util.Set;
24+
import java.util.TreeMap;
2425
import java.util.function.IntFunction;
2526

2627
import org.eclipse.microprofile.config.Config;
2728
import org.eclipse.microprofile.config.spi.ConfigSource;
29+
import org.eclipse.microprofile.config.spi.Converter;
2830
import org.junit.jupiter.api.Test;
2931

3032
import io.smallrye.config.common.AbstractConfigSource;
@@ -377,13 +379,22 @@ void getValuesMap() {
377379
assertEquals("value", map.get("key.nested"));
378380
assertEquals("value", map.get("key.quoted"));
379381

382+
Converter<String> stringConverter = config.requireConverter(String.class);
383+
Map<String, String> treeMap = config.getValues("my.prop", stringConverter, stringConverter, t -> new TreeMap<>());
384+
assertTrue(treeMap instanceof TreeMap);
385+
380386
Optional<Map<String, String>> optionalMap = config.getOptionalValues("my.prop", String.class, String.class);
381387
assertTrue(optionalMap.isPresent());
382388
assertEquals(3, optionalMap.get().size());
383389
assertEquals("value", optionalMap.get().get("key"));
384390
assertEquals("value", optionalMap.get().get("key.nested"));
385391
assertEquals("value", optionalMap.get().get("key.quoted"));
386392

393+
Optional<Map<String, String>> optionalTreeMap = config.getOptionalValues("my.prop", stringConverter, stringConverter,
394+
t -> new TreeMap<>());
395+
assertTrue(optionalTreeMap.isPresent());
396+
assertTrue(optionalTreeMap.get() instanceof TreeMap);
397+
387398
assertTrue(config.getOptionalValues("my.optional", String.class, String.class).isEmpty());
388399
}
389400

@@ -428,6 +439,11 @@ void getValuesMapList() {
428439
assertEquals("value", map.get("key.quoted").get(0));
429440
assertEquals("value", map.get("key.quoted").get(1));
430441

442+
Converter<String> stringConverter = config.requireConverter(String.class);
443+
Map<String, List<String>> treeMap = config.getValues("my.prop", stringConverter, stringConverter, t -> new TreeMap<>(),
444+
ArrayList::new);
445+
assertTrue(treeMap instanceof TreeMap);
446+
431447
Optional<Map<String, List<String>>> optionalMap = config.getOptionalValues("my.prop", String.class, String.class,
432448
ArrayList::new);
433449
assertTrue(optionalMap.isPresent());
@@ -439,6 +455,11 @@ void getValuesMapList() {
439455
assertEquals("value", optionalMap.get().get("key.quoted").get(0));
440456
assertEquals("value", optionalMap.get().get("key.quoted").get(1));
441457

458+
Optional<Map<String, List<String>>> optionalTreeMap = config.getOptionalValues("my.prop", stringConverter,
459+
stringConverter, t -> new TreeMap<>(), ArrayList::new);
460+
assertTrue(optionalTreeMap.isPresent());
461+
assertTrue(optionalTreeMap.get() instanceof TreeMap);
462+
442463
assertTrue(config.getOptionalValues("my.optional", String.class, String.class, ArrayList::new).isEmpty());
443464
}
444465

0 commit comments

Comments
 (0)