Skip to content

Commit

Permalink
feat: Added support for arrays to the Generic Binding (#679)
Browse files Browse the repository at this point in the history
* chore: Added support for arrays to the Generic Binding

When using the Generic Binding, it was not possible to define an array value. Here we add support for it.

Example: "key=[value1, value2, value3]"

* Improved regexp and fix comments

* Add test with spaces

* Improved parsing to ignore "broken" arrays
  • Loading branch information
ctasada authored Apr 6, 2024
1 parent 56f4090 commit 487e268
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 8 deletions.
1 change: 1 addition & 0 deletions springwolf-add-ons/springwolf-generic-binding/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ dependencies {

testImplementation "org.assertj:assertj-core:${assertjCoreVersion}"
testImplementation "org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}"
testImplementation("org.junit.jupiter:junit-jupiter-params:${junitJupiterVersion}")
testRuntimeOnly "org.junit.jupiter:junit-jupiter:${junitJupiterVersion}"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class PropertiesUtil {

private static final Pattern ARRAY_PATTERN = Pattern.compile("^\\[([^]]+)]$");

private PropertiesUtil() {}

public static Map<String, Object> toMap(String[] propertyStrings) {
return convertPropertiesToNestedMap(buildPropertiesFrom((propertyStrings)));
}
Expand All @@ -39,17 +45,30 @@ private static Map<String, Object> convertPropertiesToNestedMap(Properties prope
Map<String, Object> mapNode = bindingData;
while (path.size() > 1) {
String pathElement = path.get(0);
if (!mapNode.containsKey(pathElement)) {
mapNode.put(pathElement, new HashMap<>());
}

mapNode.computeIfAbsent(pathElement, k -> new HashMap<>());
mapNode = (Map<String, Object>) mapNode.get(pathElement);

path.pop();
}

mapNode.put(path.get(0), properties.get(propertyName));
var value = parseValue(properties.get(propertyName));
mapNode.put(path.get(0), value);
}
return bindingData;
}

private static Object parseValue(Object input) {
if (input instanceof String inputString) {
Matcher matcher = ARRAY_PATTERN.matcher(inputString);

// Check if the pattern matches the input string
if (matcher.find()) {
// Extract the key and values
String[] values = matcher.group(1).split(",");
return Arrays.stream(values).map(String::trim).toList();
}
}

return input;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import io.github.springwolf.core.asyncapi.scanners.bindings.operations.ProcessedOperationBinding;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import java.util.Arrays;
import java.util.List;
Expand All @@ -22,7 +24,7 @@ void testClassWithoutAnnotation() {
List<ProcessedOperationBinding> result = getProcessedOperationBindings(ClassWithoutAnnotation.class);

// then
assertThat(result).hasSize(0);
assertThat(result).isEmpty();
}

@Test
Expand All @@ -41,12 +43,11 @@ void testClassWithAnnotationHasABinding() {
}

private List<ProcessedOperationBinding> getProcessedOperationBindings(Class<?> testClass) {
List<ProcessedOperationBinding> result = Arrays.stream(testClass.getDeclaredMethods())
return Arrays.stream(testClass.getDeclaredMethods())
.map((m) -> m.getAnnotationsByType(AsyncGenericOperationBinding.class))
.flatMap(Arrays::stream)
.map(processor::mapToOperationBinding)
.toList();
return result;
}

private static class ClassWithoutAnnotation {
Expand Down Expand Up @@ -89,6 +90,18 @@ void onePropertyTest() {
assertThat(result).isEqualTo(Map.of("key", "value"));
}

@Test
void oneLongPropertyTest() {
// given
String[] strings = {"key=value is long"};

// when
Map<String, Object> result = PropertiesUtil.toMap(strings);

// then
assertThat(result).isEqualTo(Map.of("key", "value is long"));
}

@Test
void twoPropertiesTest() {
// given
Expand All @@ -101,6 +114,43 @@ void twoPropertiesTest() {
assertThat(result).isEqualTo(Map.of("key1", "value1", "key2", "value2"));
}

@Test
void arrayPropertyTest() {
// given
String[] strings = {"key=[value1, value2, value3 is long]"};

// when
Map<String, Object> result = PropertiesUtil.toMap(strings);

// then
assertThat(result).isEqualTo(Map.of("key", List.of("value1", "value2", "value3 is long")));
}

@CsvSource(value = {"asdf[sdf]", "[sdf][sdf]", "[sd[sdf]]", "[kdkd]dkkd", "[kdkd"})
@ParameterizedTest
void arrayParsingShouldBeIgnored(String value) {
// given
String[] strings = {"key=" + value};

// when
Map<String, Object> result = PropertiesUtil.toMap(strings);

// then value is still a string, ignoring the array conversion
assertThat(result).isEqualTo(Map.of("key", value));
}

@Test
void simpleMapPropertyTest() {
// given
String[] strings = {"map.key1=value1", "map.key2=value2", "map.key3=value3"};

// when
Map<String, Object> result = PropertiesUtil.toMap(strings);

// then
assertThat(result).isEqualTo(Map.of("map", Map.of("key1", "value1", "key2", "value2", "key3", "value3")));
}

@Test
void nestedPropertyTest() {
// given
Expand Down Expand Up @@ -136,5 +186,17 @@ void yamlSyntaxDoesWorkAsWell() {
// then
assertThat(result).isEqualTo(Map.of("key", "value"));
}

@Test
void yamlSyntaxArrayPropertyTest() {
// given
String[] strings = {"key: [value1, value2, value3 is long]"};

// when
Map<String, Object> result = PropertiesUtil.toMap(strings);

// then
assertThat(result).isEqualTo(Map.of("key", List.of("value1", "value2", "value3 is long")));
}
}
}

0 comments on commit 487e268

Please sign in to comment.