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 */ 017 package org.apache.commons.collections; 018 019 import org.apache.commons.collections.bag.HashBag; 020 import org.apache.commons.collections.bag.PredicatedBag; 021 import org.apache.commons.collections.bag.PredicatedSortedBag; 022 import org.apache.commons.collections.bag.SynchronizedBag; 023 import org.apache.commons.collections.bag.SynchronizedSortedBag; 024 import org.apache.commons.collections.bag.TransformedBag; 025 import org.apache.commons.collections.bag.TransformedSortedBag; 026 import org.apache.commons.collections.bag.TreeBag; 027 import org.apache.commons.collections.bag.TypedBag; 028 import org.apache.commons.collections.bag.TypedSortedBag; 029 import org.apache.commons.collections.bag.UnmodifiableBag; 030 import org.apache.commons.collections.bag.UnmodifiableSortedBag; 031 032 /** 033 * Provides utility methods and decorators for 034 * {@link Bag} and {@link SortedBag} instances. 035 * 036 * @since Commons Collections 2.1 037 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $ 038 * 039 * @author Paul Jack 040 * @author Stephen Colebourne 041 * @author Andrew Freeman 042 * @author Matthew Hawthorne 043 */ 044 public class BagUtils { 045 046 /** 047 * An empty unmodifiable bag. 048 */ 049 public static final Bag EMPTY_BAG = UnmodifiableBag.decorate(new HashBag()); 050 051 /** 052 * An empty unmodifiable sorted bag. 053 */ 054 public static final Bag EMPTY_SORTED_BAG = UnmodifiableSortedBag.decorate(new TreeBag()); 055 056 /** 057 * Instantiation of BagUtils is not intended or required. 058 * However, some tools require an instance to operate. 059 */ 060 public BagUtils() { 061 } 062 063 //----------------------------------------------------------------------- 064 /** 065 * Returns a synchronized (thread-safe) bag backed by the given bag. 066 * In order to guarantee serial access, it is critical that all 067 * access to the backing bag is accomplished through the returned bag. 068 * <p> 069 * It is imperative that the user manually synchronize on the returned 070 * bag when iterating over it: 071 * 072 * <pre> 073 * Bag bag = BagUtils.synchronizedBag(new HashBag()); 074 * ... 075 * synchronized(bag) { 076 * Iterator i = bag.iterator(); // Must be in synchronized block 077 * while (i.hasNext()) 078 * foo(i.next()); 079 * } 080 * } 081 * </pre> 082 * 083 * Failure to follow this advice may result in non-deterministic 084 * behavior. 085 * 086 * @param bag the bag to synchronize, must not be null 087 * @return a synchronized bag backed by that bag 088 * @throws IllegalArgumentException if the Bag is null 089 */ 090 public static Bag synchronizedBag(Bag bag) { 091 return SynchronizedBag.decorate(bag); 092 } 093 094 /** 095 * Returns an unmodifiable view of the given bag. Any modification 096 * attempts to the returned bag will raise an 097 * {@link UnsupportedOperationException}. 098 * 099 * @param bag the bag whose unmodifiable view is to be returned, must not be null 100 * @return an unmodifiable view of that bag 101 * @throws IllegalArgumentException if the Bag is null 102 */ 103 public static Bag unmodifiableBag(Bag bag) { 104 return UnmodifiableBag.decorate(bag); 105 } 106 107 /** 108 * Returns a predicated (validating) bag backed by the given bag. 109 * <p> 110 * Only objects that pass the test in the given predicate can be added to the bag. 111 * Trying to add an invalid object results in an IllegalArgumentException. 112 * It is important not to use the original bag after invoking this method, 113 * as it is a backdoor for adding invalid objects. 114 * 115 * @param bag the bag to predicate, must not be null 116 * @param predicate the predicate for the bag, must not be null 117 * @return a predicated bag backed by the given bag 118 * @throws IllegalArgumentException if the Bag or Predicate is null 119 */ 120 public static Bag predicatedBag(Bag bag, Predicate predicate) { 121 return PredicatedBag.decorate(bag, predicate); 122 } 123 124 /** 125 * Returns a typed bag backed by the given bag. 126 * <p> 127 * Only objects of the specified type can be added to the bag. 128 * 129 * @param bag the bag to limit to a specific type, must not be null 130 * @param type the type of objects which may be added to the bag 131 * @return a typed bag backed by the specified bag 132 */ 133 public static Bag typedBag(Bag bag, Class type) { 134 return TypedBag.decorate(bag, type); 135 } 136 137 /** 138 * Returns a transformed bag backed by the given bag. 139 * <p> 140 * Each object is passed through the transformer as it is added to the 141 * Bag. It is important not to use the original bag after invoking this 142 * method, as it is a backdoor for adding untransformed objects. 143 * 144 * @param bag the bag to predicate, must not be null 145 * @param transformer the transformer for the bag, must not be null 146 * @return a transformed bag backed by the given bag 147 * @throws IllegalArgumentException if the Bag or Transformer is null 148 */ 149 public static Bag transformedBag(Bag bag, Transformer transformer) { 150 return TransformedBag.decorate(bag, transformer); 151 } 152 153 //----------------------------------------------------------------------- 154 /** 155 * Returns a synchronized (thread-safe) sorted bag backed by the given 156 * sorted bag. 157 * In order to guarantee serial access, it is critical that all 158 * access to the backing bag is accomplished through the returned bag. 159 * <p> 160 * It is imperative that the user manually synchronize on the returned 161 * bag when iterating over it: 162 * 163 * <pre> 164 * SortedBag bag = BagUtils.synchronizedSortedBag(new TreeBag()); 165 * ... 166 * synchronized(bag) { 167 * Iterator i = bag.iterator(); // Must be in synchronized block 168 * while (i.hasNext()) 169 * foo(i.next()); 170 * } 171 * } 172 * </pre> 173 * 174 * Failure to follow this advice may result in non-deterministic 175 * behavior. 176 * 177 * @param bag the bag to synchronize, must not be null 178 * @return a synchronized bag backed by that bag 179 * @throws IllegalArgumentException if the SortedBag is null 180 */ 181 public static SortedBag synchronizedSortedBag(SortedBag bag) { 182 return SynchronizedSortedBag.decorate(bag); 183 } 184 185 /** 186 * Returns an unmodifiable view of the given sorted bag. Any modification 187 * attempts to the returned bag will raise an 188 * {@link UnsupportedOperationException}. 189 * 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 SortedBag unmodifiableSortedBag(SortedBag bag) { 195 return UnmodifiableSortedBag.decorate(bag); 196 } 197 198 /** 199 * Returns a predicated (validating) sorted bag backed by the given sorted bag. 200 * <p> 201 * Only objects that pass the test in the given predicate can be added to the bag. 202 * Trying to add an invalid object results in an IllegalArgumentException. 203 * It is important not to use the original bag after invoking this method, 204 * as it is a backdoor for adding invalid objects. 205 * 206 * @param bag the sorted bag to predicate, must not be null 207 * @param predicate the predicate for the bag, must not be null 208 * @return a predicated bag backed by the given bag 209 * @throws IllegalArgumentException if the SortedBag or Predicate is null 210 */ 211 public static SortedBag predicatedSortedBag(SortedBag bag, Predicate predicate) { 212 return PredicatedSortedBag.decorate(bag, predicate); 213 } 214 215 /** 216 * Returns a typed sorted bag backed by the given bag. 217 * <p> 218 * Only objects of the specified type can be added to the bag. 219 * 220 * @param bag the bag to limit to a specific type, must not be null 221 * @param type the type of objects which may be added to the bag 222 * @return a typed bag backed by the specified bag 223 */ 224 public static SortedBag typedSortedBag(SortedBag bag, Class type) { 225 return TypedSortedBag.decorate(bag, type); 226 } 227 228 /** 229 * Returns a transformed sorted bag backed by the given bag. 230 * <p> 231 * Each object is passed through the transformer as it is added to the 232 * Bag. It is important not to use the original bag after invoking this 233 * method, as it is a backdoor for adding untransformed objects. 234 * 235 * @param bag the bag to predicate, must not be null 236 * @param transformer the transformer for the bag, must not be null 237 * @return a transformed bag backed by the given bag 238 * @throws IllegalArgumentException if the Bag or Transformer is null 239 */ 240 public static SortedBag transformedSortedBag(SortedBag bag, Transformer transformer) { 241 return TransformedSortedBag.decorate(bag, transformer); 242 } 243 244 }