001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.collections.collection;
018
019 import java.util.Collection;
020 import java.util.Iterator;
021
022 import org.apache.commons.collections.Predicate;
023
024 /**
025 * Decorates another <code>Collection</code> to validate that additions
026 * match a specified predicate.
027 * <p>
028 * This collection exists to provide validation for the decorated collection.
029 * It is normally created to decorate an empty collection.
030 * If an object cannot be added to the collection, an IllegalArgumentException is thrown.
031 * <p>
032 * One usage would be to ensure that no null entries are added to the collection.
033 * <pre>Collection coll = PredicatedCollection.decorate(new ArrayList(), NotNullPredicate.INSTANCE);</pre>
034 * <p>
035 * This class is Serializable from Commons Collections 3.1.
036 *
037 * @since Commons Collections 3.0
038 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
039 *
040 * @author Stephen Colebourne
041 * @author Paul Jack
042 */
043 public class PredicatedCollection extends AbstractSerializableCollectionDecorator {
044
045 /** Serialization version */
046 private static final long serialVersionUID = -5259182142076705162L;
047
048 /** The predicate to use */
049 protected final Predicate predicate;
050
051 /**
052 * Factory method to create a predicated (validating) collection.
053 * <p>
054 * If there are any elements already in the collection being decorated, they
055 * are validated.
056 *
057 * @param coll the collection to decorate, must not be null
058 * @param predicate the predicate to use for validation, must not be null
059 * @return a new predicated collection
060 * @throws IllegalArgumentException if collection or predicate is null
061 * @throws IllegalArgumentException if the collection contains invalid elements
062 */
063 public static Collection decorate(Collection coll, Predicate predicate) {
064 return new PredicatedCollection(coll, predicate);
065 }
066
067 //-----------------------------------------------------------------------
068 /**
069 * Constructor that wraps (not copies).
070 * <p>
071 * If there are any elements already in the collection being decorated, they
072 * are validated.
073 *
074 * @param coll the collection to decorate, must not be null
075 * @param predicate the predicate to use for validation, must not be null
076 * @throws IllegalArgumentException if collection or predicate is null
077 * @throws IllegalArgumentException if the collection contains invalid elements
078 */
079 protected PredicatedCollection(Collection coll, Predicate predicate) {
080 super(coll);
081 if (predicate == null) {
082 throw new IllegalArgumentException("Predicate must not be null");
083 }
084 this.predicate = predicate;
085 for (Iterator it = coll.iterator(); it.hasNext(); ) {
086 validate(it.next());
087 }
088 }
089
090 /**
091 * Validates the object being added to ensure it matches the predicate.
092 * <p>
093 * The predicate itself should not throw an exception, but return false to
094 * indicate that the object cannot be added.
095 *
096 * @param object the object being added
097 * @throws IllegalArgumentException if the add is invalid
098 */
099 protected void validate(Object object) {
100 if (predicate.evaluate(object) == false) {
101 throw new IllegalArgumentException("Cannot add Object '" + object + "' - Predicate rejected it");
102 }
103 }
104
105 //-----------------------------------------------------------------------
106 /**
107 * Override to validate the object being added to ensure it matches
108 * the predicate.
109 *
110 * @param object the object being added
111 * @return the result of adding to the underlying collection
112 * @throws IllegalArgumentException if the add is invalid
113 */
114 public boolean add(Object object) {
115 validate(object);
116 return getCollection().add(object);
117 }
118
119 /**
120 * Override to validate the objects being added to ensure they match
121 * the predicate. If any one fails, no update is made to the underlying
122 * collection.
123 *
124 * @param coll the collection being added
125 * @return the result of adding to the underlying collection
126 * @throws IllegalArgumentException if the add is invalid
127 */
128 public boolean addAll(Collection coll) {
129 for (Iterator it = coll.iterator(); it.hasNext(); ) {
130 validate(it.next());
131 }
132 return getCollection().addAll(coll);
133 }
134
135 }