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