    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}