commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From t.@apache.org
Subject svn commit: r1654518 - in /commons/proper/collections/trunk/src: changes/changes.xml main/java/org/apache/commons/collections4/collection/PredicatedCollection.java test/java/org/apache/commons/collections4/collection/PredicatedCollectionBuilderTest.java
Date Sat, 24 Jan 2015 14:03:40 GMT
Author: tn
Date: Sat Jan 24 14:03:40 2015
New Revision: 1654518

URL: http://svn.apache.org/r1654518
Log:
[COLLECTIONS-530] Added Builder for PredicatedCollection. Thanks to Erik.

Added:
    commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/collection/PredicatedCollectionBuilderTest.java
  (with props)
Modified:
    commons/proper/collections/trunk/src/changes/changes.xml
    commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/collection/PredicatedCollection.java

Modified: commons/proper/collections/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/changes/changes.xml?rev=1654518&r1=1654517&r2=1654518&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/changes/changes.xml (original)
+++ commons/proper/collections/trunk/src/changes/changes.xml Sat Jan 24 14:03:40 2015
@@ -22,6 +22,11 @@
   <body>
 
   <release version="4.1" date="TBD" description="">
+    <action issue="COLLECTIONS-530" dev="tn" type="fix" due-to="Erik">
+      Added a Builder for "PredicatedCollection". Elements added to the builder
+      that fail the predicate will not throw an IllegalArgumentException. The builder
+      supports creating predicated lists, bags, sets and queues.
+    </action>
     <action issue="COLLECTIONS-545" dev="tn" type="fix" due-to="Oswaldo Olivo">
       Documented runtime complexity of "CollectionUtils#removeAll(Collection, Collection).
     </action>

Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/collection/PredicatedCollection.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/collection/PredicatedCollection.java?rev=1654518&r1=1654517&r2=1654518&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/collection/PredicatedCollection.java
(original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/collection/PredicatedCollection.java
Sat Jan 24 14:03:40 2015
@@ -16,9 +16,23 @@
  */
 package org.apache.commons.collections4.collection;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
 
+import org.apache.commons.collections4.Bag;
 import org.apache.commons.collections4.Predicate;
+import org.apache.commons.collections4.bag.HashBag;
+import org.apache.commons.collections4.bag.PredicatedBag;
+import org.apache.commons.collections4.functors.NotNullPredicate;
+import org.apache.commons.collections4.list.PredicatedList;
+import org.apache.commons.collections4.queue.PredicatedQueue;
+import org.apache.commons.collections4.set.PredicatedSet;
 
 /**
  * Decorates another {@link Collection} to validate that additions
@@ -28,8 +42,10 @@ import org.apache.commons.collections4.P
  * It is normally created to decorate an empty collection.
  * If an object cannot be added to the collection, an IllegalArgumentException is thrown.
  * <p>
- * One usage would be to ensure that no null entries are added to the collection.
- * <pre>Collection coll = PredicatedCollection.decorate(new ArrayList(), NotNullPredicate.INSTANCE);</pre>
+ * One usage would be to ensure that no null entries are added to the collection:
+ * <pre>
+ * Collection coll = PredicatedCollection.predicatedCollection(new ArrayList(), NotNullPredicate.INSTANCE);
+ * </pre>
  * <p>
  * This class is Serializable from Commons Collections 3.1.
  *
@@ -46,6 +62,29 @@ public class PredicatedCollection<E> ext
     protected final Predicate<? super E> predicate;
 
     /**
+     * Returns a Builder with the given predicate.
+     *
+     * @param <E>  the element type
+     * @param predicate  the predicate to use
+     * @return a new Builder for predicated collections
+     * @since 4.1
+     */
+    public static <E> Builder<E> builder(final Predicate<? super E> predicate)
{
+        return new Builder<E>(predicate);
+    }
+
+    /**
+     * Returns a Builder with a NotNullPredicate.
+     *
+     * @param <E>  the element type
+     * @return a new Builder for predicated collections that ignores null values.
+     * @since 4.1
+     */
+    public static <E> Builder<E> notNullBuilder() {
+        return new Builder<E>(NotNullPredicate.<E>notNullPredicate());
+    }
+
+    /**
      * Factory method to create a predicated (validating) collection.
      * <p>
      * If there are any elements already in the collection being decorated, they
@@ -135,4 +174,230 @@ public class PredicatedCollection<E> ext
         return decorated().addAll(coll);
     }
 
+    /**
+     * Builder for creating predicated collections.
+     * <p>
+     * Create a Builder with a predicate to validate elements against, then add any elements
+     * to the builder. Elements that fail the predicate will be added to a rejected list.
+     * Finally create or decorate a collection using the createPredicated[List,Set,Bag,Queue]
methods.
+     * <p>
+     * An example:
+     * <pre>
+     *   Predicate&lt;String&gt; predicate = NotNullPredicate.notNullPredicate();
+     *   PredicatedCollectionBuilder&lt;String&gt; builder = PredicatedCollection.builder(predicate);
+     *   builder.add("item1");
+     *   builder.add(null);
+     *   builder.add("item2");
+     *   List&lt;String&gt; predicatedList = builder.createPredicatedList();
+     * </pre>
+     * <p>
+     * At the end of the code fragment above predicatedList is protected by the predicate
supplied
+     * to the builder and it contains item1 and item2.
+     * <p>
+     * More elements can be added to the builder once a predicated collection has been created,
+     * but these elements will not be reflected in already created collections.
+     *
+     * @param <E>  the element type
+     * @since 4.1
+     */
+    public static class Builder<E> {
+
+        /** The predicate to use. */
+        private final Predicate<? super E> predicate;
+
+        /** The buffer containing valid elements. */
+        private final List<E> accepted = new ArrayList<E>();
+
+        /** The buffer containing rejected elements. */
+        private final List<E> rejected = new ArrayList<E>();
+
+        // -----------------------------------------------------------------------
+        /**
+         * Constructs a PredicatedCollectionBuilder with the specified Predicate.
+         *
+         * @param predicate  the predicate to use
+         * @throws IllegalArgumentException if predicate is null
+         */
+        public Builder(final Predicate<? super E> predicate) {
+            if (predicate == null) {
+                throw new IllegalArgumentException("Predicate must not be null");
+            }
+            this.predicate = predicate;
+        }
+
+        /**
+         * Adds the item to the builder.
+         * <p>
+         * If the predicate is true, it is added to the list of accepted elements,
+         * otherwise it is added to the rejected list.
+         *
+         * @param item  the element to add
+         * @return the PredicatedCollectionBuilder.
+         */
+        public Builder<E> add(final E item) {
+            if (predicate.evaluate(item)) {
+                accepted.add(item);
+            } else {
+                rejected.add(item);
+            }
+            return this;
+        }
+
+        /**
+         * Adds all elements from the given collection to the builder.
+         * <p>
+         * All elements for which the predicate evaluates to true will be added to the
+         * list of accepted elements, otherwise they are added to the rejected list.
+         *
+         * @param items  the elements to add to the builder
+         * @return the PredicatedCollectionBuilder.
+         */
+        public Builder<E> addAll(final Collection<? extends E> items) {
+            if (items != null) {
+                for (E item : items) {
+                    add(item);
+                }
+            }
+            return this;
+        }
+
+        /**
+         * Create a new predicated list filled with the accepted elements.
+         * <p>
+         * The builder is not modified by this method, so it is possible to create more collections
+         * or add more elements afterwards. Further changes will not propagate to the returned
list.
+         *
+         * @return a new predicated list.
+         */
+        public List<E> createPredicatedList() {
+            return createPredicatedList(new ArrayList<E>());
+        }
+
+        /**
+         * Decorates the given list with validating behavior using the predicate. All accepted
elements
+         * are appended to the list. If the list already contains elements, they are validated.
+         * <p>
+         * The builder is not modified by this method, so it is possible to create more collections
+         * or add more elements afterwards. Further changes will not propagate to the returned
list.
+         *
+         * @param list  the List to decorate, must not be null
+         * @return the decorated list.
+         * @throws IllegalArgumentException if list is null or contains invalid elements
+         */
+        public List<E> createPredicatedList(final List<E> list) {
+            if (list == null) {
+                throw new IllegalArgumentException("list must not be null");
+            }
+            final List<E> predicatedList = PredicatedList.predicatedList(list, predicate);
+            predicatedList.addAll(accepted);
+            return predicatedList;
+        }
+
+        /**
+         * Create a new predicated set filled with the accepted elements.
+         * <p>
+         * The builder is not modified by this method, so it is possible to create more collections
+         * or add more elements afterwards. Further changes will not propagate to the returned
set.
+         *
+         * @return a new predicated set.
+         */
+        public Set<E> createPredicatedSet() {
+            return createPredicatedSet(new HashSet<E>());
+        }
+
+        /**
+         * Decorates the given list with validating behavior using the predicate. All accepted
elements
+         * are appended to the set. If the set already contains elements, they are validated.
+         * <p>
+         * The builder is not modified by this method, so it is possible to create more collections
+         * or add more elements afterwards. Further changes will not propagate to the returned
set.
+         *
+         * @param set  the set to decorate, must not be null
+         * @return the decorated set.
+         * @throws IllegalArgumentException if set is null or contains invalid elements
+         */
+        public Set<E> createPredicatedSet(final Set<E> set) {
+            if (set == null) {
+                throw new IllegalArgumentException("set must not be null");
+            }
+            final PredicatedSet<E> predicatedSet = PredicatedSet.predicatedSet(set,
predicate);
+            predicatedSet.addAll(accepted);
+            return predicatedSet;
+        }
+
+        /**
+         * Create a new predicated bag filled with the accepted elements.
+         * <p>
+         * The builder is not modified by this method, so it is possible to create more collections
+         * or add more elements afterwards. Further changes will not propagate to the returned
bag.
+         *
+         * @return a new predicated bag.
+         */
+        public Bag<E> createPredicatedBag() {
+            return createPredicatedBag(new HashBag<E>());
+        }
+
+        /**
+         * Decorates the given bag with validating behavior using the predicate. All accepted
elements
+         * are appended to the bag. If the bag already contains elements, they are validated.
+         * <p>
+         * The builder is not modified by this method, so it is possible to create more collections
+         * or add more elements afterwards. Further changes will not propagate to the returned
bag.
+         *
+         * @param bag  the bag to decorate, must not be null
+         * @return the decorated bag.
+         * @throws IllegalArgumentException if bag is null or contains invalid elements
+         */
+        public Bag<E> createPredicatedBag(final Bag<E> bag) {
+            if (bag == null) {
+                throw new IllegalArgumentException("bag must not be null");
+            }
+            final PredicatedBag<E> predicatedBag = PredicatedBag.predicatedBag(bag,
predicate);
+            predicatedBag.addAll(accepted);
+            return predicatedBag;
+        }
+
+        /**
+         * Create a new predicated queue filled with the accepted elements.
+         * <p>
+         * The builder is not modified by this method, so it is possible to create more collections
+         * or add more elements afterwards. Further changes will not propagate to the returned
queue.
+         *
+         * @return a new predicated queue.
+         */
+        public Queue<E> createPredicatedQueue() {
+            return createPredicatedQueue(new LinkedList<E>());
+        }
+
+        /**
+         * Decorates the given queue with validating behavior using the predicate. All accepted
elements
+         * are appended to the queue. If the queue already contains elements, they are validated.
+         * <p>
+         * The builder is not modified by this method, so it is possible to create more collections
+         * or add more elements afterwards. Further changes will not propagate to the returned
queue.
+         *
+         * @param queue  the queue to decorate, must not be null
+         * @return the decorated queue.
+         * @throws IllegalArgumentException if queue is null or contains invalid elements
+         */
+        public Queue<E> createPredicatedQueue(final Queue<E> queue) {
+            if (queue == null) {
+                throw new IllegalArgumentException("queue must not be null");
+            }
+            final PredicatedQueue<E> predicatedQueue = PredicatedQueue.predicatedQueue(queue,
predicate);
+            predicatedQueue.addAll(accepted);
+            return predicatedQueue;
+        }
+
+        /**
+         * Returns an unmodifiable collection containing all rejected elements.
+         *
+         * @return an unmodifiable collection
+         */
+        public Collection<E> rejectedElements() {
+            return Collections.unmodifiableCollection(rejected);
+        }
+
+    }
+
 }

Added: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/collection/PredicatedCollectionBuilderTest.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/collection/PredicatedCollectionBuilderTest.java?rev=1654518&view=auto
==============================================================================
--- commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/collection/PredicatedCollectionBuilderTest.java
(added)
+++ commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/collection/PredicatedCollectionBuilderTest.java
Sat Jan 24 14:03:40 2015
@@ -0,0 +1,144 @@
+/*
+ * 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.collection;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
+
+import org.apache.commons.collections4.Bag;
+import org.apache.commons.collections4.Predicate;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests the PredicatedCollection.Builder class.
+ * 
+ * @since 4.1
+ * @version $Id$
+ */
+public class PredicatedCollectionBuilderTest {
+
+    /**
+     * Verify that passing the Predicate means ending up in the buffer.
+     */
+    @Test
+    public void addPass() {
+        PredicatedCollection.Builder<String> builder = PredicatedCollection.notNullBuilder();
+        builder.add("test");
+        Assert.assertEquals(builder.createPredicatedList().size(), 1);
+    }
+
+    /**
+     * Verify that failing the Predicate means NOT ending up in the buffer.
+     */
+    @Test
+    public void addFail() {
+        PredicatedCollection.Builder<String> builder = PredicatedCollection.notNullBuilder();
+        builder.add((String) null);
+        Assert.assertTrue(builder.createPredicatedList().isEmpty());
+        
+        Assert.assertEquals(1, builder.rejectedElements().size());
+    }
+
+    /**
+     * Verify that only items that pass the Predicate end up in the buffer.
+     */
+    @Test
+    public void addAllPass() {
+        PredicatedCollection.Builder<String> builder = PredicatedCollection.notNullBuilder();
+        builder.addAll(Arrays.asList("test1", null, "test2"));
+        Assert.assertEquals(builder.createPredicatedList().size(), 2);
+    }
+
+    @Test
+    public void createPredicatedCollectionWithNotNullPredicate() {
+        PredicatedCollection.Builder<String> builder = PredicatedCollection.notNullBuilder();
+        builder.add("test1");
+        builder.add((String) null);
+
+        List<String> predicatedList = builder.createPredicatedList();
+        checkPredicatedCollection1(predicatedList);
+        
+        Set<String> predicatedSet = builder.createPredicatedSet();
+        checkPredicatedCollection1(predicatedSet);
+
+        Bag<String> predicatedBag = builder.createPredicatedBag();
+        checkPredicatedCollection1(predicatedBag);
+
+        Queue<String> predicatedQueue = builder.createPredicatedQueue();
+        checkPredicatedCollection1(predicatedQueue);
+    }
+    
+    private void checkPredicatedCollection1(final Collection<String> collection) {
+        Assert.assertEquals(1, collection.size());
+
+        collection.add("test2");
+        Assert.assertEquals(2, collection.size());
+
+        try {
+            collection.add(null);
+            Assert.fail("Expecting IllegalArgumentException for failing predicate!");
+        } catch (IllegalArgumentException iae) {
+            // expected
+        }
+    }
+
+    @Test
+    public void createPredicatedCollectionWithPredicate() {
+        OddPredicate p = new OddPredicate();
+        PredicatedCollection.Builder<Integer> builder = PredicatedCollection.builder(p);
+
+        builder.add(1);
+        builder.add(2);
+        builder.add(3);
+
+        List<Integer> predicatedList = builder.createPredicatedList();
+        checkPredicatedCollection2(predicatedList);
+        
+        Set<Integer> predicatedSet = builder.createPredicatedSet();
+        checkPredicatedCollection2(predicatedSet);
+
+        Bag<Integer> predicatedBag = builder.createPredicatedBag();
+        checkPredicatedCollection2(predicatedBag);
+
+        Queue<Integer> predicatedQueue = builder.createPredicatedQueue();
+        checkPredicatedCollection2(predicatedQueue);
+    }
+
+    private void checkPredicatedCollection2(final Collection<Integer> collection) {
+        Assert.assertEquals(2, collection.size());
+
+        try {
+            collection.add(4);
+            Assert.fail("Expecting IllegalArgumentException for failing predicate!");
+        } catch (IllegalArgumentException iae) {
+        }
+        Assert.assertEquals(2, collection.size());
+
+        collection.add(5);
+        Assert.assertEquals(3, collection.size());
+    }
+
+    private static class OddPredicate implements Predicate<Integer> {
+        public boolean evaluate(Integer value) {
+            return value % 2 == 1;
+        }
+    }
+}

Propchange: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/collection/PredicatedCollectionBuilderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/collection/PredicatedCollectionBuilderTest.java
------------------------------------------------------------------------------
    svn:keywords = Id Revision HeadURL

Propchange: commons/proper/collections/trunk/src/test/java/org/apache/commons/collections4/collection/PredicatedCollectionBuilderTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message