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