Skip to content

Commit 3c52410

Browse files
Added Configurator findStringMatchMultiMap overload that takes a preserveOrder flag (#1062)
1 parent ddcd85e commit 3c52410

File tree

3 files changed

+98
-3
lines changed

3 files changed

+98
-3
lines changed

src/main/java/emissary/config/Configurator.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,22 @@ public interface Configurator {
8181
Map<String, String> findStringMatchMap(String param, boolean preserveCase, boolean preserveOrder);
8282

8383
/**
84-
* Find all entry keys that begin with the specified string Remaining key portion is upper cased
84+
* Find all entry keys that begin with the specified string Remaining key portion is upper-cased
8585
*
8686
* @param theParameter the parameter the leading key startsWith
8787
* @return map with remaining key portion as key, value as a set of multiple values
8888
*/
8989
Map<String, Set<String>> findStringMatchMultiMap(final String theParameter);
9090

91+
/**
92+
* Find all entry keys that begin with the specified string Remaining key portion is upper-cased
93+
*
94+
* @param theParameter the parameter the leading key startsWith
95+
* @param preserveOrder ordering of keys is preserved
96+
* @return map with remaining key portion as key, value as a set of multiple values
97+
*/
98+
Map<String, Set<String>> findStringMatchMultiMap(final String theParameter, boolean preserveOrder);
99+
91100

92101
String findRequiredStringEntry(String theParameter);
93102

src/main/java/emissary/config/ServiceConfigGuide.java

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.HashSet;
2727
import java.util.Iterator;
2828
import java.util.LinkedHashMap;
29+
import java.util.LinkedHashSet;
2930
import java.util.List;
3031
import java.util.Locale;
3132
import java.util.Map;
@@ -829,12 +830,44 @@ public Map<String, String> findStringMatchMap(@Nullable final String theParamete
829830
*/
830831
@Override
831832
public Map<String, Set<String>> findStringMatchMultiMap(@Nullable final String param) {
833+
if (param == null) {
834+
return Map.of();
835+
}
836+
837+
return findStringMatchMultiMap(param, false);
838+
}
839+
840+
/**
841+
* Find entries beginning with the specified string and return a hash keyed on the remainder of the string with the
842+
* value of the config line as the value of the hash Multiple values for the same hash are allowed and returned as a
843+
* Set.
844+
*
845+
* <pre>
846+
* {@code
847+
* Example config entries
848+
* FOO_ONE: AAA
849+
* FOO_TWO: BBB
850+
* FOO_TWO: CCC
851+
* Calling findStringMatchMap("FOO_",true)
852+
* will yield a map with Sets
853+
* ONE -> {AAA}
854+
* TWO -> {BBB,CCC}
855+
* }
856+
* </pre>
857+
*
858+
* @param param the key to look for in the config file
859+
* @param preserveOrder ordering of keys is preserved
860+
* @return map where key is remainder after match and value is a Set of all found config values, or an empty map if none
861+
* found
862+
*/
863+
@Override
864+
public Map<String, Set<String>> findStringMatchMultiMap(@Nullable final String param, final boolean preserveOrder) {
832865

833866
if (param == null) {
834867
return Map.of();
835868
}
836869

837-
final Map<String, Set<String>> theHash = new HashMap<>();
870+
final Map<String, Set<String>> theHash = preserveOrder ? new LinkedHashMap<>() : new HashMap<>();
838871
final List<ConfigEntry> parameters = this.findStringMatchEntries(param);
839872

840873
for (final ConfigEntry el : parameters) {
@@ -843,12 +876,13 @@ public Map<String, Set<String>> findStringMatchMultiMap(@Nullable final String p
843876
if (theHash.containsKey(key)) {
844877
theHash.get(key).add(el.getValue());
845878
} else {
846-
final Set<String> values = new HashSet<>();
879+
final Set<String> values = preserveOrder ? new LinkedHashSet<>() : new HashSet<>();
847880
values.add(el.getValue());
848881
theHash.put(key, values);
849882
}
850883
}
851884
return theHash;
885+
852886
}
853887

854888
/**

src/test/java/emissary/config/ServiceConfigGuideTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
import java.nio.file.Path;
2020
import java.nio.file.Paths;
2121
import java.util.ArrayList;
22+
import java.util.LinkedHashMap;
23+
import java.util.LinkedHashSet;
2224
import java.util.List;
25+
import java.util.Locale;
2326
import java.util.Map;
2427
import java.util.Set;
2528
import java.util.stream.Stream;
@@ -645,4 +648,53 @@ void testFindRequiredStringEntry() {
645648
assertNotNull(ex.getMessage(), "Exception message should not be null");
646649
assertTrue(ex.getMessage().contains(missingProp), "Exception message should name the missing config entry");
647650
}
651+
652+
@Test
653+
void testFindStringMatchMultiMapOrdered() {
654+
// this test fails if ORDERED is set to false due to results ordering
655+
final boolean ORDERED = true;
656+
657+
final ServiceConfigGuide config = new ServiceConfigGuide();
658+
659+
final String prefix = "MM_";
660+
final String key1 = "key1";
661+
final String key2 = "key2";
662+
final String key3 = "key3";
663+
final String value1 = "_value1";
664+
final String value2 = "_value2";
665+
final String value3 = "_value3";
666+
List<String> suffixes = List.of(value1, value2, value3);
667+
List<String> keys = List.of(key1, key2, key3);
668+
669+
670+
Map<String, Set<String>> expected = new LinkedHashMap<>();
671+
for (String k : keys) {
672+
for (String s : suffixes) {
673+
String key = prefix + k;
674+
String value = k + s;
675+
// add prefixed entry to config
676+
config.addEntry(key, value);
677+
// add non-prefixed entry to expected map (prefix gets stripped during findStringMatchMultiMap call)
678+
// UPPERCASE the key to match findStringMatchMultiMap retrieval behavior
679+
expected.computeIfAbsent(k.toUpperCase(Locale.getDefault()), v -> new LinkedHashSet<>()).add(value);
680+
}
681+
}
682+
Map<String, Set<String>> actual = config.findStringMatchMultiMap(prefix, ORDERED);
683+
assertFalse(actual.isEmpty(), "did not find any multi-map entries");
684+
assertEquals(expected.size(), actual.size(), "should have the same number of keys");
685+
var actualsIterator = actual.entrySet().iterator();
686+
var expectedIterator = expected.entrySet().iterator();
687+
int i = 0;
688+
while (expectedIterator.hasNext()) {
689+
assertTrue(actualsIterator.hasNext());
690+
691+
i++;
692+
var expectedEntry = expectedIterator.next();
693+
var actualEntry = actualsIterator.next();
694+
assertEquals(expectedEntry.getKey(), actualEntry.getKey(), "failed on key #" + i);
695+
assertEquals(expectedEntry.getValue(), actualEntry.getValue(), "value mismatch for key '" + actualEntry.getKey() + "'");
696+
}
697+
698+
}
699+
648700
}

0 commit comments

Comments
 (0)