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;
018
019 import org.apache.commons.collections.bag.HashBag;
020 import org.apache.commons.collections.bag.PredicatedBag;
021 import org.apache.commons.collections.bag.PredicatedSortedBag;
022 import org.apache.commons.collections.bag.SynchronizedBag;
023 import org.apache.commons.collections.bag.SynchronizedSortedBag;
024 import org.apache.commons.collections.bag.TransformedBag;
025 import org.apache.commons.collections.bag.TransformedSortedBag;
026 import org.apache.commons.collections.bag.TreeBag;
027 import org.apache.commons.collections.bag.TypedBag;
028 import org.apache.commons.collections.bag.TypedSortedBag;
029 import org.apache.commons.collections.bag.UnmodifiableBag;
030 import org.apache.commons.collections.bag.UnmodifiableSortedBag;
031
032 /**
033 * Provides utility methods and decorators for
034 * {@link Bag} and {@link SortedBag} instances.
035 *
036 * @since Commons Collections 2.1
037 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
038 *
039 * @author Paul Jack
040 * @author Stephen Colebourne
041 * @author Andrew Freeman
042 * @author Matthew Hawthorne
043 */
044 public class BagUtils {
045
046 /**
047 * An empty unmodifiable bag.
048 */
049 public static final Bag EMPTY_BAG = UnmodifiableBag.decorate(new HashBag());
050
051 /**
052 * An empty unmodifiable sorted bag.
053 */
054 public static final Bag EMPTY_SORTED_BAG = UnmodifiableSortedBag.decorate(new TreeBag());
055
056 /**
057 * Instantiation of BagUtils is not intended or required.
058 * However, some tools require an instance to operate.
059 */
060 public BagUtils() {
061 }
062
063 //-----------------------------------------------------------------------
064 /**
065 * Returns a synchronized (thread-safe) bag backed by the given bag.
066 * In order to guarantee serial access, it is critical that all
067 * access to the backing bag is accomplished through the returned bag.
068 * <p>
069 * It is imperative that the user manually synchronize on the returned
070 * bag when iterating over it:
071 *
072 * <pre>
073 * Bag bag = BagUtils.synchronizedBag(new HashBag());
074 * ...
075 * synchronized(bag) {
076 * Iterator i = bag.iterator(); // Must be in synchronized block
077 * while (i.hasNext())
078 * foo(i.next());
079 * }
080 * }
081 * </pre>
082 *
083 * Failure to follow this advice may result in non-deterministic
084 * behavior.
085 *
086 * @param bag the bag to synchronize, must not be null
087 * @return a synchronized bag backed by that bag
088 * @throws IllegalArgumentException if the Bag is null
089 */
090 public static Bag synchronizedBag(Bag bag) {
091 return SynchronizedBag.decorate(bag);
092 }
093
094 /**
095 * Returns an unmodifiable view of the given bag. Any modification
096 * attempts to the returned bag will raise an
097 * {@link UnsupportedOperationException}.
098 *
099 * @param bag the bag whose unmodifiable view is to be returned, must not be null
100 * @return an unmodifiable view of that bag
101 * @throws IllegalArgumentException if the Bag is null
102 */
103 public static Bag unmodifiableBag(Bag bag) {
104 return UnmodifiableBag.decorate(bag);
105 }
106
107 /**
108 * Returns a predicated (validating) bag backed by the given bag.
109 * <p>
110 * Only objects that pass the test in the given predicate can be added to the bag.
111 * Trying to add an invalid object results in an IllegalArgumentException.
112 * It is important not to use the original bag after invoking this method,
113 * as it is a backdoor for adding invalid objects.
114 *
115 * @param bag the bag to predicate, must not be null
116 * @param predicate the predicate for the bag, must not be null
117 * @return a predicated bag backed by the given bag
118 * @throws IllegalArgumentException if the Bag or Predicate is null
119 */
120 public static Bag predicatedBag(Bag bag, Predicate predicate) {
121 return PredicatedBag.decorate(bag, predicate);
122 }
123
124 /**
125 * Returns a typed bag backed by the given bag.
126 * <p>
127 * Only objects of the specified type can be added to the bag.
128 *
129 * @param bag the bag to limit to a specific type, must not be null
130 * @param type the type of objects which may be added to the bag
131 * @return a typed bag backed by the specified bag
132 */
133 public static Bag typedBag(Bag bag, Class type) {
134 return TypedBag.decorate(bag, type);
135 }
136
137 /**
138 * Returns a transformed bag backed by the given bag.
139 * <p>
140 * Each object is passed through the transformer as it is added to the
141 * Bag. It is important not to use the original bag after invoking this
142 * method, as it is a backdoor for adding untransformed objects.
143 *
144 * @param bag the bag to predicate, must not be null
145 * @param transformer the transformer for the bag, must not be null
146 * @return a transformed bag backed by the given bag
147 * @throws IllegalArgumentException if the Bag or Transformer is null
148 */
149 public static Bag transformedBag(Bag bag, Transformer transformer) {
150 return TransformedBag.decorate(bag, transformer);
151 }
152
153 //-----------------------------------------------------------------------
154 /**
155 * Returns a synchronized (thread-safe) sorted bag backed by the given
156 * sorted bag.
157 * In order to guarantee serial access, it is critical that all
158 * access to the backing bag is accomplished through the returned bag.
159 * <p>
160 * It is imperative that the user manually synchronize on the returned
161 * bag when iterating over it:
162 *
163 * <pre>
164 * SortedBag bag = BagUtils.synchronizedSortedBag(new TreeBag());
165 * ...
166 * synchronized(bag) {
167 * Iterator i = bag.iterator(); // Must be in synchronized block
168 * while (i.hasNext())
169 * foo(i.next());
170 * }
171 * }
172 * </pre>
173 *
174 * Failure to follow this advice may result in non-deterministic
175 * behavior.
176 *
177 * @param bag the bag to synchronize, must not be null
178 * @return a synchronized bag backed by that bag
179 * @throws IllegalArgumentException if the SortedBag is null
180 */
181 public static SortedBag synchronizedSortedBag(SortedBag bag) {
182 return SynchronizedSortedBag.decorate(bag);
183 }
184
185 /**
186 * Returns an unmodifiable view of the given sorted bag. Any modification
187 * attempts to the returned bag will raise an
188 * {@link UnsupportedOperationException}.
189 *
190 * @param bag the bag whose unmodifiable view is to be returned, must not be null
191 * @return an unmodifiable view of that bag
192 * @throws IllegalArgumentException if the SortedBag is null
193 */
194 public static SortedBag unmodifiableSortedBag(SortedBag bag) {
195 return UnmodifiableSortedBag.decorate(bag);
196 }
197
198 /**
199 * Returns a predicated (validating) sorted bag backed by the given sorted bag.
200 * <p>
201 * Only objects that pass the test in the given predicate can be added to the bag.
202 * Trying to add an invalid object results in an IllegalArgumentException.
203 * It is important not to use the original bag after invoking this method,
204 * as it is a backdoor for adding invalid objects.
205 *
206 * @param bag the sorted bag to predicate, must not be null
207 * @param predicate the predicate for the bag, must not be null
208 * @return a predicated bag backed by the given bag
209 * @throws IllegalArgumentException if the SortedBag or Predicate is null
210 */
211 public static SortedBag predicatedSortedBag(SortedBag bag, Predicate predicate) {
212 return PredicatedSortedBag.decorate(bag, predicate);
213 }
214
215 /**
216 * Returns a typed sorted bag backed by the given bag.
217 * <p>
218 * Only objects of the specified type can be added to the bag.
219 *
220 * @param bag the bag to limit to a specific type, must not be null
221 * @param type the type of objects which may be added to the bag
222 * @return a typed bag backed by the specified bag
223 */
224 public static SortedBag typedSortedBag(SortedBag bag, Class type) {
225 return TypedSortedBag.decorate(bag, type);
226 }
227
228 /**
229 * Returns a transformed sorted bag backed by the given bag.
230 * <p>
231 * Each object is passed through the transformer as it is added to the
232 * Bag. It is important not to use the original bag after invoking this
233 * method, as it is a backdoor for adding untransformed objects.
234 *
235 * @param bag the bag to predicate, must not be null
236 * @param transformer the transformer for the bag, must not be null
237 * @return a transformed bag backed by the given bag
238 * @throws IllegalArgumentException if the Bag or Transformer is null
239 */
240 public static SortedBag transformedSortedBag(SortedBag bag, Transformer transformer) {
241 return TransformedSortedBag.decorate(bag, transformer);
242 }
243
244 }