From a7cb0ad3c7fc4b11d340830b8adbfd6a9d5abca1 Mon Sep 17 00:00:00 2001 From: Family Date: Fri, 2 Oct 2020 23:33:47 +0530 Subject: [PATCH 1/3] MapBuilder class and Test cases --- .../commons/collections4/MapBuilder.java | 115 +++++++++++++++++ .../commons/collections4/MapBuilderTest.java | 122 ++++++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 src/main/java/org/apache/commons/collections4/MapBuilder.java create mode 100644 src/test/java/org/apache/commons/collections4/MapBuilderTest.java diff --git a/src/main/java/org/apache/commons/collections4/MapBuilder.java b/src/main/java/org/apache/commons/collections4/MapBuilder.java new file mode 100644 index 0000000000..a668ff857c --- /dev/null +++ b/src/main/java/org/apache/commons/collections4/MapBuilder.java @@ -0,0 +1,115 @@ +package org.apache.commons.collections4; + +import org.apache.commons.collections4.map.HashedMap; + +import java.util.*; + +/** + * Defines an Helper Builder that generates a {@code Map} + * A Builder class to help decide which type of map to use based on simple requirements. + * Currently It takes care of only basic types of Maps and can be extended to different types of Maps available in the ecosystem. + * + *
{@code
+ * Map builderMap = new MapBuilder().setIterationOrder(MapBuilder.KeyOrder.INSERTION_ORDER).build();
+ * builderMap.put("A", 1);
+ * builderMap.put("X", 24);
+ * builderMap.put("B", 2);
+ * builderMap.put("Y", 26);
+ * }
+ * + * @author Amita Pradhan + */ +public class MapBuilder { + + private Comparator comparator; + private KeyOrder iterationOrder; + private boolean synchronizedMap; + private boolean immutable; + private Map data; + + public MapBuilder() { + comparator = null; + iterationOrder = KeyOrder.RANDOM; + synchronizedMap = false; + immutable = false; + data = null; + } + + /* + Sets the comparator to be used to decide the Iteration order in case of iterationOrder = COMPARATOR_ORDER; + */ + public MapBuilder setComparator(Comparator comparator) { + this.comparator = comparator; + return this; + } + + /* + Sets the Iteration order to be used from [RANDOM, NATURAL_ORDER, INSERTION_ORDER, COMPARATOR_ORDER] + */ + public MapBuilder setIterationOrder(KeyOrder iterationOrder) { + this.iterationOrder = iterationOrder; + return this; + } + + /* + Since most of the maps are not inherently thread safe , this option provides the option if the map has to be synchronised or not + */ + public MapBuilder setSynchronizedMap(boolean synchronizedMap) { + this.synchronizedMap = synchronizedMap; + return this; + } + + /* + Option to create a immutable map from the provided data + */ + public MapBuilder setImmutable(boolean immutable) { + this.immutable = immutable; + return this; + } + + /* + Populates the Map with some preexisting data. All the selected conditions will be automatically applied to the existing data + */ + public MapBuilder setData(Map data) { + this.data = data; + return this; + } + + /* + Builder Method which takes care of all the conditions and returns the required Map. + */ + public Map build() { + Map map; + switch (iterationOrder) { + case NATURAL_ORDER : + case COMPARATOR_ORDER: + map = new TreeMap(comparator); + break; + case INSERTION_ORDER : + map = new LinkedHashMap(); + break; + default: + map = new HashedMap(); + break; + } + + if(MapUtils.isNotEmpty(data)) { + map.putAll(data); + } + + if(synchronizedMap) { + map = Collections.synchronizedMap(map); + } + + if(immutable) { + map = Collections.unmodifiableMap(map); + } + + return map; + } + + enum KeyOrder + { + RANDOM, NATURAL_ORDER, INSERTION_ORDER, COMPARATOR_ORDER; + } +} diff --git a/src/test/java/org/apache/commons/collections4/MapBuilderTest.java b/src/test/java/org/apache/commons/collections4/MapBuilderTest.java new file mode 100644 index 0000000000..7cb6df31ec --- /dev/null +++ b/src/test/java/org/apache/commons/collections4/MapBuilderTest.java @@ -0,0 +1,122 @@ +package org.apache.commons.collections4; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Test Cases for Map Builder + */ +class MapBuilderTest { + + @Test + void setComparator() { + // Null Comparator + Map myMap = new HashMap(); + myMap.put("A", 1); + myMap.put("X", 24); + myMap.put("B", 2); + myMap.put("Y", 26); + Map builderMap = new MapBuilder().setData(myMap).setComparator(null).build(); + Assert.assertEquals(myMap, builderMap); + + // Reverse comparator + builderMap = new MapBuilder().setData(myMap).setIterationOrder(MapBuilder.KeyOrder.COMPARATOR_ORDER).setComparator(Comparator.reverseOrder()).build(); + Assert.assertEquals(builderMap.keySet().stream().findFirst().get(), "Y"); + Assert.assertEquals(builderMap.keySet().stream().skip(1).findFirst().get(), "X"); + Assert.assertEquals(builderMap.keySet().stream().skip(2).findFirst().get(), "B"); + Assert.assertEquals(builderMap.keySet().stream().skip(3).findFirst().get(), "A"); + } + + @Test + void setIterationOrder() { + //Key Order = RANDOM + Map myMap = new HashMap(); + myMap.put("A", 1); + myMap.put("X", 24); + myMap.put("B", 2); + myMap.put("Y", 26); + Map builderMap = new MapBuilder().setData(myMap).setIterationOrder(MapBuilder.KeyOrder.RANDOM).build(); + Assert.assertEquals(myMap, builderMap); + + //Key Order = INSERTION ORDER + builderMap = new MapBuilder().setIterationOrder(MapBuilder.KeyOrder.INSERTION_ORDER).build(); + builderMap.put("A", 1); + builderMap.put("X", 24); + builderMap.put("B", 2); + builderMap.put("Y", 26); + Assert.assertEquals(builderMap.keySet().stream().findFirst().get(), "A"); + Assert.assertEquals(builderMap.keySet().stream().skip(1).findFirst().get(), "X"); + Assert.assertEquals(builderMap.keySet().stream().skip(2).findFirst().get(), "B"); + Assert.assertEquals(builderMap.keySet().stream().skip(3).findFirst().get(), "Y"); + + //Key Order = NATURAL ORDER + builderMap = new MapBuilder().setIterationOrder(MapBuilder.KeyOrder.NATURAL_ORDER).build(); + builderMap.put("A", 1); + builderMap.put("X", 24); + builderMap.put("B", 2); + builderMap.put("Y", 26); + Assert.assertEquals(builderMap.keySet().stream().findFirst().get(), "A"); + Assert.assertEquals(builderMap.keySet().stream().skip(1).findFirst().get(), "B"); + Assert.assertEquals(builderMap.keySet().stream().skip(2).findFirst().get(), "X"); + Assert.assertEquals(builderMap.keySet().stream().skip(3).findFirst().get(), "Y"); + + //Key Order = COMPARATOR ORDER and null comparator + builderMap = new MapBuilder().setIterationOrder(MapBuilder.KeyOrder.COMPARATOR_ORDER).build(); + builderMap.put("A", 1); + builderMap.put("X", 24); + builderMap.put("B", 2); + builderMap.put("Y", 26); + Assert.assertEquals(builderMap.keySet().stream().findFirst().get(), "A"); + Assert.assertEquals(builderMap.keySet().stream().skip(1).findFirst().get(), "B"); + Assert.assertEquals(builderMap.keySet().stream().skip(2).findFirst().get(), "X"); + Assert.assertEquals(builderMap.keySet().stream().skip(3).findFirst().get(), "Y"); + + //Key Order = COMPARATOR ORDER and valid comparator + builderMap = new MapBuilder().setIterationOrder(MapBuilder.KeyOrder.COMPARATOR_ORDER).setComparator(Comparator.reverseOrder()).build(); + builderMap.put("A", 1); + builderMap.put("X", 24); + builderMap.put("B", 2); + builderMap.put("Y", 26); + Assert.assertEquals(builderMap.keySet().stream().findFirst().get(), "Y"); + Assert.assertEquals(builderMap.keySet().stream().skip(1).findFirst().get(), "X"); + Assert.assertEquals(builderMap.keySet().stream().skip(2).findFirst().get(), "B"); + Assert.assertEquals(builderMap.keySet().stream().skip(3).findFirst().get(), "A"); + } + + @Test + void setImmutable() { + Map myMap = new HashMap(); + myMap.put("A", 1); + myMap.put("B", 2); + Map builderMap = new MapBuilder().setData(myMap).setImmutable(true).build(); + boolean exceptionThrown = false; + try { + builderMap.put("C", 3); + }catch (UnsupportedOperationException e) { + exceptionThrown = true; + } + Assert.assertTrue(exceptionThrown); + Assert.assertEquals(myMap, builderMap); + } + + @Test + void setData() { + Map myMap = new HashMap(); + myMap.put("A", 1); + myMap.put("B", 2); + Map builderMap = new MapBuilder().setData(myMap).build(); + Assert.assertEquals(myMap, builderMap); + } + + @Test + void build() { + Map builderMap = new MapBuilder().build(); + Assert.assertTrue(builderMap.size() == 0); + } +} \ No newline at end of file From 0756ad6c7f713dd5c05f0a31c6b85cee0ffa62c5 Mon Sep 17 00:00:00 2001 From: Family Date: Sat, 3 Oct 2020 21:12:36 +0530 Subject: [PATCH 2/3] Addressed comments --- .../commons/collections4/MapBuilder.java | 15 ++++++------- .../commons/collections4/MapBuilderTest.java | 22 +++++++++---------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/MapBuilder.java b/src/main/java/org/apache/commons/collections4/MapBuilder.java index a668ff857c..da1964a567 100644 --- a/src/main/java/org/apache/commons/collections4/MapBuilder.java +++ b/src/main/java/org/apache/commons/collections4/MapBuilder.java @@ -17,19 +17,18 @@ * builderMap.put("Y", 26); * } * - * @author Amita Pradhan */ -public class MapBuilder { +public class MapBuilder { - private Comparator comparator; + private Comparator comparator; private KeyOrder iterationOrder; private boolean synchronizedMap; private boolean immutable; - private Map data; + private Map data; public MapBuilder() { comparator = null; - iterationOrder = KeyOrder.RANDOM; + iterationOrder = KeyOrder.UNORDERED; synchronizedMap = false; immutable = false; data = null; @@ -44,7 +43,7 @@ public MapBuilder setComparator(Comparator comparator) { } /* - Sets the Iteration order to be used from [RANDOM, NATURAL_ORDER, INSERTION_ORDER, COMPARATOR_ORDER] + Sets the Iteration order to be used from [UNORDERED, NATURAL_ORDER, INSERTION_ORDER, COMPARATOR_ORDER] */ public MapBuilder setIterationOrder(KeyOrder iterationOrder) { this.iterationOrder = iterationOrder; @@ -79,7 +78,7 @@ public MapBuilder setData(Map data) { Builder Method which takes care of all the conditions and returns the required Map. */ public Map build() { - Map map; + Map map; switch (iterationOrder) { case NATURAL_ORDER : case COMPARATOR_ORDER: @@ -110,6 +109,6 @@ public Map build() { enum KeyOrder { - RANDOM, NATURAL_ORDER, INSERTION_ORDER, COMPARATOR_ORDER; + UNORDERED, NATURAL_ORDER, INSERTION_ORDER, COMPARATOR_ORDER; } } diff --git a/src/test/java/org/apache/commons/collections4/MapBuilderTest.java b/src/test/java/org/apache/commons/collections4/MapBuilderTest.java index 7cb6df31ec..f36a0f04a0 100644 --- a/src/test/java/org/apache/commons/collections4/MapBuilderTest.java +++ b/src/test/java/org/apache/commons/collections4/MapBuilderTest.java @@ -7,8 +7,6 @@ import java.util.HashMap; import java.util.Map; -import static org.junit.jupiter.api.Assertions.*; - /** * Test Cases for Map Builder */ @@ -17,12 +15,12 @@ class MapBuilderTest { @Test void setComparator() { // Null Comparator - Map myMap = new HashMap(); + Map myMap = new HashMap(); myMap.put("A", 1); myMap.put("X", 24); myMap.put("B", 2); myMap.put("Y", 26); - Map builderMap = new MapBuilder().setData(myMap).setComparator(null).build(); + Map builderMap = new MapBuilder().setData(myMap).setComparator(null).build(); Assert.assertEquals(myMap, builderMap); // Reverse comparator @@ -35,13 +33,13 @@ void setComparator() { @Test void setIterationOrder() { - //Key Order = RANDOM - Map myMap = new HashMap(); + //Key Order = UNORDERED + Map myMap = new HashMap(); myMap.put("A", 1); myMap.put("X", 24); myMap.put("B", 2); myMap.put("Y", 26); - Map builderMap = new MapBuilder().setData(myMap).setIterationOrder(MapBuilder.KeyOrder.RANDOM).build(); + Map builderMap = new MapBuilder().setData(myMap).setIterationOrder(MapBuilder.KeyOrder.UNORDERED).build(); Assert.assertEquals(myMap, builderMap); //Key Order = INSERTION ORDER @@ -91,10 +89,10 @@ void setIterationOrder() { @Test void setImmutable() { - Map myMap = new HashMap(); + Map myMap = new HashMap(); myMap.put("A", 1); myMap.put("B", 2); - Map builderMap = new MapBuilder().setData(myMap).setImmutable(true).build(); + Map builderMap = new MapBuilder().setData(myMap).setImmutable(true).build(); boolean exceptionThrown = false; try { builderMap.put("C", 3); @@ -107,16 +105,16 @@ void setImmutable() { @Test void setData() { - Map myMap = new HashMap(); + Map myMap = new HashMap(); myMap.put("A", 1); myMap.put("B", 2); - Map builderMap = new MapBuilder().setData(myMap).build(); + Map builderMap = new MapBuilder().setData(myMap).build(); Assert.assertEquals(myMap, builderMap); } @Test void build() { - Map builderMap = new MapBuilder().build(); + Map builderMap = new MapBuilder().build(); Assert.assertTrue(builderMap.size() == 0); } } \ No newline at end of file From b5cc1de697d03c51ebc3d2488f132da8c8af6082 Mon Sep 17 00:00:00 2001 From: Family Date: Tue, 6 Oct 2020 23:06:56 +0530 Subject: [PATCH 3/3] Added apache header and fixed checkstyle error --- .../commons/collections4/MapBuilder.java | 57 ++++++++++++------- .../commons/collections4/MapBuilderTest.java | 50 ++++++++-------- 2 files changed, 65 insertions(+), 42 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/MapBuilder.java b/src/main/java/org/apache/commons/collections4/MapBuilder.java index da1964a567..539ec3c617 100644 --- a/src/main/java/org/apache/commons/collections4/MapBuilder.java +++ b/src/main/java/org/apache/commons/collections4/MapBuilder.java @@ -1,8 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.apache.commons.collections4; import org.apache.commons.collections4.map.HashedMap; -import java.util.*; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.TreeMap; +import java.util.Collections; /** * Defines an Helper Builder that generates a {@code Map} @@ -18,13 +38,13 @@ * } * */ -public class MapBuilder { +public class MapBuilder { private Comparator comparator; private KeyOrder iterationOrder; private boolean synchronizedMap; private boolean immutable; - private Map data; + private Map data; public MapBuilder() { comparator = null; @@ -78,37 +98,36 @@ public MapBuilder setData(Map data) { Builder Method which takes care of all the conditions and returns the required Map. */ public Map build() { - Map map; + Map map; switch (iterationOrder) { - case NATURAL_ORDER : - case COMPARATOR_ORDER: - map = new TreeMap(comparator); - break; - case INSERTION_ORDER : - map = new LinkedHashMap(); - break; - default: - map = new HashedMap(); - break; + case NATURAL_ORDER : + case COMPARATOR_ORDER: + map = new TreeMap(comparator); + break; + case INSERTION_ORDER : + map = new LinkedHashMap(); + break; + default: + map = new HashedMap(); + break; } - if(MapUtils.isNotEmpty(data)) { + if (MapUtils.isNotEmpty(data)) { map.putAll(data); } - if(synchronizedMap) { + if (synchronizedMap) { map = Collections.synchronizedMap(map); } - if(immutable) { + if (immutable) { map = Collections.unmodifiableMap(map); } return map; } - enum KeyOrder - { + enum KeyOrder { UNORDERED, NATURAL_ORDER, INSERTION_ORDER, COMPARATOR_ORDER; } } diff --git a/src/test/java/org/apache/commons/collections4/MapBuilderTest.java b/src/test/java/org/apache/commons/collections4/MapBuilderTest.java index f36a0f04a0..3fcdb3980c 100644 --- a/src/test/java/org/apache/commons/collections4/MapBuilderTest.java +++ b/src/test/java/org/apache/commons/collections4/MapBuilderTest.java @@ -1,16 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.apache.commons.collections4; +import org.apache.commons.collections4.map.HashedMap; import org.junit.Assert; import org.junit.jupiter.api.Test; import java.util.Comparator; import java.util.HashMap; import java.util.Map; +import java.util.LinkedHashMap; +import java.util.TreeMap; /** * Test Cases for Map Builder */ -class MapBuilderTest { +public class MapBuilderTest { @Test void setComparator() { @@ -20,11 +39,9 @@ void setComparator() { myMap.put("X", 24); myMap.put("B", 2); myMap.put("Y", 26); - Map builderMap = new MapBuilder().setData(myMap).setComparator(null).build(); - Assert.assertEquals(myMap, builderMap); // Reverse comparator - builderMap = new MapBuilder().setData(myMap).setIterationOrder(MapBuilder.KeyOrder.COMPARATOR_ORDER).setComparator(Comparator.reverseOrder()).build(); + Map builderMap = new MapBuilder().setData(myMap).setIterationOrder(MapBuilder.KeyOrder.COMPARATOR_ORDER).setComparator(Comparator.reverseOrder()).build(); Assert.assertEquals(builderMap.keySet().stream().findFirst().get(), "Y"); Assert.assertEquals(builderMap.keySet().stream().skip(1).findFirst().get(), "X"); Assert.assertEquals(builderMap.keySet().stream().skip(2).findFirst().get(), "B"); @@ -40,7 +57,7 @@ void setIterationOrder() { myMap.put("B", 2); myMap.put("Y", 26); Map builderMap = new MapBuilder().setData(myMap).setIterationOrder(MapBuilder.KeyOrder.UNORDERED).build(); - Assert.assertEquals(myMap, builderMap); + Assert.assertTrue(builderMap instanceof HashedMap); //Key Order = INSERTION ORDER builderMap = new MapBuilder().setIterationOrder(MapBuilder.KeyOrder.INSERTION_ORDER).build(); @@ -48,10 +65,7 @@ void setIterationOrder() { builderMap.put("X", 24); builderMap.put("B", 2); builderMap.put("Y", 26); - Assert.assertEquals(builderMap.keySet().stream().findFirst().get(), "A"); - Assert.assertEquals(builderMap.keySet().stream().skip(1).findFirst().get(), "X"); - Assert.assertEquals(builderMap.keySet().stream().skip(2).findFirst().get(), "B"); - Assert.assertEquals(builderMap.keySet().stream().skip(3).findFirst().get(), "Y"); + Assert.assertTrue(builderMap instanceof LinkedHashMap); //Key Order = NATURAL ORDER builderMap = new MapBuilder().setIterationOrder(MapBuilder.KeyOrder.NATURAL_ORDER).build(); @@ -59,10 +73,7 @@ void setIterationOrder() { builderMap.put("X", 24); builderMap.put("B", 2); builderMap.put("Y", 26); - Assert.assertEquals(builderMap.keySet().stream().findFirst().get(), "A"); - Assert.assertEquals(builderMap.keySet().stream().skip(1).findFirst().get(), "B"); - Assert.assertEquals(builderMap.keySet().stream().skip(2).findFirst().get(), "X"); - Assert.assertEquals(builderMap.keySet().stream().skip(3).findFirst().get(), "Y"); + Assert.assertTrue(builderMap instanceof TreeMap); //Key Order = COMPARATOR ORDER and null comparator builderMap = new MapBuilder().setIterationOrder(MapBuilder.KeyOrder.COMPARATOR_ORDER).build(); @@ -70,10 +81,7 @@ void setIterationOrder() { builderMap.put("X", 24); builderMap.put("B", 2); builderMap.put("Y", 26); - Assert.assertEquals(builderMap.keySet().stream().findFirst().get(), "A"); - Assert.assertEquals(builderMap.keySet().stream().skip(1).findFirst().get(), "B"); - Assert.assertEquals(builderMap.keySet().stream().skip(2).findFirst().get(), "X"); - Assert.assertEquals(builderMap.keySet().stream().skip(3).findFirst().get(), "Y"); + Assert.assertTrue(builderMap instanceof TreeMap); //Key Order = COMPARATOR ORDER and valid comparator builderMap = new MapBuilder().setIterationOrder(MapBuilder.KeyOrder.COMPARATOR_ORDER).setComparator(Comparator.reverseOrder()).build(); @@ -81,10 +89,7 @@ void setIterationOrder() { builderMap.put("X", 24); builderMap.put("B", 2); builderMap.put("Y", 26); - Assert.assertEquals(builderMap.keySet().stream().findFirst().get(), "Y"); - Assert.assertEquals(builderMap.keySet().stream().skip(1).findFirst().get(), "X"); - Assert.assertEquals(builderMap.keySet().stream().skip(2).findFirst().get(), "B"); - Assert.assertEquals(builderMap.keySet().stream().skip(3).findFirst().get(), "A"); + Assert.assertTrue(builderMap instanceof TreeMap); } @Test @@ -100,7 +105,6 @@ void setImmutable() { exceptionThrown = true; } Assert.assertTrue(exceptionThrown); - Assert.assertEquals(myMap, builderMap); } @Test @@ -117,4 +121,4 @@ void build() { Map builderMap = new MapBuilder().build(); Assert.assertTrue(builderMap.size() == 0); } -} \ No newline at end of file +}