diff --git a/changes.xml b/changes.xml
index 26fc3e5..10ad615 100644
--- a/changes.xml
+++ b/changes.xml
@@ -23,6 +23,15 @@
xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/plugins/maven-changes-plugin/xsd/changes-1.0.0.xsd">
+
+
+ ImmutableValueMap.of: Retain order of items as stated in JavaDoc.
+
+
+ ImmutableValueMap.copyOf: Ensure map is immutable.
+
+
+
Switch to Java 11 as minimum version.
diff --git a/pom.xml b/pom.xml
index c5b62a8..c97c490 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,7 @@
io.wcm
io.wcm.sling.commons
- 1.6.2
+ 1.6.4
jar
Sling Commons
@@ -49,7 +49,7 @@
sling/commons
- 2023-04-19T11:06:55Z
+ 2023-07-03T09:55:00Z
diff --git a/src/main/java/io/wcm/sling/commons/resource/ImmutableValueMap.java b/src/main/java/io/wcm/sling/commons/resource/ImmutableValueMap.java
index 11ca568..7b503d0 100644
--- a/src/main/java/io/wcm/sling/commons/resource/ImmutableValueMap.java
+++ b/src/main/java/io/wcm/sling/commons/resource/ImmutableValueMap.java
@@ -21,7 +21,7 @@
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
@@ -185,9 +185,10 @@ public void clear() {
* @param v1 Value 1
* @return ImmutableValueMap
*/
- @SuppressWarnings("null")
public static @NotNull ImmutableValueMap of(@NotNull String k1, @NotNull Object v1) {
- return new ImmutableValueMap(Map.of(k1, v1));
+ Map map = new LinkedHashMap<>();
+ map.put(k1, v1);
+ return new ImmutableValueMap(Collections.unmodifiableMap(map));
}
/**
@@ -199,10 +200,12 @@ public void clear() {
* @return ImmutableValueMap
* @throws IllegalArgumentException if duplicate keys are provided
*/
- @SuppressWarnings("null")
public static @NotNull ImmutableValueMap of(@NotNull String k1, @NotNull Object v1,
@NotNull String k2, @NotNull Object v2) {
- return new ImmutableValueMap(Map.of(k1, v1, k2, v2));
+ Map map = new LinkedHashMap<>();
+ map.put(k1, v1);
+ map.put(k2, v2);
+ return new ImmutableValueMap(Collections.unmodifiableMap(map));
}
/**
@@ -216,12 +219,15 @@ public void clear() {
* @return ImmutableValueMap
* @throws IllegalArgumentException if duplicate keys are provided
*/
- @SuppressWarnings("null")
public static @NotNull ImmutableValueMap of(
@NotNull String k1, @NotNull Object v1,
@NotNull String k2, @NotNull Object v2,
@NotNull String k3, @NotNull Object v3) {
- return new ImmutableValueMap(Map.of(k1, v1, k2, v2, k3, v3));
+ Map map = new LinkedHashMap<>();
+ map.put(k1, v1);
+ map.put(k2, v2);
+ map.put(k3, v3);
+ return new ImmutableValueMap(Collections.unmodifiableMap(map));
}
/**
@@ -237,13 +243,18 @@ public void clear() {
* @return ImmutableValueMap
* @throws IllegalArgumentException if duplicate keys are provided
*/
- @SuppressWarnings({ "null", "java:S107", "PMD.UseObjectForClearerAPI" })
+ @SuppressWarnings({ "java:S107", "PMD.UseObjectForClearerAPI" })
public static @NotNull ImmutableValueMap of(
@NotNull String k1, @NotNull Object v1,
@NotNull String k2, @NotNull Object v2,
@NotNull String k3, @NotNull Object v3,
@NotNull String k4, @NotNull Object v4) {
- return new ImmutableValueMap(Map.of(k1, v1, k2, v2, k3, v3, k4, v4));
+ Map map = new LinkedHashMap<>();
+ map.put(k1, v1);
+ map.put(k2, v2);
+ map.put(k3, v3);
+ map.put(k4, v4);
+ return new ImmutableValueMap(Collections.unmodifiableMap(map));
}
/**
@@ -261,14 +272,20 @@ public void clear() {
* @return ImmutableValueMap
* @throws IllegalArgumentException if duplicate keys are provided
*/
- @SuppressWarnings({ "null", "java:S107", "PMD.UseObjectForClearerAPI" })
+ @SuppressWarnings({ "java:S107", "PMD.UseObjectForClearerAPI" })
public static ImmutableValueMap of(
@NotNull String k1, @NotNull Object v1,
@NotNull String k2, @NotNull Object v2,
@NotNull String k3, @NotNull Object v3,
@NotNull String k4, @NotNull Object v4,
@NotNull String k5, @NotNull Object v5) {
- return new ImmutableValueMap(Map.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5));
+ Map map = new LinkedHashMap<>();
+ map.put(k1, v1);
+ map.put(k2, v2);
+ map.put(k3, v3);
+ map.put(k4, v4);
+ map.put(k5, v5);
+ return new ImmutableValueMap(Collections.unmodifiableMap(map));
}
// looking for of() with > 5 entries? Use the builder instead.
@@ -296,12 +313,7 @@ public static ImmutableValueMap of(
* @throws NullPointerException if any key or value in {@code map} is null
*/
public static @NotNull ImmutableValueMap copyOf(@NotNull Map map) {
- if (map instanceof ValueMap) {
- return new ImmutableValueMap((ValueMap)map);
- }
- else {
- return new ImmutableValueMap(map);
- }
+ return new ImmutableValueMap(Collections.unmodifiableMap(map));
}
/**
@@ -309,7 +321,7 @@ public static ImmutableValueMap of(
*/
public static final class Builder {
- private final @NotNull Map map = new HashMap<>();
+ private final @NotNull Map map = new LinkedHashMap<>();
/**
* Associates {@code key} with {@code value} in the built map. Duplicate
diff --git a/src/test/java/io/wcm/sling/commons/resource/ImmutableValueMapTest.java b/src/test/java/io/wcm/sling/commons/resource/ImmutableValueMapTest.java
index f8a8409..e84c70e 100644
--- a/src/test/java/io/wcm/sling/commons/resource/ImmutableValueMapTest.java
+++ b/src/test/java/io/wcm/sling/commons/resource/ImmutableValueMapTest.java
@@ -25,6 +25,7 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import java.util.Iterator;
import java.util.Map;
import org.apache.sling.api.resource.ValueMap;
@@ -107,46 +108,31 @@ void testOf() {
@Test
void testOfx1() {
ValueMap map = ImmutableValueMap.of("p1", "v1");
- assertEquals(1, map.size());
- assertEquals("v1", map.get("p1"));
+ assertWithOrder(map, "p1", "v1");
}
@Test
void testOfx2() {
- ValueMap map = ImmutableValueMap.of("p1", "v1", "p2", "v2");
- assertEquals(2, map.size());
- assertEquals("v1", map.get("p1"));
- assertEquals("v2", map.get("p2"));
+ ValueMap map = ImmutableValueMap.of("p2", "v2", "p1", "v1");
+ assertWithOrder(map, "p2", "v2", "p1", "v1");
}
@Test
void testOfx3() {
ValueMap map = ImmutableValueMap.of("p1", "v1", "p2", "v2", "p3", "v3");
- assertEquals(3, map.size());
- assertEquals("v1", map.get("p1"));
- assertEquals("v2", map.get("p2"));
- assertEquals("v3", map.get("p3"));
+ assertWithOrder(map, "p1", "v1", "p2", "v2", "p3", "v3");
}
@Test
void testOfx4() {
- ValueMap map = ImmutableValueMap.of("p1", "v1", "p2", "v2", "p3", "v3", "p4", "v4");
- assertEquals(4, map.size());
- assertEquals("v1", map.get("p1"));
- assertEquals("v2", map.get("p2"));
- assertEquals("v3", map.get("p3"));
- assertEquals("v4", map.get("p4"));
+ ValueMap map = ImmutableValueMap.of("p3", "v3", "p2", "v2", "p1", "v1", "p4", "v4");
+ assertWithOrder(map, "p3", "v3", "p2", "v2", "p1", "v1", "p4", "v4");
}
@Test
void testOfx5() {
- ValueMap map = ImmutableValueMap.of("p1", "v1", "p2", "v2", "p3", "v3", "p4", "v4", "p5", "v5");
- assertEquals(5, map.size());
- assertEquals("v1", map.get("p1"));
- assertEquals("v2", map.get("p2"));
- assertEquals("v3", map.get("p3"));
- assertEquals("v4", map.get("p4"));
- assertEquals("v5", map.get("p5"));
+ ValueMap map = ImmutableValueMap.of("p1", "v1", "p5", "v5", "p3", "v3", "p4", "v4", "p2", "v2");
+ assertWithOrder(map, "p1", "v1", "p5", "v5", "p3", "v3", "p4", "v4", "p2", "v2");
}
@Test
@@ -211,4 +197,17 @@ void testToString() {
assertEquals("{}", ImmutableValueMap.of().toString());
}
+ private void assertWithOrder(Map map, Object... items) {
+ int count = items.length / 2;
+ assertEquals(count, map.size(), "map size");
+ Iterator> entries = map.entrySet().iterator();
+ for (int i = 0; i < items.length - 1; i = i + 2) {
+ Object key = items[i];
+ Object value = items[i + 1];
+ Map.Entry entry = entries.next();
+ assertEquals(key, entry.getKey(), "Key Entry #" + (i / 2));
+ assertEquals(value, entry.getValue(), "Value Entry #" + (i / 2));
+ }
+ }
+
}