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