View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections;
18  
19  import org.apache.commons.collections.bag.HashBag;
20  import org.apache.commons.collections.bag.PredicatedBag;
21  import org.apache.commons.collections.bag.PredicatedSortedBag;
22  import org.apache.commons.collections.bag.SynchronizedBag;
23  import org.apache.commons.collections.bag.SynchronizedSortedBag;
24  import org.apache.commons.collections.bag.TransformedBag;
25  import org.apache.commons.collections.bag.TransformedSortedBag;
26  import org.apache.commons.collections.bag.TreeBag;
27  import org.apache.commons.collections.bag.UnmodifiableBag;
28  import org.apache.commons.collections.bag.UnmodifiableSortedBag;
29  
30  /**
31   * Provides utility methods and decorators for {@link Bag} and {@link SortedBag} instances.
32   *
33   * @since 2.1
34   * @version $Id: BagUtils.java 1436066 2013-01-21 01:28:08Z sebb $
35   */
36  public class BagUtils {
37  
38      /**
39       * An empty unmodifiable bag.
40       */
41      public static final Bag<Object> EMPTY_BAG = UnmodifiableBag.unmodifiableBag(new HashBag<Object>());
42  
43      /**
44       * An empty unmodifiable sorted bag.
45       */
46      public static final Bag<Object> EMPTY_SORTED_BAG =
47              UnmodifiableSortedBag.unmodifiableSortedBag(new TreeBag<Object>());
48  
49      /**
50       * Instantiation of BagUtils is not intended or required. However, some
51       * tools require an instance to operate.
52       */
53      public BagUtils() {
54      }
55  
56      //-----------------------------------------------------------------------
57      /**
58       * Returns a synchronized (thread-safe) bag backed by the given bag. In
59       * order to guarantee serial access, it is critical that all access to the
60       * backing bag is accomplished through the returned bag.
61       * <p>
62       * It is imperative that the user manually synchronize on the returned bag
63       * when iterating over it:
64       * 
65       * <pre>
66       * Bag bag = BagUtils.synchronizedBag(new HashBag());
67       * ...
68       * synchronized(bag) {
69       *     Iterator i = bag.iterator(); // Must be in synchronized block
70       *     while (i.hasNext())
71       *         foo(i.next());
72       *     }
73       * }
74       * </pre>
75       * 
76       * Failure to follow this advice may result in non-deterministic behavior.
77       * 
78       * @param <E> the element type
79       * @param bag the bag to synchronize, must not be null
80       * @return a synchronized bag backed by that bag
81       * @throws IllegalArgumentException if the Bag is null
82       */
83      public static <E> Bag<E> synchronizedBag(final Bag<E> bag) {
84          return SynchronizedBag.synchronizedBag(bag);
85      }
86  
87      /**
88       * Returns an unmodifiable view of the given bag. Any modification attempts
89       * to the returned bag will raise an {@link UnsupportedOperationException}.
90       * 
91       * @param <E> the element type
92       * @param bag the bag whose unmodifiable view is to be returned, must not be null
93       * @return an unmodifiable view of that bag
94       * @throws IllegalArgumentException if the Bag is null
95       */
96      public static <E> Bag<E> unmodifiableBag(final Bag<E> bag) {
97          return UnmodifiableBag.unmodifiableBag(bag);
98      }
99  
100     /**
101      * Returns a predicated (validating) bag backed by the given bag.
102      * <p>
103      * Only objects that pass the test in the given predicate can be added to
104      * the bag. Trying to add an invalid object results in an
105      * IllegalArgumentException. It is important not to use the original bag
106      * after invoking this method, as it is a backdoor for adding invalid
107      * objects.
108      * 
109      * @param <E> the element type
110      * @param bag the bag to predicate, must not be null
111      * @param predicate the predicate for the bag, must not be null
112      * @return a predicated bag backed by the given bag
113      * @throws IllegalArgumentException if the Bag or Predicate is null
114      */
115     public static <E> Bag<E> predicatedBag(final Bag<E> bag, final Predicate<? super E> predicate) {
116         return PredicatedBag.predicatedBag(bag, predicate);
117     }
118 
119     /**
120      * Returns a transformed bag backed by the given bag.
121      * <p>
122      * Each object is passed through the transformer as it is added to the Bag.
123      * It is important not to use the original bag after invoking this method,
124      * as it is a backdoor for adding untransformed objects.
125      * <p>
126      * Existing entries in the specified bag will not be transformed.
127      * If you want that behaviour, see {@link TransformedBag#transformedBag(Bag, Transformer)}.
128      * 
129      * @param <E> the element type
130      * @param bag the bag to predicate, must not be null
131      * @param transformer the transformer for the bag, must not be null
132      * @return a transformed bag backed by the given bag
133      * @throws IllegalArgumentException if the Bag or Transformer is null
134      */
135     public static <E> Bag<E> transformingBag(final Bag<E> bag, final Transformer<? super E, ? extends E> transformer) {
136         return TransformedBag.transformingBag(bag, transformer);
137     }
138 
139     //-----------------------------------------------------------------------
140     /**
141      * Returns a synchronized (thread-safe) sorted bag backed by the given
142      * sorted bag. In order to guarantee serial access, it is critical that all
143      * access to the backing bag is accomplished through the returned bag.
144      * <p>
145      * It is imperative that the user manually synchronize on the returned bag
146      * when iterating over it:
147      * 
148      * <pre>
149      * SortedBag bag = BagUtils.synchronizedSortedBag(new TreeBag());
150      * ...
151      * synchronized(bag) {
152      *     Iterator i = bag.iterator(); // Must be in synchronized block
153      *     while (i.hasNext())
154      *         foo(i.next());
155      *     }
156      * }
157      * </pre>
158      * 
159      * Failure to follow this advice may result in non-deterministic behavior.
160      * 
161      * @param <E> the element type
162      * @param bag the bag to synchronize, must not be null
163      * @return a synchronized bag backed by that bag
164      * @throws IllegalArgumentException if the SortedBag is null
165      */
166     public static <E> SortedBag<E> synchronizedSortedBag(final SortedBag<E> bag) {
167         return SynchronizedSortedBag.synchronizedSortedBag(bag);
168     }
169 
170     /**
171      * Returns an unmodifiable view of the given sorted bag. Any modification
172      * attempts to the returned bag will raise an
173      * {@link UnsupportedOperationException}.
174      * 
175      * @param <E> the element type
176      * @param bag the bag whose unmodifiable view is to be returned, must not be null
177      * @return an unmodifiable view of that bag
178      * @throws IllegalArgumentException if the SortedBag is null
179      */
180     public static <E> SortedBag<E> unmodifiableSortedBag(final SortedBag<E> bag) {
181         return UnmodifiableSortedBag.unmodifiableSortedBag(bag);
182     }
183 
184     /**
185      * Returns a predicated (validating) sorted bag backed by the given sorted
186      * bag.
187      * <p>
188      * Only objects that pass the test in the given predicate can be added to
189      * the bag. Trying to add an invalid object results in an
190      * IllegalArgumentException. It is important not to use the original bag
191      * after invoking this method, as it is a backdoor for adding invalid
192      * objects.
193      * 
194      * @param <E> the element type
195      * @param bag the sorted bag to predicate, must not be null
196      * @param predicate the predicate for the bag, must not be null
197      * @return a predicated bag backed by the given bag
198      * @throws IllegalArgumentException if the SortedBag or Predicate is null
199      */
200     public static <E> SortedBag<E> predicatedSortedBag(final SortedBag<E> bag,
201             final Predicate<? super E> predicate) {
202         return PredicatedSortedBag.predicatedSortedBag(bag, predicate);
203     }
204 
205     /**
206      * Returns a transformed sorted bag backed by the given bag.
207      * <p>
208      * Each object is passed through the transformer as it is added to the Bag.
209      * It is important not to use the original bag after invoking this method,
210      * as it is a backdoor for adding untransformed objects.
211      * <p>
212      * Existing entries in the specified bag will not be transformed.
213      * If you want that behaviour, see
214      * {@link TransformedSortedBag#transformedSortedBag(SortedBag, Transformer)}.
215      * 
216      * @param <E> the element type
217      * @param bag the bag to predicate, must not be null
218      * @param transformer the transformer for the bag, must not be null
219      * @return a transformed bag backed by the given bag
220      * @throws IllegalArgumentException if the Bag or Transformer is null
221      */
222     public static <E> SortedBag<E> transformingSortedBag(final SortedBag<E> bag,
223                                                          final Transformer<? super E, ? extends E> transformer) {
224         return TransformedSortedBag.transformingSortedBag(bag, transformer);
225     }
226 
227     /**
228      * Get an empty <code>Bag</code>.
229      *
230      * @param <E> the element type
231      * @return an empty Bag
232      */
233     @SuppressWarnings("unchecked") // OK, empty bag is compatible with any type
234     public static <E> Bag<E> emptyBag() {
235         return (Bag<E>) EMPTY_BAG;        
236     }
237 
238     /**
239      * Get an empty <code>SortedBag</code>.
240      *
241      * @param <E> the element type
242      * @return an empty sorted Bag
243      */
244     @SuppressWarnings("unchecked") // OK, empty bag is compatible with any type
245     public static <E> SortedBag<E> emptySortedBag() {
246         return (SortedBag<E>) EMPTY_SORTED_BAG;        
247     }
248 }