diff --git a/scm-core/src/main/java/sonia/scm/update/MapBasedPropertyReaderInstance.java b/scm-core/src/main/java/sonia/scm/update/MapBasedPropertyReaderInstance.java new file mode 100644 index 0000000000..65e6a71958 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/update/MapBasedPropertyReaderInstance.java @@ -0,0 +1,36 @@ +package sonia.scm.update; + +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.stream.Stream; + +public class MapBasedPropertyReaderInstance implements V1PropertyReader.Instance { + private final Stream> all; + + public MapBasedPropertyReaderInstance(Map all) { + this(all.entrySet().stream()); + } + + private MapBasedPropertyReaderInstance(Stream> all) { + this.all = all; + } + + @Override + public void forEachEntry(BiConsumer propertiesForNameConsumer) { + all.forEach(e -> call(e.getKey(), e.getValue(), propertiesForNameConsumer)); + } + + @Override + public V1PropertyReader.Instance havingAnyOf(String... keys) { + return new MapBasedPropertyReaderInstance(all.filter(e -> e.getValue().hasAny(keys))); + } + + @Override + public V1PropertyReader.Instance havingAllOf(String... keys) { + return new MapBasedPropertyReaderInstance(all.filter(e -> e.getValue().hasAll(keys))); + } + + private void call(String repositoryId, V1Properties properties, BiConsumer propertiesForNameConsumer) { + propertiesForNameConsumer.accept(repositoryId, properties); + } +} diff --git a/scm-core/src/main/java/sonia/scm/update/RepositoryV1PropertyReader.java b/scm-core/src/main/java/sonia/scm/update/RepositoryV1PropertyReader.java index cb9f2d01d9..5faf4500cd 100644 --- a/scm-core/src/main/java/sonia/scm/update/RepositoryV1PropertyReader.java +++ b/scm-core/src/main/java/sonia/scm/update/RepositoryV1PropertyReader.java @@ -1,7 +1,6 @@ package sonia.scm.update; import java.util.Map; -import java.util.function.BiConsumer; public class RepositoryV1PropertyReader implements V1PropertyReader { @Override @@ -11,13 +10,7 @@ public class RepositoryV1PropertyReader implements V1PropertyReader { @Override public Instance createInstance(Map all) { - return propertiesForNameConsumer -> - all - .entrySet() - .forEach(e -> call(e.getKey(), e.getValue(), propertiesForNameConsumer)); + return new MapBasedPropertyReaderInstance(all); } - private void call(String repositoryId, V1Properties properties, BiConsumer propertiesForNameConsumer) { - propertiesForNameConsumer.accept(repositoryId, properties); - } } diff --git a/scm-core/src/main/java/sonia/scm/update/V1Properties.java b/scm-core/src/main/java/sonia/scm/update/V1Properties.java index 5776fc91c7..984a1e0fdb 100644 --- a/scm-core/src/main/java/sonia/scm/update/V1Properties.java +++ b/scm-core/src/main/java/sonia/scm/update/V1Properties.java @@ -6,7 +6,8 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import java.util.List; -import static java.util.Collections.unmodifiableList; +import static java.util.Arrays.asList; +import static java.util.Arrays.stream; @XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "properties") @@ -14,7 +15,26 @@ public class V1Properties { @XmlElement(name = "item") private List properties; + public V1Properties() { + } + + public V1Properties(V1Property... properties) { + this(asList(properties)); + } + + public V1Properties(List properties) { + this.properties = properties; + } + public String get(String key) { return properties.stream().filter(p -> key.equals(p.getKey())).map(V1Property::getValue).findFirst().orElse(null); } + + public boolean hasAny(String[] keys) { + return properties.stream().anyMatch(p -> stream(keys).anyMatch(k -> k.equals(p.getKey()))); + } + + public boolean hasAll(String[] keys) { + return stream(keys).allMatch(k -> properties.stream().anyMatch(p -> k.equals(p.getKey()))); + } } diff --git a/scm-core/src/main/java/sonia/scm/update/V1PropertyReader.java b/scm-core/src/main/java/sonia/scm/update/V1PropertyReader.java index 2d20a9aeed..2c8381e247 100644 --- a/scm-core/src/main/java/sonia/scm/update/V1PropertyReader.java +++ b/scm-core/src/main/java/sonia/scm/update/V1PropertyReader.java @@ -11,5 +11,9 @@ public interface V1PropertyReader { interface Instance { void forEachEntry(BiConsumer propertiesForNameConsumer); + + Instance havingAnyOf(String... keys); + + Instance havingAllOf(String... keys); } } diff --git a/scm-core/src/test/java/sonia/scm/update/MapBasedPropertyReaderInstanceTest.java b/scm-core/src/test/java/sonia/scm/update/MapBasedPropertyReaderInstanceTest.java new file mode 100644 index 0000000000..f214203866 --- /dev/null +++ b/scm-core/src/test/java/sonia/scm/update/MapBasedPropertyReaderInstanceTest.java @@ -0,0 +1,61 @@ +package sonia.scm.update; + +import com.google.common.collect.ImmutableMap; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; + +class MapBasedPropertyReaderInstanceTest { + + Map executedCalls = new HashMap<>(); + + BiConsumer consumer = (key, properties) -> executedCalls.put(key, properties); + + MapBasedPropertyReaderInstance instance = new MapBasedPropertyReaderInstance( + ImmutableMap.of( + "o1", new V1Properties( + new V1Property("k1", "v1-1"), + new V1Property("k2", "v1-2"), + new V1Property("k3", "v1-3") + ), + "o2", new V1Properties( + new V1Property("k1", "v2-1"), + new V1Property("k2", "v2-2") + ), + "o3", new V1Properties( + new V1Property("k1", "v3-1") + ) + ) + ); + + @Test + void shouldCallBackForEachObjectIfNotFiltered() { + instance.forEachEntry(consumer); + + Assertions.assertThat(executedCalls).hasSize(3); + } + + @Test + void shouldCallBackOnlyObjectsHavingAtLeastOneOfGivenKey() { + instance.havingAnyOf("k2", "k3").forEachEntry(consumer); + + Assertions.assertThat(executedCalls).hasSize(2).containsKeys("o1", "o2"); + } + + @Test + void shouldCallBackOnlyObjectsHavingAllOfGivenKey() { + instance.havingAllOf("k2", "k3").forEachEntry(consumer); + + Assertions.assertThat(executedCalls).hasSize(1).containsKeys("o1"); + } + + @Test + void shouldCombineFilters() { + instance.havingAnyOf("k2", "k3").havingAllOf("k3").forEachEntry(consumer); + + Assertions.assertThat(executedCalls).hasSize(1).containsKeys("o1"); + } +}