This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new c83c322 ISIS-2666: Can<T>: add method pickByIndex(...)
c83c322 is described below
commit c83c322fa2035433f24287b39f47d15e98d5f2df
Author: [email protected] <[email protected]@luna>
AuthorDate: Fri May 14 14:58:39 2021 +0200
ISIS-2666: Can<T>: add method pickByIndex(...)
---
.../org/apache/isis/commons/collections/Can.java | 16 ++++
.../apache/isis/commons/collections/Can_Empty.java | 5 ++
.../isis/commons/collections/Can_Multiple.java | 17 +++++
.../isis/commons/collections/Can_Singleton.java | 25 ++++++
.../apache/isis/commons/collections/CanTest.java | 89 ++++++++++++++--------
5 files changed, 120 insertions(+), 32 deletions(-)
diff --git a/commons/src/main/java/org/apache/isis/commons/collections/Can.java
b/commons/src/main/java/org/apache/isis/commons/collections/Can.java
index c37e75d..33741f5 100644
--- a/commons/src/main/java/org/apache/isis/commons/collections/Can.java
+++ b/commons/src/main/java/org/apache/isis/commons/collections/Can.java
@@ -539,6 +539,21 @@ extends Iterable<T>, Comparable<Can<T>>, Serializable {
Can<T> remove(T element);
+ /**
+ * Given <i>n</i> indices, returns an equivalent of
+ * <pre>
+ * Can.of(
+ * this.get(indices[0]).orElse(null),
+ * this.get(indices[1]).orElse(null),
+ * ...
+ * this.get(indices[n-1]).orElse(null)
+ * )
+ * </pre>
+ * (where nulls are being ignored)
+ * @param indices - null-able
+ */
+ Can<T> pickByIndex(@Nullable int ...indices);
+
// -- SEARCH
/**
@@ -720,4 +735,5 @@ extends Iterable<T>, Comparable<Can<T>>, Serializable {
T[] toArray(Class<T> elementType);
+
}
diff --git
a/commons/src/main/java/org/apache/isis/commons/collections/Can_Empty.java
b/commons/src/main/java/org/apache/isis/commons/collections/Can_Empty.java
index 331f356..997a8f5 100644
--- a/commons/src/main/java/org/apache/isis/commons/collections/Can_Empty.java
+++ b/commons/src/main/java/org/apache/isis/commons/collections/Can_Empty.java
@@ -169,6 +169,11 @@ final class Can_Empty<T> implements Can<T> {
}
@Override
+ public Can<T> pickByIndex(final @Nullable int... indices) {
+ return Can.empty();
+ }
+
+ @Override
public int indexOf(T element) {
return -1;
}
diff --git
a/commons/src/main/java/org/apache/isis/commons/collections/Can_Multiple.java
b/commons/src/main/java/org/apache/isis/commons/collections/Can_Multiple.java
index 965010d..1149952 100644
---
a/commons/src/main/java/org/apache/isis/commons/collections/Can_Multiple.java
+++
b/commons/src/main/java/org/apache/isis/commons/collections/Can_Multiple.java
@@ -220,6 +220,23 @@ final class Can_Multiple<T> implements Can<T> {
}
@Override
+ public Can<T> pickByIndex(final @Nullable int... indices) {
+ if(indices==null
+ ||indices.length==0) {
+ return Can.empty();
+ }
+ val newElements = new ArrayList<T>(indices.length);
+ final int maxIndex = size()-1;
+ for(int index:indices) {
+ if(index>=0
+ && index<=maxIndex) {
+ newElements.add(elements.get(index));
+ }
+ }
+ return Can.ofCollection(newElements);
+ }
+
+ @Override
public int indexOf(@NonNull T element) {
return this.elements.indexOf(element);
}
diff --git
a/commons/src/main/java/org/apache/isis/commons/collections/Can_Singleton.java
b/commons/src/main/java/org/apache/isis/commons/collections/Can_Singleton.java
index cf930ee..65e09b6 100644
---
a/commons/src/main/java/org/apache/isis/commons/collections/Can_Singleton.java
+++
b/commons/src/main/java/org/apache/isis/commons/collections/Can_Singleton.java
@@ -194,6 +194,31 @@ final class Can_Singleton<T> implements Can<T> {
}
@Override
+ public Can<T> pickByIndex(final @Nullable int... indices) {
+ if(indices==null
+ ||indices.length==0) {
+ return Can.empty();
+ }
+ int pickCount = 0; // actual size of the returned Can<T>
+ for(int index:indices) {
+ if(index==0) {
+ ++pickCount;
+ }
+ }
+ if(pickCount==0) {
+ return Can.empty();
+ }
+ if(pickCount==1) {
+ return this;
+ }
+ val newElements = new ArrayList<T>(pickCount);
+ for(int i=0; i<pickCount; i++) {
+ newElements.add(element);
+ }
+ return Can.ofCollection(newElements);
+ }
+
+ @Override
public int indexOf(@NonNull T element) {
return this.element.equals(element) ? 0 : -1;
}
diff --git
a/commons/src/test/java/org/apache/isis/commons/collections/CanTest.java
b/commons/src/test/java/org/apache/isis/commons/collections/CanTest.java
index 6095a05..ed3311e 100644
--- a/commons/src/test/java/org/apache/isis/commons/collections/CanTest.java
+++ b/commons/src/test/java/org/apache/isis/commons/collections/CanTest.java
@@ -24,13 +24,13 @@ import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
+import org.apache.isis.commons.internal.collections._Sets;
+import org.apache.isis.commons.internal.testing._SerializationTester;
+
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import org.apache.isis.commons.internal.collections._Sets;
-import org.apache.isis.commons.internal.testing._SerializationTester;
-
import lombok.val;
class CanTest {
@@ -39,35 +39,35 @@ class CanTest {
void tester_selftest() throws ClassNotFoundException, IOException {
_SerializationTester.selftest();
}
-
+
@Test
void emptyCans_shouldBeEqual() {
assertEquals(Can.empty(), Can.<String>of());
}
-
+
@Test
void emptyCan_shouldBeSerializable() {
_SerializationTester.assertEqualsOnRoundtrip(Can.empty());
_SerializationTester.assertEqualsOnRoundtrip(Can.<String>of());
}
-
+
@Test
void singletonCan_shouldBeSerializable() {
_SerializationTester.assertEqualsOnRoundtrip(Can.<String>of("hi"));
}
-
+
@Test
void multiCan_shouldBeSerializable() {
_SerializationTester.assertEqualsOnRoundtrip(Can.<String>of("hi",
"there"));
}
-
+
// -- REVERTING
-
+
@Test
void multiCan_correctly_reverts() {
assertEquals(Can.<String>of("c", "b", "a"), Can.<String>of("a", "b",
"c").reverse());
}
-
+
@Test
void multiCan_startsWith() {
assertTrue(Can.<String>of("a", "b",
"c").startsWith(Can.<String>of("a", "b", "c")));
@@ -77,7 +77,7 @@ class CanTest {
assertTrue(Can.<String>of("a", "b", "c").startsWith(null));
assertFalse(Can.<String>of("a", "b",
"c").startsWith(Can.<String>of("a", "b", "x")));
}
-
+
@Test
void multiCan_endsWith() {
assertTrue(Can.<String>of("a", "b", "c").endsWith(Can.<String>of("a",
"b", "c")));
@@ -87,88 +87,113 @@ class CanTest {
assertTrue(Can.<String>of("a", "b", "c").endsWith(null));
assertFalse(Can.<String>of("a", "b", "c").endsWith(Can.<String>of("x",
"b", "a")));
}
-
+
// -- FILTERING
-
+
@Test
void emptyCanFilter_isIdentity() {
assertEquals(Can.<String>empty(),
Can.<String>empty().filter(x->false));
assertEquals(Can.<String>empty(), Can.<String>empty().filter(null));
}
-
+
@Test
void singletonCanFilter_whenAccept_isIdentity() {
assertEquals(Can.<String>of("hi"),
Can.<String>of("hi").filter(x->true));
assertEquals(Can.<String>of("hi"), Can.<String>of("hi").filter(null));
}
-
+
@Test
void canFilter_whenNotAccept_isEmpty() {
assertEquals(Can.<String>empty(),
Can.<String>of("hi").filter(x->false));
assertEquals(Can.<String>empty(), Can.<String>of("hi",
"there").filter(x->false));
}
-
+
@Test
void multiCanFilter_whenAccept_isIdentity() {
assertEquals(Can.<String>of("hi", "there"), Can.<String>of("hi",
"there").filter(x->true));
assertEquals(Can.<String>of("hi", "there"), Can.<String>of("hi",
"there").filter(null));
}
-
+
@Test
void multiCanFilter_whenAcceptOne_isDifferentCan() {
assertEquals(Can.<String>of("there"), Can.<String>of("hi",
"there").filter("there"::equals));
assertEquals(Can.<String>of("hi"), Can.<String>of("hi",
"there").filter("hi"::equals));
assertEquals(Can.<String>of("hello"), Can.<String>of("hi", "hello",
"there").filter("hello"::equals));
}
-
+
@Test
void multiCanFilter_whenAcceptTwo_isDifferentCan() {
assertEquals(Can.<String>of("hi", "hello"), Can.<String>of("hi",
"hello", "there").filter(x->x.startsWith("h")));
}
-
+
// -- STREAM IDIOMS
-
+
@Test
void partialSums_reversed() {
assertEquals(Can.<String>of("a", "b"),
Can.<String>empty().add("a").add("b"));
assertEquals(Can.<String>of("a", "b"), Can.<String>empty().add(0,
"b").add(0, "a"));
-
+
final Can<String> all = Can.<String>of("a", "b", "c");
-
+
val iterator = all.reverseIterator();
-
+
val partialSums = Stream.iterate(
- Can.<String>empty(),
+ Can.<String>empty(),
parts->parts.add(0, iterator.next()))
.limit(4)
.collect(Can.toCan());
-
+
assertEquals(Can.of(
Can.<String>empty(),
Can.<String>of("c"),
Can.<String>of("b", "c"),
Can.<String>of("a", "b", "c")
- ),
+ ),
partialSums);
-
+
}
-
+
// -- TO SET CONVERSION
-
+
@Test
void multiCan_toSet_should_find_duplicates() {
val expectedSet = _Sets.of("a", "b", "c");
val duplicates = _Sets.<String>newHashSet();
-
+
assertSetEquals(expectedSet, Can.<String>of("a", "c", "b",
"a").toSet());
assertSetEquals(expectedSet, Can.<String>of("a", "c", "b",
"a").toSet(duplicates::add));
assertSetEquals(_Sets.of("a"), duplicates);
}
-
+
+ // -- PICKING
+
+ @Test
+ void can_pickByIndex() {
+
+ assertEquals(
+ Can.empty(),
+ Can.empty().pickByIndex(0, 1, 0));
+
+ assertEquals(
+ Can.empty(),
+ Can.<String>of("a", "b", "c").pickByIndex(-2, 5));
+
+ assertEquals(
+ Can.of("a", "a", "a"),
+ Can.<String>of("a").pickByIndex(0, 0, -2, 5, 0));
+
+ assertEquals(
+ Can.of("a", "b", "a"),
+ Can.<String>of("a", "b", "c").pickByIndex(0, 1, -2, 0, 5));
+ }
+
+ // -- HEPER
+
private static <T> void assertSetEquals(Set<T> a, Set<T> b) {
assertTrue(_Sets.minus(a, b).isEmpty());
assertTrue(_Sets.minus(b, a).isEmpty());
}
-
+
+
}