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