BagUtils.java

  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.collections4;

  18. import org.apache.commons.collections4.bag.CollectionBag;
  19. import org.apache.commons.collections4.bag.HashBag;
  20. import org.apache.commons.collections4.bag.PredicatedBag;
  21. import org.apache.commons.collections4.bag.PredicatedSortedBag;
  22. import org.apache.commons.collections4.bag.SynchronizedBag;
  23. import org.apache.commons.collections4.bag.SynchronizedSortedBag;
  24. import org.apache.commons.collections4.bag.TransformedBag;
  25. import org.apache.commons.collections4.bag.TransformedSortedBag;
  26. import org.apache.commons.collections4.bag.TreeBag;
  27. import org.apache.commons.collections4.bag.UnmodifiableBag;
  28. import org.apache.commons.collections4.bag.UnmodifiableSortedBag;

  29. /**
  30.  * Provides utility methods and decorators for {@link Bag} and {@link SortedBag} instances.
  31.  *
  32.  * @since 2.1
  33.  */
  34. public class BagUtils {

  35.     /**
  36.      * An empty unmodifiable bag.
  37.      */
  38.     @SuppressWarnings("rawtypes") // OK, empty bag is compatible with any type
  39.     public static final Bag EMPTY_BAG = UnmodifiableBag.unmodifiableBag(new HashBag<>());

  40.     /**
  41.      * An empty unmodifiable sorted bag.
  42.      */
  43.     @SuppressWarnings("rawtypes") // OK, empty bag is compatible with any type
  44.     public static final Bag EMPTY_SORTED_BAG =
  45.             UnmodifiableSortedBag.unmodifiableSortedBag(new TreeBag<>());

  46.     /**
  47.      * Returns a bag that complies to the Collection contract, backed by the given bag.
  48.      *
  49.      * @param <E> the element type
  50.      * @param bag the bag to decorate, must not be null
  51.      * @return a Bag that complies to the Collection contract
  52.      * @throws NullPointerException if bag is null
  53.      * @since 4.0
  54.      */
  55.     public static <E> Bag<E> collectionBag(final Bag<E> bag) {
  56.         return CollectionBag.collectionBag(bag);
  57.     }

  58.     /**
  59.      * Gets an empty {@code Bag}.
  60.      *
  61.      * @param <E> the element type
  62.      * @return an empty Bag
  63.      */
  64.     @SuppressWarnings("unchecked") // OK, empty bag is compatible with any type
  65.     public static <E> Bag<E> emptyBag() {
  66.         return EMPTY_BAG;
  67.     }

  68.     /**
  69.      * Gets an empty {@code SortedBag}.
  70.      *
  71.      * @param <E> the element type
  72.      * @return an empty sorted Bag
  73.      */
  74.     @SuppressWarnings("unchecked") // OK, empty bag is compatible with any type
  75.     public static <E> SortedBag<E> emptySortedBag() {
  76.         return (SortedBag<E>) EMPTY_SORTED_BAG;
  77.     }

  78.     /**
  79.      * Returns a predicated (validating) bag backed by the given bag.
  80.      * <p>
  81.      * Only objects that pass the test in the given predicate can be added to
  82.      * the bag. Trying to add an invalid object results in an
  83.      * IllegalArgumentException. It is important not to use the original bag
  84.      * after invoking this method, as it is a backdoor for adding invalid
  85.      * objects.
  86.      * </p>
  87.      *
  88.      * @param <E> the element type
  89.      * @param bag the bag to predicate, must not be null
  90.      * @param predicate the predicate for the bag, must not be null
  91.      * @return a predicated bag backed by the given bag
  92.      * @throws NullPointerException if the Bag or Predicate is null
  93.      */
  94.     public static <E> Bag<E> predicatedBag(final Bag<E> bag, final Predicate<? super E> predicate) {
  95.         return PredicatedBag.predicatedBag(bag, predicate);
  96.     }

  97.     /**
  98.      * Returns a predicated (validating) sorted bag backed by the given sorted
  99.      * bag.
  100.      * <p>
  101.      * Only objects that pass the test in the given predicate can be added to
  102.      * the bag. Trying to add an invalid object results in an
  103.      * IllegalArgumentException. It is important not to use the original bag
  104.      * after invoking this method, as it is a backdoor for adding invalid
  105.      * objects.
  106.      * </p>
  107.      *
  108.      * @param <E> the element type
  109.      * @param bag the sorted bag to predicate, must not be null
  110.      * @param predicate the predicate for the bag, must not be null
  111.      * @return a predicated bag backed by the given bag
  112.      * @throws NullPointerException if the SortedBag or Predicate is null
  113.      */
  114.     public static <E> SortedBag<E> predicatedSortedBag(final SortedBag<E> bag,
  115.             final Predicate<? super E> predicate) {
  116.         return PredicatedSortedBag.predicatedSortedBag(bag, predicate);
  117.     }

  118.     /**
  119.      * Returns a synchronized (thread-safe) bag backed by the given bag. In
  120.      * order to guarantee serial access, it is critical that all access to the
  121.      * backing bag is accomplished through the returned bag.
  122.      * <p>
  123.      * It is imperative that the user manually synchronize on the returned bag
  124.      * when iterating over it:
  125.      * </p>
  126.      *
  127.      * <pre>
  128.      * Bag bag = BagUtils.synchronizedBag(new HashBag());
  129.      * ...
  130.      * synchronized(bag) {
  131.      *     Iterator i = bag.iterator(); // Must be in synchronized block
  132.      *     while (i.hasNext())
  133.      *         foo(i.next());
  134.      *     }
  135.      * }
  136.      * </pre>
  137.      *
  138.      * Failure to follow this advice may result in non-deterministic behavior.
  139.      *
  140.      * @param <E> the element type
  141.      * @param bag the bag to synchronize, must not be null
  142.      * @return a synchronized bag backed by that bag
  143.      * @throws NullPointerException if the Bag is null
  144.      */
  145.     public static <E> Bag<E> synchronizedBag(final Bag<E> bag) {
  146.         return SynchronizedBag.synchronizedBag(bag);
  147.     }

  148.     /**
  149.      * Returns a synchronized (thread-safe) sorted bag backed by the given
  150.      * sorted bag. In order to guarantee serial access, it is critical that all
  151.      * access to the backing bag is accomplished through the returned bag.
  152.      * <p>
  153.      * It is imperative that the user manually synchronize on the returned bag
  154.      * when iterating over it:
  155.      * </p>
  156.      *
  157.      * <pre>
  158.      * SortedBag bag = BagUtils.synchronizedSortedBag(new TreeBag());
  159.      * ...
  160.      * synchronized(bag) {
  161.      *     Iterator i = bag.iterator(); // Must be in synchronized block
  162.      *     while (i.hasNext())
  163.      *         foo(i.next());
  164.      *     }
  165.      * }
  166.      * </pre>
  167.      *
  168.      * Failure to follow this advice may result in non-deterministic behavior.
  169.      *
  170.      * @param <E> the element type
  171.      * @param bag the bag to synchronize, must not be null
  172.      * @return a synchronized bag backed by that bag
  173.      * @throws NullPointerException if the SortedBag is null
  174.      */
  175.     public static <E> SortedBag<E> synchronizedSortedBag(final SortedBag<E> bag) {
  176.         return SynchronizedSortedBag.synchronizedSortedBag(bag);
  177.     }

  178.     /**
  179.      * Returns a transformed bag backed by the given bag.
  180.      * <p>
  181.      * Each object is passed through the transformer as it is added to the Bag.
  182.      * It is important not to use the original bag after invoking this method,
  183.      * as it is a backdoor for adding untransformed objects.
  184.      * </p>
  185.      * <p>
  186.      * Existing entries in the specified bag will not be transformed.
  187.      * If you want that behavior, see {@link TransformedBag#transformedBag(Bag, Transformer)}.
  188.      * </p>
  189.      *
  190.      * @param <E> the element type
  191.      * @param bag the bag to predicate, must not be null
  192.      * @param transformer the transformer for the bag, must not be null
  193.      * @return a transformed bag backed by the given bag
  194.      * @throws NullPointerException if the Bag or Transformer is null
  195.      */
  196.     public static <E> Bag<E> transformingBag(final Bag<E> bag, final Transformer<? super E, ? extends E> transformer) {
  197.         return TransformedBag.transformingBag(bag, transformer);
  198.     }

  199.     /**
  200.      * Returns a transformed sorted bag backed by the given bag.
  201.      * <p>
  202.      * Each object is passed through the transformer as it is added to the Bag.
  203.      * It is important not to use the original bag after invoking this method,
  204.      * as it is a backdoor for adding untransformed objects.
  205.      * </p>
  206.      * <p>
  207.      * Existing entries in the specified bag will not be transformed.
  208.      * If you want that behavior, see
  209.      * {@link TransformedSortedBag#transformedSortedBag(SortedBag, Transformer)}.
  210.      * </p>
  211.      *
  212.      * @param <E> the element type
  213.      * @param bag the bag to predicate, must not be null
  214.      * @param transformer the transformer for the bag, must not be null
  215.      * @return a transformed bag backed by the given bag
  216.      * @throws NullPointerException if the Bag or Transformer is null
  217.      */
  218.     public static <E> SortedBag<E> transformingSortedBag(final SortedBag<E> bag,
  219.                                                          final Transformer<? super E, ? extends E> transformer) {
  220.         return TransformedSortedBag.transformingSortedBag(bag, transformer);
  221.     }

  222.     /**
  223.      * Returns an unmodifiable view of the given bag. Any modification attempts
  224.      * to the returned bag will raise an {@link UnsupportedOperationException}.
  225.      *
  226.      * @param <E> the element type
  227.      * @param bag the bag whose unmodifiable view is to be returned, must not be null
  228.      * @return an unmodifiable view of that bag
  229.      * @throws NullPointerException if the Bag is null
  230.      */
  231.     public static <E> Bag<E> unmodifiableBag(final Bag<? extends E> bag) {
  232.         return UnmodifiableBag.unmodifiableBag(bag);
  233.     }

  234.     /**
  235.      * Returns an unmodifiable view of the given sorted bag. Any modification
  236.      * attempts to the returned bag will raise an
  237.      * {@link UnsupportedOperationException}.
  238.      *
  239.      * @param <E> the element type
  240.      * @param bag the bag whose unmodifiable view is to be returned, must not be null
  241.      * @return an unmodifiable view of that bag
  242.      * @throws NullPointerException if the SortedBag is null
  243.      */
  244.     public static <E> SortedBag<E> unmodifiableSortedBag(final SortedBag<E> bag) {
  245.         return UnmodifiableSortedBag.unmodifiableSortedBag(bag);
  246.     }

  247.     /**
  248.      * Don't allow instances.
  249.      */
  250.     private BagUtils() {
  251.         // empty
  252.     }

  253. }