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 *      https://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 */
017package org.apache.commons.collections4;
018
019import org.apache.commons.collections4.bag.CollectionBag;
020import org.apache.commons.collections4.bag.HashBag;
021import org.apache.commons.collections4.bag.PredicatedBag;
022import org.apache.commons.collections4.bag.PredicatedSortedBag;
023import org.apache.commons.collections4.bag.SynchronizedBag;
024import org.apache.commons.collections4.bag.SynchronizedSortedBag;
025import org.apache.commons.collections4.bag.TransformedBag;
026import org.apache.commons.collections4.bag.TransformedSortedBag;
027import org.apache.commons.collections4.bag.TreeBag;
028import org.apache.commons.collections4.bag.UnmodifiableBag;
029import org.apache.commons.collections4.bag.UnmodifiableSortedBag;
030
031/**
032 * Provides utility methods and decorators for {@link Bag} and {@link SortedBag} instances.
033 *
034 * @since 2.1
035 * @deprecated Since 4.6.0, use {@link MultiSetUtils} instead.
036 */
037@Deprecated
038public class BagUtils {
039
040    /**
041     * An empty unmodifiable bag.
042     */
043    @SuppressWarnings("rawtypes") // OK, empty bag is compatible with any type
044    public static final Bag EMPTY_BAG = UnmodifiableBag.unmodifiableBag(new HashBag<>());
045
046    /**
047     * An empty unmodifiable sorted bag.
048     */
049    @SuppressWarnings("rawtypes") // OK, empty bag is compatible with any type
050    public static final Bag EMPTY_SORTED_BAG =
051            UnmodifiableSortedBag.unmodifiableSortedBag(new TreeBag<>());
052
053    /**
054     * Returns a bag that complies to the Collection contract, backed by the given bag.
055     *
056     * @param <E> The element type
057     * @param bag The bag to decorate, must not be null
058     * @return A Bag that complies to the Collection contract
059     * @throws NullPointerException if bag is null
060     * @since 4.0
061     */
062    public static <E> Bag<E> collectionBag(final Bag<E> bag) {
063        return CollectionBag.collectionBag(bag);
064    }
065
066    /**
067     * Gets an empty {@code Bag}.
068     *
069     * @param <E> The element type
070     * @return An empty Bag
071     */
072    @SuppressWarnings("unchecked") // OK, empty bag is compatible with any type
073    public static <E> Bag<E> emptyBag() {
074        return EMPTY_BAG;
075    }
076
077    /**
078     * Gets an empty {@code SortedBag}.
079     *
080     * @param <E> The element type
081     * @return An empty sorted Bag
082     */
083    @SuppressWarnings("unchecked") // OK, empty bag is compatible with any type
084    public static <E> SortedBag<E> emptySortedBag() {
085        return (SortedBag<E>) EMPTY_SORTED_BAG;
086    }
087
088    /**
089     * Returns a predicated (validating) bag backed by the given bag.
090     * <p>
091     * Only objects that pass the test in the given predicate can be added to
092     * the bag. Trying to add an invalid object results in an
093     * IllegalArgumentException. It is important not to use the original bag
094     * after invoking this method, as it is a backdoor for adding invalid
095     * objects.
096     * </p>
097     *
098     * @param <E> The element type
099     * @param bag The bag to predicate, must not be null
100     * @param predicate The predicate for the bag, must not be null
101     * @return A predicated bag backed by the given bag
102     * @throws NullPointerException if the Bag or Predicate is null
103     */
104    public static <E> Bag<E> predicatedBag(final Bag<E> bag, final Predicate<? super E> predicate) {
105        return PredicatedBag.predicatedBag(bag, predicate);
106    }
107
108    /**
109     * Returns a predicated (validating) sorted bag backed by the given sorted
110     * bag.
111     * <p>
112     * Only objects that pass the test in the given predicate can be added to
113     * the bag. Trying to add an invalid object results in an
114     * IllegalArgumentException. It is important not to use the original bag
115     * after invoking this method, as it is a backdoor for adding invalid
116     * objects.
117     * </p>
118     *
119     * @param <E> The element type
120     * @param bag The sorted bag to predicate, must not be null
121     * @param predicate The predicate for the bag, must not be null
122     * @return A predicated bag backed by the given bag
123     * @throws NullPointerException if the SortedBag or Predicate is null
124     */
125    public static <E> SortedBag<E> predicatedSortedBag(final SortedBag<E> bag,
126            final Predicate<? super E> predicate) {
127        return PredicatedSortedBag.predicatedSortedBag(bag, predicate);
128    }
129
130    /**
131     * Returns a synchronized (thread-safe) bag backed by the given bag. In
132     * order to guarantee serial access, it is critical that all access to the
133     * backing bag is accomplished through the returned bag.
134     * <p>
135     * It is imperative that the user manually synchronize on the returned bag
136     * when iterating over it:
137     * </p>
138     *
139     * <pre>
140     * Bag bag = BagUtils.synchronizedBag(new HashBag());
141     * ...
142     * synchronized(bag) {
143     *     Iterator i = bag.iterator(); // Must be in synchronized block
144     *     while (i.hasNext())
145     *         foo(i.next());
146     *     }
147     * }
148     * </pre>
149     *
150     * Failure to follow this advice may result in non-deterministic behavior.
151     *
152     * @param <E> The element type
153     * @param bag The bag to synchronize, must not be null
154     * @return A synchronized bag backed by that bag
155     * @throws NullPointerException if the Bag is null
156     */
157    public static <E> Bag<E> synchronizedBag(final Bag<E> bag) {
158        return SynchronizedBag.synchronizedBag(bag);
159    }
160
161    /**
162     * Returns a synchronized (thread-safe) sorted bag backed by the given
163     * sorted bag. In order to guarantee serial access, it is critical that all
164     * access to the backing bag is accomplished through the returned bag.
165     * <p>
166     * It is imperative that the user manually synchronize on the returned bag
167     * when iterating over it:
168     * </p>
169     *
170     * <pre>
171     * SortedBag bag = BagUtils.synchronizedSortedBag(new TreeBag());
172     * ...
173     * synchronized(bag) {
174     *     Iterator i = bag.iterator(); // Must be in synchronized block
175     *     while (i.hasNext())
176     *         foo(i.next());
177     *     }
178     * }
179     * </pre>
180     *
181     * Failure to follow this advice may result in non-deterministic behavior.
182     *
183     * @param <E> The element type
184     * @param bag The bag to synchronize, must not be null
185     * @return A synchronized bag backed by that bag
186     * @throws NullPointerException if the SortedBag is null
187     */
188    public static <E> SortedBag<E> synchronizedSortedBag(final SortedBag<E> bag) {
189        return SynchronizedSortedBag.synchronizedSortedBag(bag);
190    }
191
192    /**
193     * Returns a transformed bag backed by the given bag.
194     * <p>
195     * Each object is passed through the transformer as it is added to the Bag.
196     * It is important not to use the original bag after invoking this method,
197     * as it is a backdoor for adding untransformed objects.
198     * </p>
199     * <p>
200     * Existing entries in the specified bag will not be transformed.
201     * If you want that behavior, see {@link TransformedBag#transformedBag(Bag, Transformer)}.
202     * </p>
203     *
204     * @param <E> The element type
205     * @param bag The bag to predicate, must not be null
206     * @param transformer The transformer for the bag, must not be null
207     * @return A transformed bag backed by the given bag
208     * @throws NullPointerException if the Bag or Transformer is null
209     */
210    public static <E> Bag<E> transformingBag(final Bag<E> bag, final Transformer<? super E, ? extends E> transformer) {
211        return TransformedBag.transformingBag(bag, transformer);
212    }
213
214    /**
215     * Returns a transformed sorted bag backed by the given bag.
216     * <p>
217     * Each object is passed through the transformer as it is added to the Bag.
218     * It is important not to use the original bag after invoking this method,
219     * as it is a backdoor for adding untransformed objects.
220     * </p>
221     * <p>
222     * Existing entries in the specified bag will not be transformed.
223     * If you want that behavior, see
224     * {@link TransformedSortedBag#transformedSortedBag(SortedBag, Transformer)}.
225     * </p>
226     *
227     * @param <E> The element type
228     * @param bag The bag to predicate, must not be null
229     * @param transformer The transformer for the bag, must not be null
230     * @return A transformed bag backed by the given bag
231     * @throws NullPointerException if the Bag or Transformer is null
232     */
233    public static <E> SortedBag<E> transformingSortedBag(final SortedBag<E> bag,
234                                                         final Transformer<? super E, ? extends E> transformer) {
235        return TransformedSortedBag.transformingSortedBag(bag, transformer);
236    }
237
238    /**
239     * Returns an unmodifiable view of the given bag. Any modification attempts
240     * to the returned bag will raise an {@link UnsupportedOperationException}.
241     *
242     * @param <E> The element type
243     * @param bag The bag whose unmodifiable view is to be returned, must not be null
244     * @return An unmodifiable view of that bag
245     * @throws NullPointerException if the Bag is null
246     */
247    public static <E> Bag<E> unmodifiableBag(final Bag<? extends E> bag) {
248        return UnmodifiableBag.unmodifiableBag(bag);
249    }
250
251    /**
252     * Returns an unmodifiable view of the given sorted bag. Any modification
253     * attempts to the returned bag will raise an
254     * {@link UnsupportedOperationException}.
255     *
256     * @param <E> The element type
257     * @param bag The bag whose unmodifiable view is to be returned, must not be null
258     * @return An unmodifiable view of that bag
259     * @throws NullPointerException if the SortedBag is null
260     */
261    public static <E> SortedBag<E> unmodifiableSortedBag(final SortedBag<E> bag) {
262        return UnmodifiableSortedBag.unmodifiableSortedBag(bag);
263    }
264
265    /**
266     * Don't allow instances.
267     */
268    private BagUtils() {
269        // empty
270    }
271
272}