COLLECTIONS-229 - Remove deprecated classes and code

git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/collections/branches/collections_jdk5_branch@468687 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stephen Colebourne 2006-10-28 12:53:28 +00:00
parent c5a502a084
commit efd41aff47
47 changed files with 56 additions and 16836 deletions

View File

@ -1,70 +0,0 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<title>RELEASE NOTES: COLLECTIONS GENERICS X.X</title>
</head>
<body>
<center><h2>RELEASE NOTES: COLLECTIONS GENERICS X.X</h2></center>
<p>
Commons collections is a project to develop and maintain collection classes
based on and inspired by the JDK collection framework.
This project is JDK1.2 compatible, and does not use JDK1.5 generics.
</p>
<p>
This release adds various new classes and fixes a number of bugs.
All feedback should be directed to commons-user at jakarta.apache.org.
</p>
<hr />
<center><h3>COMPATIBILITY</h3></center>
<p>
This release is fully source and binary compatible with v3.2.
(Checks performed using JDiff and Clirr, thanks).
Please check the bug fixes to ensure you weren't relying on the behaviour of a bug.
</p>
<p>
There are xxxxxxxxxxxxxxxxxxx new <i>deprecations</i>:<br />
If this causes major headaches to anyone please contact commons-dev at jakarta.apache.org.
</p>
<center><h3>NEW CLASSES</h3></center>
<ul>
<li>xxxxxxxxxxxxxx</li>
</ul>
<center><h3>ENHANCEMENTS</h3></center>
<ul>
<li>xxxxxxxxxxxxxx</li>
</ul>
<center><h3>BUG FIXES</h3></center>
<ul>
<li>Flat3Map - Fix setValue in MapIterator and EntrySetIterator to work correctly [COLLECTIONS-217]</li>
<li>ExtendedProperties - Include property name had confused static/instance semantics [COLLECTIONS-214]</li>
<li>CollectionUtils - Fix removeAll() method which was completely broken [COLLECTIONS-219]</li>
</ul>
<center><h3>JAVADOC</h3></center>
<ul>
<li>IteratorChain - Clarify constructor behaviour</li>
<li>MuliKey - Spelling [COLLECTIONS-216]</li>
<li>DefaultedMap - Clarify transformer behaviour [COLLECTIONS-215]</li>
</ul>
</body>
</html>

43
RELEASE-NOTES.txt Normal file
View File

@ -0,0 +1,43 @@
Commons Collections Generics Package
Version X.X
Release Notes
INTRODUCTION:
Commons collections is a project to develop and maintain collection classes
based on and inspired by the JDK collection framework.
This version uses the generics features of JDK1.5 and is not compatible with
earlier JDK versions.
The process of generifying an API is complex.
For commons-collections, we have chosen to break the API in various ways.
The aim behind this is to provide an API design that better suits generics.
We have also removed all deprecated classes and fixed oddities in the previous
API that we couldn't fix due to backwards compatability restrictions.
As such, this release should not be considered to be a simple, drop-in, replacement
for commons-collections. You will probably receive compile errors, and you will
certainly have generification warnings to solve. These release notes will try
to guide you in the process of upgrading, however you should remember that this
is a new API based on the original, so some concepts have changed.
Changes from commons-collections
--------------------------------
- Removed all deprecated classes and methods
Feedback
--------
Open source works best when you give feedback:
http://jakarta.apache.org/commons/collections/
Please direct all bug reports to JIRA
http://issues.apache.org/jira/browse/COLLECTIONS
Or subscribe to the commons-user mailing list (prefix emails by [collections])
http://jakarta.apache.org/site/mail.html
The Commons-Collections-Generics Team

View File

@ -1,804 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import org.apache.commons.collections.list.UnmodifiableList;
import org.apache.commons.collections.keyvalue.AbstractMapEntry;
import org.apache.commons.collections.set.UnmodifiableSet;
/**
* An implementation of Map for JavaBeans which uses introspection to
* get and put properties in the bean.
* <p>
* If an exception occurs during attempts to get or set a property then the
* property is considered non existent in the Map
*
* @since Commons Collections 1.0
* @version $Revision$ $Date$
*
* @author James Strachan
* @author Stephen Colebourne
* @author Dimiter Dimitrov
*
* @deprecated Identical class now available in commons-beanutils (full jar version).
* This version is due to be removed in collections v4.0.
*/
public class BeanMap extends AbstractMap implements Cloneable {
private transient Object bean;
private transient HashMap readMethods = new HashMap();
private transient HashMap writeMethods = new HashMap();
private transient HashMap types = new HashMap();
/**
* An empty array. Used to invoke accessors via reflection.
*/
public static final Object[] NULL_ARGUMENTS = {};
/**
* Maps primitive Class types to transformers. The transformer
* transform strings into the appropriate primitive wrapper.
*/
public static HashMap defaultTransformers = new HashMap();
static {
defaultTransformers.put(
Boolean.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Boolean.valueOf( input.toString() );
}
}
);
defaultTransformers.put(
Character.TYPE,
new Transformer() {
public Object transform( Object input ) {
return new Character( input.toString().charAt( 0 ) );
}
}
);
defaultTransformers.put(
Byte.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Byte.valueOf( input.toString() );
}
}
);
defaultTransformers.put(
Short.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Short.valueOf( input.toString() );
}
}
);
defaultTransformers.put(
Integer.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Integer.valueOf( input.toString() );
}
}
);
defaultTransformers.put(
Long.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Long.valueOf( input.toString() );
}
}
);
defaultTransformers.put(
Float.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Float.valueOf( input.toString() );
}
}
);
defaultTransformers.put(
Double.TYPE,
new Transformer() {
public Object transform( Object input ) {
return Double.valueOf( input.toString() );
}
}
);
}
// Constructors
//-------------------------------------------------------------------------
/**
* Constructs a new empty <code>BeanMap</code>.
*/
public BeanMap() {
}
/**
* Constructs a new <code>BeanMap</code> that operates on the
* specified bean. If the given bean is <code>null</code>, then
* this map will be empty.
*
* @param bean the bean for this map to operate on
*/
public BeanMap(Object bean) {
this.bean = bean;
initialise();
}
// Map interface
//-------------------------------------------------------------------------
public String toString() {
return "BeanMap<" + String.valueOf(bean) + ">";
}
/**
* Clone this bean map using the following process:
*
* <ul>
* <li>If there is no underlying bean, return a cloned BeanMap without a
* bean.
*
* <li>Since there is an underlying bean, try to instantiate a new bean of
* the same type using Class.newInstance().
*
* <li>If the instantiation fails, throw a CloneNotSupportedException
*
* <li>Clone the bean map and set the newly instantiated bean as the
* underlying bean for the bean map.
*
* <li>Copy each property that is both readable and writable from the
* existing object to a cloned bean map.
*
* <li>If anything fails along the way, throw a
* CloneNotSupportedException.
*
* <ul>
*/
public Object clone() throws CloneNotSupportedException {
BeanMap newMap = (BeanMap)super.clone();
if(bean == null) {
// no bean, just an empty bean map at the moment. return a newly
// cloned and empty bean map.
return newMap;
}
Object newBean = null;
Class beanClass = null;
try {
beanClass = bean.getClass();
newBean = beanClass.newInstance();
} catch (Exception e) {
// unable to instantiate
throw new CloneNotSupportedException
("Unable to instantiate the underlying bean \"" +
beanClass.getName() + "\": " + e);
}
try {
newMap.setBean(newBean);
} catch (Exception exception) {
throw new CloneNotSupportedException
("Unable to set bean in the cloned bean map: " +
exception);
}
try {
// copy only properties that are readable and writable. If its
// not readable, we can't get the value from the old map. If
// its not writable, we can't write a value into the new map.
Iterator readableKeys = readMethods.keySet().iterator();
while(readableKeys.hasNext()) {
Object key = readableKeys.next();
if(getWriteMethod(key) != null) {
newMap.put(key, get(key));
}
}
} catch (Exception exception) {
throw new CloneNotSupportedException
("Unable to copy bean values to cloned bean map: " +
exception);
}
return newMap;
}
/**
* Puts all of the writable properties from the given BeanMap into this
* BeanMap. Read-only and Write-only properties will be ignored.
*
* @param map the BeanMap whose properties to put
*/
public void putAllWriteable(BeanMap map) {
Iterator readableKeys = map.readMethods.keySet().iterator();
while (readableKeys.hasNext()) {
Object key = readableKeys.next();
if (getWriteMethod(key) != null) {
this.put(key, map.get(key));
}
}
}
/**
* This method reinitializes the bean map to have default values for the
* bean's properties. This is accomplished by constructing a new instance
* of the bean which the map uses as its underlying data source. This
* behavior for <code>clear()</code> differs from the Map contract in that
* the mappings are not actually removed from the map (the mappings for a
* BeanMap are fixed).
*/
public void clear() {
if(bean == null) return;
Class beanClass = null;
try {
beanClass = bean.getClass();
bean = beanClass.newInstance();
}
catch (Exception e) {
throw new UnsupportedOperationException( "Could not create new instance of class: " + beanClass );
}
}
/**
* Returns true if the bean defines a property with the given name.
* <p>
* The given name must be a <code>String</code>; if not, this method
* returns false. This method will also return false if the bean
* does not define a property with that name.
* <p>
* Write-only properties will not be matched as the test operates against
* property read methods.
*
* @param name the name of the property to check
* @return false if the given name is null or is not a <code>String</code>;
* false if the bean does not define a property with that name; or
* true if the bean does define a property with that name
*/
public boolean containsKey(Object name) {
Method method = getReadMethod(name);
return method != null;
}
/**
* Returns true if the bean defines a property whose current value is
* the given object.
*
* @param value the value to check
* @return false true if the bean has at least one property whose
* current value is that object, false otherwise
*/
public boolean containsValue(Object value) {
// use default implementation
return super.containsValue(value);
}
/**
* Returns the value of the bean's property with the given name.
* <p>
* The given name must be a {@link String} and must not be
* null; otherwise, this method returns <code>null</code>.
* If the bean defines a property with the given name, the value of
* that property is returned. Otherwise, <code>null</code> is
* returned.
* <p>
* Write-only properties will not be matched as the test operates against
* property read methods.
*
* @param name the name of the property whose value to return
* @return the value of the property with that name
*/
public Object get(Object name) {
if ( bean != null ) {
Method method = getReadMethod( name );
if ( method != null ) {
try {
return method.invoke( bean, NULL_ARGUMENTS );
}
catch ( IllegalAccessException e ) {
logWarn( e );
}
catch ( IllegalArgumentException e ) {
logWarn( e );
}
catch ( InvocationTargetException e ) {
logWarn( e );
}
catch ( NullPointerException e ) {
logWarn( e );
}
}
}
return null;
}
/**
* Sets the bean property with the given name to the given value.
*
* @param name the name of the property to set
* @param value the value to set that property to
* @return the previous value of that property
* @throws IllegalArgumentException if the given name is null;
* if the given name is not a {@link String}; if the bean doesn't
* define a property with that name; or if the bean property with
* that name is read-only
*/
public Object put(Object name, Object value) throws IllegalArgumentException, ClassCastException {
if ( bean != null ) {
Object oldValue = get( name );
Method method = getWriteMethod( name );
if ( method == null ) {
throw new IllegalArgumentException( "The bean of type: "+ bean.getClass().getName() + " has no property called: " + name );
}
try {
Object[] arguments = createWriteMethodArguments( method, value );
method.invoke( bean, arguments );
Object newValue = get( name );
firePropertyChange( name, oldValue, newValue );
}
catch ( InvocationTargetException e ) {
logInfo( e );
throw new IllegalArgumentException( e.getMessage() );
}
catch ( IllegalAccessException e ) {
logInfo( e );
throw new IllegalArgumentException( e.getMessage() );
}
return oldValue;
}
return null;
}
/**
* Returns the number of properties defined by the bean.
*
* @return the number of properties defined by the bean
*/
public int size() {
return readMethods.size();
}
/**
* Get the keys for this BeanMap.
* <p>
* Write-only properties are <b>not</b> included in the returned set of
* property names, although it is possible to set their value and to get
* their type.
*
* @return BeanMap keys. The Set returned by this method is not
* modifiable.
*/
public Set keySet() {
return UnmodifiableSet.decorate(readMethods.keySet());
}
/**
* Gets a Set of MapEntry objects that are the mappings for this BeanMap.
* <p>
* Each MapEntry can be set but not removed.
*
* @return the unmodifiable set of mappings
*/
public Set entrySet() {
return UnmodifiableSet.decorate(new AbstractSet() {
public Iterator iterator() {
return entryIterator();
}
public int size() {
return BeanMap.this.readMethods.size();
}
});
}
/**
* Returns the values for the BeanMap.
*
* @return values for the BeanMap. The returned collection is not
* modifiable.
*/
public Collection values() {
ArrayList answer = new ArrayList( readMethods.size() );
for ( Iterator iter = valueIterator(); iter.hasNext(); ) {
answer.add( iter.next() );
}
return UnmodifiableList.decorate(answer);
}
// Helper methods
//-------------------------------------------------------------------------
/**
* Returns the type of the property with the given name.
*
* @param name the name of the property
* @return the type of the property, or <code>null</code> if no such
* property exists
*/
public Class getType(String name) {
return (Class) types.get( name );
}
/**
* Convenience method for getting an iterator over the keys.
* <p>
* Write-only properties will not be returned in the iterator.
*
* @return an iterator over the keys
*/
public Iterator keyIterator() {
return readMethods.keySet().iterator();
}
/**
* Convenience method for getting an iterator over the values.
*
* @return an iterator over the values
*/
public Iterator valueIterator() {
final Iterator iter = keyIterator();
return new Iterator() {
public boolean hasNext() {
return iter.hasNext();
}
public Object next() {
Object key = iter.next();
return get(key);
}
public void remove() {
throw new UnsupportedOperationException( "remove() not supported for BeanMap" );
}
};
}
/**
* Convenience method for getting an iterator over the entries.
*
* @return an iterator over the entries
*/
public Iterator entryIterator() {
final Iterator iter = keyIterator();
return new Iterator() {
public boolean hasNext() {
return iter.hasNext();
}
public Object next() {
Object key = iter.next();
Object value = get(key);
return new MyMapEntry( BeanMap.this, key, value );
}
public void remove() {
throw new UnsupportedOperationException( "remove() not supported for BeanMap" );
}
};
}
// Properties
//-------------------------------------------------------------------------
/**
* Returns the bean currently being operated on. The return value may
* be null if this map is empty.
*
* @return the bean being operated on by this map
*/
public Object getBean() {
return bean;
}
/**
* Sets the bean to be operated on by this map. The given value may
* be null, in which case this map will be empty.
*
* @param newBean the new bean to operate on
*/
public void setBean( Object newBean ) {
bean = newBean;
reinitialise();
}
/**
* Returns the accessor for the property with the given name.
*
* @param name the name of the property
* @return the accessor method for the property, or null
*/
public Method getReadMethod(String name) {
return (Method) readMethods.get(name);
}
/**
* Returns the mutator for the property with the given name.
*
* @param name the name of the property
* @return the mutator method for the property, or null
*/
public Method getWriteMethod(String name) {
return (Method) writeMethods.get(name);
}
// Implementation methods
//-------------------------------------------------------------------------
/**
* Returns the accessor for the property with the given name.
*
* @param name the name of the property
* @return null if the name is null; null if the name is not a
* {@link String}; null if no such property exists; or the accessor
* method for that property
*/
protected Method getReadMethod( Object name ) {
return (Method) readMethods.get( name );
}
/**
* Returns the mutator for the property with the given name.
*
* @param name the name of the
* @return null if the name is null; null if the name is not a
* {@link String}; null if no such property exists; null if the
* property is read-only; or the mutator method for that property
*/
protected Method getWriteMethod( Object name ) {
return (Method) writeMethods.get( name );
}
/**
* Reinitializes this bean. Called during {@link #setBean(Object)}.
* Does introspection to find properties.
*/
protected void reinitialise() {
readMethods.clear();
writeMethods.clear();
types.clear();
initialise();
}
private void initialise() {
if(getBean() == null) return;
Class beanClass = getBean().getClass();
try {
//BeanInfo beanInfo = Introspector.getBeanInfo( bean, null );
BeanInfo beanInfo = Introspector.getBeanInfo( beanClass );
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
if ( propertyDescriptors != null ) {
for ( int i = 0; i < propertyDescriptors.length; i++ ) {
PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
if ( propertyDescriptor != null ) {
String name = propertyDescriptor.getName();
Method readMethod = propertyDescriptor.getReadMethod();
Method writeMethod = propertyDescriptor.getWriteMethod();
Class aType = propertyDescriptor.getPropertyType();
if ( readMethod != null ) {
readMethods.put( name, readMethod );
}
if ( writeMethod != null ) {
writeMethods.put( name, writeMethod );
}
types.put( name, aType );
}
}
}
}
catch ( IntrospectionException e ) {
logWarn( e );
}
}
/**
* Called during a successful {@link #put(Object,Object)} operation.
* Default implementation does nothing. Override to be notified of
* property changes in the bean caused by this map.
*
* @param key the name of the property that changed
* @param oldValue the old value for that property
* @param newValue the new value for that property
*/
protected void firePropertyChange( Object key, Object oldValue, Object newValue ) {
}
// Implementation classes
//-------------------------------------------------------------------------
/**
* Map entry used by {@link BeanMap}.
*/
protected static class MyMapEntry extends AbstractMapEntry {
private BeanMap owner;
/**
* Constructs a new <code>MyMapEntry</code>.
*
* @param owner the BeanMap this entry belongs to
* @param key the key for this entry
* @param value the value for this entry
*/
protected MyMapEntry( BeanMap owner, Object key, Object value ) {
super( key, value );
this.owner = owner;
}
/**
* Sets the value.
*
* @param value the new value for the entry
* @return the old value for the entry
*/
public Object setValue(Object value) {
Object key = getKey();
Object oldValue = owner.get( key );
owner.put( key, value );
Object newValue = owner.get( key );
super.setValue( newValue );
return oldValue;
}
}
/**
* Creates an array of parameters to pass to the given mutator method.
* If the given object is not the right type to pass to the method
* directly, it will be converted using {@link #convertType(Class,Object)}.
*
* @param method the mutator method
* @param value the value to pass to the mutator method
* @return an array containing one object that is either the given value
* or a transformed value
* @throws IllegalAccessException if {@link #convertType(Class,Object)}
* raises it
* @throws IllegalArgumentException if any other exception is raised
* by {@link #convertType(Class,Object)}
*/
protected Object[] createWriteMethodArguments( Method method, Object value ) throws IllegalAccessException, ClassCastException {
try {
if ( value != null ) {
Class[] types = method.getParameterTypes();
if ( types != null && types.length > 0 ) {
Class paramType = types[0];
if ( ! paramType.isAssignableFrom( value.getClass() ) ) {
value = convertType( paramType, value );
}
}
}
Object[] answer = { value };
return answer;
}
catch ( InvocationTargetException e ) {
logInfo( e );
throw new IllegalArgumentException( e.getMessage() );
}
catch ( InstantiationException e ) {
logInfo( e );
throw new IllegalArgumentException( e.getMessage() );
}
}
/**
* Converts the given value to the given type. First, reflection is
* is used to find a public constructor declared by the given class
* that takes one argument, which must be the precise type of the
* given value. If such a constructor is found, a new object is
* created by passing the given value to that constructor, and the
* newly constructed object is returned.<P>
*
* If no such constructor exists, and the given type is a primitive
* type, then the given value is converted to a string using its
* {@link Object#toString() toString()} method, and that string is
* parsed into the correct primitive type using, for instance,
* {@link Integer#valueOf(String)} to convert the string into an
* <code>int</code>.<P>
*
* If no special constructor exists and the given type is not a
* primitive type, this method returns the original value.
*
* @param newType the type to convert the value to
* @param value the value to convert
* @return the converted value
* @throws NumberFormatException if newType is a primitive type, and
* the string representation of the given value cannot be converted
* to that type
* @throws InstantiationException if the constructor found with
* reflection raises it
* @throws InvocationTargetException if the constructor found with
* reflection raises it
* @throws IllegalAccessException never
* @throws IllegalArgumentException never
*/
protected Object convertType( Class newType, Object value )
throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// try call constructor
Class[] types = { value.getClass() };
try {
Constructor constructor = newType.getConstructor( types );
Object[] arguments = { value };
return constructor.newInstance( arguments );
}
catch ( NoSuchMethodException e ) {
// try using the transformers
Transformer transformer = getTypeTransformer( newType );
if ( transformer != null ) {
return transformer.transform( value );
}
return value;
}
}
/**
* Returns a transformer for the given primitive type.
*
* @param aType the primitive type whose transformer to return
* @return a transformer that will convert strings into that type,
* or null if the given type is not a primitive type
*/
protected Transformer getTypeTransformer( Class aType ) {
return (Transformer) defaultTransformers.get( aType );
}
/**
* Logs the given exception to <code>System.out</code>. Used to display
* warnings while accessing/mutating the bean.
*
* @param ex the exception to log
*/
protected void logInfo(Exception ex) {
// Deliberately do not use LOG4J or Commons Logging to avoid dependencies
System.out.println( "INFO: Exception: " + ex );
}
/**
* Logs the given exception to <code>System.err</code>. Used to display
* errors while accessing/mutating the bean.
*
* @param ex the exception to log
*/
protected void logWarn(Exception ex) {
// Deliberately do not use LOG4J or Commons Logging to avoid dependencies
System.out.println( "WARN: Exception: " + ex );
ex.printStackTrace();
}
}

View File

@ -1,565 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.AbstractCollection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Binary heap implementation of <code>PriorityQueue</code>.
* <p>
* The <code>PriorityQueue</code> interface has now been replaced for most uses
* by the <code>Buffer</code> interface. This class and the interface are
* retained for backwards compatibility. The intended replacement is
* {@link org.apache.commons.collections.buffer.PriorityBuffer PriorityBuffer}.
* <p>
* The removal order of a binary heap is based on either the natural sort
* order of its elements or a specified {@link Comparator}. The
* {@link #pop()} method always returns the first element as determined
* by the sort order. (The <code>isMinHeap</code> flag in the constructors
* can be used to reverse the sort order, in which case {@link #pop()}
* will always remove the last element.) The removal order is
* <i>not</i> the same as the order of iteration; elements are
* returned by the iterator in no particular order.
* <p>
* The {@link #insert(Object)} and {@link #pop()} operations perform
* in logarithmic time. The {@link #peek()} operation performs in constant
* time. All other operations perform in linear time or worse.
* <p>
* Note that this implementation is not synchronized. Use SynchronizedPriorityQueue
* to provide synchronized access to a <code>BinaryHeap</code>:
*
* <pre>
* PriorityQueue heap = new SynchronizedPriorityQueue(new BinaryHeap());
* </pre>
*
* @deprecated Replaced by PriorityBuffer in buffer subpackage.
* Due to be removed in v4.0.
* @since Commons Collections 1.0
* @version $Revision$ $Date$
*
* @author Peter Donald
* @author Ram Chidambaram
* @author Michael A. Smith
* @author Paul Jack
* @author Stephen Colebourne
*/
public final class BinaryHeap extends AbstractCollection
implements PriorityQueue, Buffer {
/**
* The default capacity for a binary heap.
*/
private final static int DEFAULT_CAPACITY = 13;
/**
* The number of elements currently in this heap.
*/
int m_size; // package scoped for testing
/**
* The elements in this heap.
*/
Object[] m_elements; // package scoped for testing
/**
* If true, the first element as determined by the sort order will
* be returned. If false, the last element as determined by the
* sort order will be returned.
*/
boolean m_isMinHeap; // package scoped for testing
/**
* The comparator used to order the elements
*/
Comparator m_comparator; // package scoped for testing
/**
* Constructs a new minimum binary heap.
*/
public BinaryHeap() {
this(DEFAULT_CAPACITY, true);
}
/**
* Constructs a new <code>BinaryHeap</code> that will use the given
* comparator to order its elements.
*
* @param comparator the comparator used to order the elements, null
* means use natural order
*/
public BinaryHeap(Comparator comparator) {
this();
m_comparator = comparator;
}
/**
* Constructs a new minimum binary heap with the specified initial capacity.
*
* @param capacity The initial capacity for the heap. This value must
* be greater than zero.
* @throws IllegalArgumentException
* if <code>capacity</code> is &lt;= <code>0</code>
*/
public BinaryHeap(int capacity) {
this(capacity, true);
}
/**
* Constructs a new <code>BinaryHeap</code>.
*
* @param capacity the initial capacity for the heap
* @param comparator the comparator used to order the elements, null
* means use natural order
* @throws IllegalArgumentException
* if <code>capacity</code> is &lt;= <code>0</code>
*/
public BinaryHeap(int capacity, Comparator comparator) {
this(capacity);
m_comparator = comparator;
}
/**
* Constructs a new minimum or maximum binary heap
*
* @param isMinHeap if <code>true</code> the heap is created as a
* minimum heap; otherwise, the heap is created as a maximum heap
*/
public BinaryHeap(boolean isMinHeap) {
this(DEFAULT_CAPACITY, isMinHeap);
}
/**
* Constructs a new <code>BinaryHeap</code>.
*
* @param isMinHeap true to use the order imposed by the given
* comparator; false to reverse that order
* @param comparator the comparator used to order the elements, null
* means use natural order
*/
public BinaryHeap(boolean isMinHeap, Comparator comparator) {
this(isMinHeap);
m_comparator = comparator;
}
/**
* Constructs a new minimum or maximum binary heap with the specified
* initial capacity.
*
* @param capacity the initial capacity for the heap. This value must
* be greater than zero.
* @param isMinHeap if <code>true</code> the heap is created as a
* minimum heap; otherwise, the heap is created as a maximum heap.
* @throws IllegalArgumentException
* if <code>capacity</code> is <code>&lt;= 0</code>
*/
public BinaryHeap(int capacity, boolean isMinHeap) {
if (capacity <= 0) {
throw new IllegalArgumentException("invalid capacity");
}
m_isMinHeap = isMinHeap;
//+1 as 0 is noop
m_elements = new Object[capacity + 1];
}
/**
* Constructs a new <code>BinaryHeap</code>.
*
* @param capacity the initial capacity for the heap
* @param isMinHeap true to use the order imposed by the given
* comparator; false to reverse that order
* @param comparator the comparator used to order the elements, null
* means use natural order
* @throws IllegalArgumentException
* if <code>capacity</code> is <code>&lt;= 0</code>
*/
public BinaryHeap(int capacity, boolean isMinHeap, Comparator comparator) {
this(capacity, isMinHeap);
m_comparator = comparator;
}
//-----------------------------------------------------------------------
/**
* Clears all elements from queue.
*/
public void clear() {
m_elements = new Object[m_elements.length]; // for gc
m_size = 0;
}
/**
* Tests if queue is empty.
*
* @return <code>true</code> if queue is empty; <code>false</code>
* otherwise.
*/
public boolean isEmpty() {
return m_size == 0;
}
/**
* Tests if queue is full.
*
* @return <code>true</code> if queue is full; <code>false</code>
* otherwise.
*/
public boolean isFull() {
//+1 as element 0 is noop
return m_elements.length == m_size + 1;
}
/**
* Inserts an element into queue.
*
* @param element the element to be inserted
*/
public void insert(Object element) {
if (isFull()) {
grow();
}
//percolate element to it's place in tree
if (m_isMinHeap) {
percolateUpMinHeap(element);
} else {
percolateUpMaxHeap(element);
}
}
/**
* Returns the element on top of heap but don't remove it.
*
* @return the element at top of heap
* @throws NoSuchElementException if <code>isEmpty() == true</code>
*/
public Object peek() throws NoSuchElementException {
if (isEmpty()) {
throw new NoSuchElementException();
} else {
return m_elements[1];
}
}
/**
* Returns the element on top of heap and remove it.
*
* @return the element at top of heap
* @throws NoSuchElementException if <code>isEmpty() == true</code>
*/
public Object pop() throws NoSuchElementException {
final Object result = peek();
m_elements[1] = m_elements[m_size--];
// set the unused element to 'null' so that the garbage collector
// can free the object if not used anywhere else.(remove reference)
m_elements[m_size + 1] = null;
if (m_size != 0) {
// percolate top element to it's place in tree
if (m_isMinHeap) {
percolateDownMinHeap(1);
} else {
percolateDownMaxHeap(1);
}
}
return result;
}
/**
* Percolates element down heap from the position given by the index.
* <p>
* Assumes it is a minimum heap.
*
* @param index the index for the element
*/
protected void percolateDownMinHeap(final int index) {
final Object element = m_elements[index];
int hole = index;
while ((hole * 2) <= m_size) {
int child = hole * 2;
// if we have a right child and that child can not be percolated
// up then move onto other child
if (child != m_size && compare(m_elements[child + 1], m_elements[child]) < 0) {
child++;
}
// if we found resting place of bubble then terminate search
if (compare(m_elements[child], element) >= 0) {
break;
}
m_elements[hole] = m_elements[child];
hole = child;
}
m_elements[hole] = element;
}
/**
* Percolates element down heap from the position given by the index.
* <p>
* Assumes it is a maximum heap.
*
* @param index the index of the element
*/
protected void percolateDownMaxHeap(final int index) {
final Object element = m_elements[index];
int hole = index;
while ((hole * 2) <= m_size) {
int child = hole * 2;
// if we have a right child and that child can not be percolated
// up then move onto other child
if (child != m_size && compare(m_elements[child + 1], m_elements[child]) > 0) {
child++;
}
// if we found resting place of bubble then terminate search
if (compare(m_elements[child], element) <= 0) {
break;
}
m_elements[hole] = m_elements[child];
hole = child;
}
m_elements[hole] = element;
}
/**
* Percolates element up heap from the position given by the index.
* <p>
* Assumes it is a minimum heap.
*
* @param index the index of the element to be percolated up
*/
protected void percolateUpMinHeap(final int index) {
int hole = index;
Object element = m_elements[hole];
while (hole > 1 && compare(element, m_elements[hole / 2]) < 0) {
// save element that is being pushed down
// as the element "bubble" is percolated up
final int next = hole / 2;
m_elements[hole] = m_elements[next];
hole = next;
}
m_elements[hole] = element;
}
/**
* Percolates a new element up heap from the bottom.
* <p>
* Assumes it is a minimum heap.
*
* @param element the element
*/
protected void percolateUpMinHeap(final Object element) {
m_elements[++m_size] = element;
percolateUpMinHeap(m_size);
}
/**
* Percolates element up heap from from the position given by the index.
* <p>
* Assume it is a maximum heap.
*
* @param index the index of the element to be percolated up
*/
protected void percolateUpMaxHeap(final int index) {
int hole = index;
Object element = m_elements[hole];
while (hole > 1 && compare(element, m_elements[hole / 2]) > 0) {
// save element that is being pushed down
// as the element "bubble" is percolated up
final int next = hole / 2;
m_elements[hole] = m_elements[next];
hole = next;
}
m_elements[hole] = element;
}
/**
* Percolates a new element up heap from the bottom.
* <p>
* Assume it is a maximum heap.
*
* @param element the element
*/
protected void percolateUpMaxHeap(final Object element) {
m_elements[++m_size] = element;
percolateUpMaxHeap(m_size);
}
/**
* Compares two objects using the comparator if specified, or the
* natural order otherwise.
*
* @param a the first object
* @param b the second object
* @return -ve if a less than b, 0 if they are equal, +ve if a greater than b
*/
private int compare(Object a, Object b) {
if (m_comparator != null) {
return m_comparator.compare(a, b);
} else {
return ((Comparable) a).compareTo(b);
}
}
/**
* Increases the size of the heap to support additional elements
*/
protected void grow() {
final Object[] elements = new Object[m_elements.length * 2];
System.arraycopy(m_elements, 0, elements, 0, m_elements.length);
m_elements = elements;
}
/**
* Returns a string representation of this heap. The returned string
* is similar to those produced by standard JDK collections.
*
* @return a string representation of this heap
*/
public String toString() {
final StringBuffer sb = new StringBuffer();
sb.append("[ ");
for (int i = 1; i < m_size + 1; i++) {
if (i != 1) {
sb.append(", ");
}
sb.append(m_elements[i]);
}
sb.append(" ]");
return sb.toString();
}
/**
* Returns an iterator over this heap's elements.
*
* @return an iterator over this heap's elements
*/
public Iterator iterator() {
return new Iterator() {
private int index = 1;
private int lastReturnedIndex = -1;
public boolean hasNext() {
return index <= m_size;
}
public Object next() {
if (!hasNext()) throw new NoSuchElementException();
lastReturnedIndex = index;
index++;
return m_elements[lastReturnedIndex];
}
public void remove() {
if (lastReturnedIndex == -1) {
throw new IllegalStateException();
}
m_elements[ lastReturnedIndex ] = m_elements[ m_size ];
m_elements[ m_size ] = null;
m_size--;
if( m_size != 0 && lastReturnedIndex <= m_size) {
int compareToParent = 0;
if (lastReturnedIndex > 1) {
compareToParent = compare(m_elements[lastReturnedIndex],
m_elements[lastReturnedIndex / 2]);
}
if (m_isMinHeap) {
if (lastReturnedIndex > 1 && compareToParent < 0) {
percolateUpMinHeap(lastReturnedIndex);
} else {
percolateDownMinHeap(lastReturnedIndex);
}
} else { // max heap
if (lastReturnedIndex > 1 && compareToParent > 0) {
percolateUpMaxHeap(lastReturnedIndex);
} else {
percolateDownMaxHeap(lastReturnedIndex);
}
}
}
index--;
lastReturnedIndex = -1;
}
};
}
/**
* Adds an object to this heap. Same as {@link #insert(Object)}.
*
* @param object the object to add
* @return true, always
*/
public boolean add(Object object) {
insert(object);
return true;
}
/**
* Returns the priority element. Same as {@link #peek()}.
*
* @return the priority element
* @throws BufferUnderflowException if this heap is empty
*/
public Object get() {
try {
return peek();
} catch (NoSuchElementException e) {
throw new BufferUnderflowException();
}
}
/**
* Removes the priority element. Same as {@link #pop()}.
*
* @return the removed priority element
* @throws BufferUnderflowException if this heap is empty
*/
public Object remove() {
try {
return pop();
} catch (NoSuchElementException e) {
throw new BufferUnderflowException();
}
}
/**
* Returns the number of elements in this heap.
*
* @return the number of elements in this heap
*/
public int size() {
return m_size;
}
}

View File

@ -1,311 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.AbstractCollection;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* The BoundedFifoBuffer is a very efficient implementation of
* Buffer that does not alter the size of the buffer at runtime.
* <p>
* The removal order of a <code>BoundedFifoBuffer</code> is based on the
* insertion order; elements are removed in the same order in which they
* were added. The iteration order is the same as the removal order.
* <p>
* The {@link #add(Object)}, {@link #remove()} and {@link #get()} operations
* all perform in constant time. All other operations perform in linear
* time or worse.
* <p>
* Note that this implementation is not synchronized. The following can be
* used to provide synchronized access to your <code>BoundedFifoBuffer</code>:
* <pre>
* Buffer fifo = BufferUtils.synchronizedBuffer(new BoundedFifoBuffer());
* </pre>
* <p>
* This buffer prevents null objects from being added.
*
* @deprecated Moved to buffer subpackage. Due to be removed in v4.0.
* @since 2.1
* @version $Revision$ $Date$
*
* @author Avalon
* @author Berin Loritsch
* @author Paul Jack
* @author Stephen Colebourne
* @author Herve Quiroz
*/
public class BoundedFifoBuffer extends AbstractCollection
implements Buffer, BoundedCollection {
private final Object[] m_elements;
private int m_start = 0;
private int m_end = 0;
private boolean m_full = false;
private final int maxElements;
/**
* Constructs a new <code>BoundedFifoBuffer</code> big enough to hold
* 32 elements.
*/
public BoundedFifoBuffer() {
this(32);
}
/**
* Constructs a new <code>BoundedFifoBuffer</code> big enough to hold
* the specified number of elements.
*
* @param size the maximum number of elements for this fifo
* @throws IllegalArgumentException if the size is less than 1
*/
public BoundedFifoBuffer(int size) {
if (size <= 0) {
throw new IllegalArgumentException("The size must be greater than 0");
}
m_elements = new Object[size];
maxElements = m_elements.length;
}
/**
* Constructs a new <code>BoundedFifoBuffer</code> big enough to hold all
* of the elements in the specified collection. That collection's
* elements will also be added to the buffer.
*
* @param coll the collection whose elements to add, may not be null
* @throws NullPointerException if the collection is null
*/
public BoundedFifoBuffer(Collection coll) {
this(coll.size());
addAll(coll);
}
/**
* Returns the number of elements stored in the buffer.
*
* @return this buffer's size
*/
public int size() {
int size = 0;
if (m_end < m_start) {
size = maxElements - m_start + m_end;
} else if (m_end == m_start) {
size = (m_full ? maxElements : 0);
} else {
size = m_end - m_start;
}
return size;
}
/**
* Returns true if this buffer is empty; false otherwise.
*
* @return true if this buffer is empty
*/
public boolean isEmpty() {
return size() == 0;
}
/**
* Returns true if this collection is full and no new elements can be added.
*
* @return <code>true</code> if the collection is full
*/
public boolean isFull() {
return size() == maxElements;
}
/**
* Gets the maximum size of the collection (the bound).
*
* @return the maximum number of elements the collection can hold
*/
public int maxSize() {
return maxElements;
}
/**
* Clears this buffer.
*/
public void clear() {
m_full = false;
m_start = 0;
m_end = 0;
Arrays.fill(m_elements, null);
}
/**
* Adds the given element to this buffer.
*
* @param element the element to add
* @return true, always
* @throws NullPointerException if the given element is null
* @throws BufferOverflowException if this buffer is full
*/
public boolean add(Object element) {
if (null == element) {
throw new NullPointerException("Attempted to add null object to buffer");
}
if (m_full) {
throw new BufferOverflowException("The buffer cannot hold more than " + maxElements + " objects.");
}
m_elements[m_end++] = element;
if (m_end >= maxElements) {
m_end = 0;
}
if (m_end == m_start) {
m_full = true;
}
return true;
}
/**
* Returns the least recently inserted element in this buffer.
*
* @return the least recently inserted element
* @throws BufferUnderflowException if the buffer is empty
*/
public Object get() {
if (isEmpty()) {
throw new BufferUnderflowException("The buffer is already empty");
}
return m_elements[m_start];
}
/**
* Removes the least recently inserted element from this buffer.
*
* @return the least recently inserted element
* @throws BufferUnderflowException if the buffer is empty
*/
public Object remove() {
if (isEmpty()) {
throw new BufferUnderflowException("The buffer is already empty");
}
Object element = m_elements[m_start];
if (null != element) {
m_elements[m_start++] = null;
if (m_start >= maxElements) {
m_start = 0;
}
m_full = false;
}
return element;
}
/**
* Increments the internal index.
*
* @param index the index to increment
* @return the updated index
*/
private int increment(int index) {
index++;
if (index >= maxElements) {
index = 0;
}
return index;
}
/**
* Decrements the internal index.
*
* @param index the index to decrement
* @return the updated index
*/
private int decrement(int index) {
index--;
if (index < 0) {
index = maxElements - 1;
}
return index;
}
/**
* Returns an iterator over this buffer's elements.
*
* @return an iterator over this buffer's elements
*/
public Iterator iterator() {
return new Iterator() {
private int index = m_start;
private int lastReturnedIndex = -1;
private boolean isFirst = m_full;
public boolean hasNext() {
return isFirst || (index != m_end);
}
public Object next() {
if (!hasNext()) throw new NoSuchElementException();
isFirst = false;
lastReturnedIndex = index;
index = increment(index);
return m_elements[lastReturnedIndex];
}
public void remove() {
if (lastReturnedIndex == -1) throw new IllegalStateException();
// First element can be removed quickly
if (lastReturnedIndex == m_start) {
BoundedFifoBuffer.this.remove();
lastReturnedIndex = -1;
return;
}
// Other elements require us to shift the subsequent elements
int i = lastReturnedIndex + 1;
while (i != m_end) {
if (i >= maxElements) {
m_elements[i - 1] = m_elements[0];
i = 0;
} else {
m_elements[i - 1] = m_elements[i];
i++;
}
}
lastReturnedIndex = -1;
m_end = decrement(m_end);
m_elements[m_end] = null;
m_full = false;
index = decrement(index);
}
};
}
}

View File

@ -1,455 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.set.UnmodifiableSet;
/**
* A skeletal implementation of the {@link Bag}
* interface to minimize the effort required for target implementations.
* Subclasses need only to call <code>setMap(Map)</code> in their constructor
* (or invoke the Map constructor) specifying a map instance that will be used
* to store the contents of the bag.
* <p>
* The map will be used to map bag elements to a number; the number represents
* the number of occurrences of that element in the bag.
*
* @deprecated Moved to bag subpackage as AbstractMapBag. Due to be removed in v4.0.
* @since Commons Collections 2.0
* @version $Revision$ $Date$
*
* @author Chuck Burdick
* @author Michael A. Smith
* @author Stephen Colebourne
* @author Janek Bogucki
*/
public abstract class DefaultMapBag implements Bag {
private Map _map = null;
private int _total = 0;
private int _mods = 0;
/**
* No-argument constructor.
* Subclasses should invoke <code>setMap(Map)</code> in
* their constructors.
*/
public DefaultMapBag() {
}
/**
* Constructor that assigns the specified Map as the backing store.
* The map must be empty.
*
* @param map the map to assign
*/
protected DefaultMapBag(Map map) {
setMap(map);
}
/**
* Adds a new element to the bag by incrementing its count in the
* underlying map.
*
* @param object the object to add
* @return <code>true</code> if the object was not already in the <code>uniqueSet</code>
*/
public boolean add(Object object) {
return add(object, 1);
}
/**
* Adds a new element to the bag by incrementing its count in the map.
*
* @param object the object to search for
* @param nCopies the number of copies to add
* @return <code>true</code> if the object was not already in the <code>uniqueSet</code>
*/
public boolean add(Object object, int nCopies) {
_mods++;
if (nCopies > 0) {
int count = (nCopies + getCount(object));
_map.put(object, new Integer(count));
_total += nCopies;
return (count == nCopies);
} else {
return false;
}
}
/**
* Invokes {@link #add(Object)} for each element in the given collection.
*
* @param coll the collection to add
* @return <code>true</code> if this call changed the bag
*/
public boolean addAll(Collection coll) {
boolean changed = false;
Iterator i = coll.iterator();
while (i.hasNext()) {
boolean added = add(i.next());
changed = changed || added;
}
return changed;
}
/**
* Clears the bag by clearing the underlying map.
*/
public void clear() {
_mods++;
_map.clear();
_total = 0;
}
/**
* Determines if the bag contains the given element by checking if the
* underlying map contains the element as a key.
*
* @param object the object to search for
* @return true if the bag contains the given element
*/
public boolean contains(Object object) {
return _map.containsKey(object);
}
/**
* Determines if the bag contains the given elements.
*
* @param coll the collection to check against
* @return <code>true</code> if the Bag contains all the collection
*/
public boolean containsAll(Collection coll) {
return containsAll(new HashBag(coll));
}
/**
* Returns <code>true</code> if the bag contains all elements in
* the given collection, respecting cardinality.
*
* @param other the bag to check against
* @return <code>true</code> if the Bag contains all the collection
*/
public boolean containsAll(Bag other) {
boolean result = true;
Iterator i = other.uniqueSet().iterator();
while (i.hasNext()) {
Object current = i.next();
boolean contains = getCount(current) >= other.getCount(current);
result = result && contains;
}
return result;
}
/**
* Returns true if the given object is not null, has the precise type
* of this bag, and contains the same number of occurrences of all the
* same elements.
*
* @param object the object to test for equality
* @return true if that object equals this bag
*/
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof Bag == false) {
return false;
}
Bag other = (Bag) object;
if (other.size() != size()) {
return false;
}
for (Iterator it = _map.keySet().iterator(); it.hasNext();) {
Object element = it.next();
if (other.getCount(element) != getCount(element)) {
return false;
}
}
return true;
}
/**
* Returns the hash code of the underlying map.
*
* @return the hash code of the underlying map
*/
public int hashCode() {
return _map.hashCode();
}
/**
* Returns true if the underlying map is empty.
*
* @return true if there are no elements in this bag
*/
public boolean isEmpty() {
return _map.isEmpty();
}
public Iterator iterator() {
return new BagIterator(this, extractList().iterator());
}
static class BagIterator implements Iterator {
private DefaultMapBag _parent = null;
private Iterator _support = null;
private Object _current = null;
private int _mods = 0;
public BagIterator(DefaultMapBag parent, Iterator support) {
_parent = parent;
_support = support;
_current = null;
_mods = parent.modCount();
}
public boolean hasNext() {
return _support.hasNext();
}
public Object next() {
if (_parent.modCount() != _mods) {
throw new ConcurrentModificationException();
}
_current = _support.next();
return _current;
}
public void remove() {
if (_parent.modCount() != _mods) {
throw new ConcurrentModificationException();
}
_support.remove();
_parent.remove(_current, 1);
_mods++;
}
}
public boolean remove(Object object) {
return remove(object, getCount(object));
}
public boolean remove(Object object, int nCopies) {
_mods++;
boolean result = false;
int count = getCount(object);
if (nCopies <= 0) {
result = false;
} else if (count > nCopies) {
_map.put(object, new Integer(count - nCopies));
result = true;
_total -= nCopies;
} else { // count > 0 && count <= i
// need to remove all
result = (_map.remove(object) != null);
_total -= count;
}
return result;
}
public boolean removeAll(Collection coll) {
boolean result = false;
if (coll != null) {
Iterator i = coll.iterator();
while (i.hasNext()) {
boolean changed = remove(i.next(), 1);
result = result || changed;
}
}
return result;
}
/**
* Remove any members of the bag that are not in the given
* bag, respecting cardinality.
*
* @param coll the collection to retain
* @return true if this call changed the collection
*/
public boolean retainAll(Collection coll) {
return retainAll(new HashBag(coll));
}
/**
* Remove any members of the bag that are not in the given
* bag, respecting cardinality.
* @see #retainAll(Collection)
*
* @param other the bag to retain
* @return <code>true</code> if this call changed the collection
*/
public boolean retainAll(Bag other) {
boolean result = false;
Bag excess = new HashBag();
Iterator i = uniqueSet().iterator();
while (i.hasNext()) {
Object current = i.next();
int myCount = getCount(current);
int otherCount = other.getCount(current);
if (1 <= otherCount && otherCount <= myCount) {
excess.add(current, myCount - otherCount);
} else {
excess.add(current, myCount);
}
}
if (!excess.isEmpty()) {
result = removeAll(excess);
}
return result;
}
/**
* Returns an array of all of this bag's elements.
*
* @return an array of all of this bag's elements
*/
public Object[] toArray() {
return extractList().toArray();
}
/**
* Returns an array of all of this bag's elements.
*
* @param array the array to populate
* @return an array of all of this bag's elements
*/
public Object[] toArray(Object[] array) {
return extractList().toArray(array);
}
/**
* Returns the number of occurrence of the given element in this bag
* by looking up its count in the underlying map.
*
* @param object the object to search for
* @return the number of occurrences of the object, zero if not found
*/
public int getCount(Object object) {
int result = 0;
Integer count = MapUtils.getInteger(_map, object);
if (count != null) {
result = count.intValue();
}
return result;
}
/**
* Returns an unmodifiable view of the underlying map's key set.
*
* @return the set of unique elements in this bag
*/
public Set uniqueSet() {
return UnmodifiableSet.decorate(_map.keySet());
}
/**
* Returns the number of elements in this bag.
*
* @return the number of elements in this bag
*/
public int size() {
return _total;
}
/**
* Actually walks the bag to make sure the count is correct and
* resets the running total
*
* @return the current total size
*/
protected int calcTotalSize() {
_total = extractList().size();
return _total;
}
/**
* Utility method for implementations to set the map that backs
* this bag. Not intended for interactive use outside of
* subclasses.
*/
protected void setMap(Map map) {
if (map == null || map.isEmpty() == false) {
throw new IllegalArgumentException("The map must be non-null and empty");
}
_map = map;
}
/**
* Utility method for implementations to access the map that backs
* this bag. Not intended for interactive use outside of
* subclasses.
*/
protected Map getMap() {
return _map;
}
/**
* Create a list for use in iteration, etc.
*/
private List extractList() {
List result = new ArrayList();
Iterator i = uniqueSet().iterator();
while (i.hasNext()) {
Object current = i.next();
for (int index = getCount(current); index > 0; index--) {
result.add(current);
}
}
return result;
}
/**
* Return number of modifications for iterator.
*
* @return the modification count
*/
private int modCount() {
return _mods;
}
/**
* Implement a toString() method suitable for debugging.
*
* @return a debugging toString
*/
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("[");
Iterator i = uniqueSet().iterator();
while (i.hasNext()) {
Object current = i.next();
int count = getCount(current);
buf.append(count);
buf.append(":");
buf.append(current);
if (i.hasNext()) {
buf.append(",");
}
}
buf.append("]");
return buf.toString();
}
}

View File

@ -1,163 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.Map;
/**
* A default implementation of {@link java.util.Map.Entry}
*
* @deprecated Use the version in the keyvalue subpackage. Will be removed in v4.0
* @since Commons Collections 1.0
* @version $Revision$ $Date$
*
* @author James Strachan
* @author Michael A. Smith
* @author Neil O'Toole
* @author Stephen Colebourne
*/
public class DefaultMapEntry implements Map.Entry, KeyValue {
/** The key */
private Object key;
/** The value */
private Object value;
/**
* Constructs a new <code>DefaultMapEntry</code> with a null key
* and null value.
*/
public DefaultMapEntry() {
super();
}
/**
* Constructs a new <code>DefaultMapEntry</code> with the given
* key and given value.
*
* @param entry the entry to copy, must not be null
* @throws NullPointerException if the entry is null
*/
public DefaultMapEntry(Map.Entry entry) {
super();
this.key = entry.getKey();
this.value = entry.getValue();
}
/**
* Constructs a new <code>DefaultMapEntry</code> with the given
* key and given value.
*
* @param key the key for the entry, may be null
* @param value the value for the entry, may be null
*/
public DefaultMapEntry(Object key, Object value) {
super();
this.key = key;
this.value = value;
}
// Map.Entry interface
//-------------------------------------------------------------------------
/**
* Gets the key from the Map Entry.
*
* @return the key
*/
public Object getKey() {
return key;
}
/**
* Sets the key stored in this Map Entry.
* <p>
* This Map Entry is not connected to a Map, so only the local data is changed.
*
* @param key the new key
*/
public void setKey(Object key) {
this.key = key;
}
/**
* Gets the value from the Map Entry.
*
* @return the value
*/
public Object getValue() {
return value;
}
/**
* Sets the value stored in this Map Entry.
* <p>
* This Map Entry is not connected to a Map, so only the local data is changed.
*
* @param value the new value
* @return the previous value
*/
public Object setValue(Object value) {
Object answer = this.value;
this.value = value;
return answer;
}
// Basics
//-----------------------------------------------------------------------
/**
* Compares this Map Entry with another Map Entry.
* <p>
* Implemented per API documentation of {@link java.util.Map.Entry#equals(Object)}
*
* @param obj the object to compare to
* @return true if equal key and value
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Map.Entry == false) {
return false;
}
Map.Entry other = (Map.Entry) obj;
return
(getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) &&
(getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()));
}
/**
* Gets a hashCode compatible with the equals method.
* <p>
* Implemented per API documentation of {@link java.util.Map.Entry#hashCode()}
*
* @return a suitable hash code
*/
public int hashCode() {
return (getKey() == null ? 0 : getKey().hashCode()) ^
(getValue() == null ? 0 : getValue().hashCode());
}
/**
* Written to match the output of the Map.Entry's used in
* a {@link java.util.HashMap}.
* @since 3.0
*/
public String toString() {
return ""+getKey()+"="+getValue();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -176,16 +176,7 @@ public class ExtendedProperties extends Hashtable {
* This is the name of the property that can point to other
* properties file for including other properties files.
*/
private String includePropertyName = null;
/**
* This is the default name of the property that can point to other
* properties file for including other properties files.
*
* @deprecated Use getInclude() and setInclude() methods which operate
* on an instance variable from v3.3. Due to be removed in v4.0.
*/
protected static String include = "include";
private String includePropertyName = "include";
/**
* These are the keys in the order they listed
@ -501,41 +492,20 @@ public class ExtendedProperties extends Hashtable {
/**
* Gets the property value for including other properties files.
* By default it is "include".
* <p>
* NOTE: Prior to v3.3 this method accessed a static variable.
* It now accesses an instance variable. For compatability, if the
* instance variable has not been set then the previous static
* variable is then accessed. However, the protected static variable
* can now only be set by subclasses.
* In v4.0, the static variable will be removed.
*
* @return the property name which includes another property
*/
public String getInclude() {
if (includePropertyName == null) {
return include; // backwards compatability
}
if ("".equals(includePropertyName)) {
return null; // hack to allow backwards compatability
}
return includePropertyName;
}
/**
* Sets the property value for including other properties files.
* By default it is "include".
* <p>
* NOTE: Prior to v3.3 this method set a static variable and affected all
* users of the class. It now sets an instance variable.
* An empty string is also now converted to null internally.
* In v4.0, the static variable will be removed.
*
* @param inc the property name which includes another property, empty converted to null
*/
public void setInclude(String inc) {
if (inc == null) {
inc = ""; // hack to allow backwards compatability
}
includePropertyName = inc;
}

View File

@ -1,51 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.Collection;
import java.util.HashMap;
/**
* A {@link Bag} that is backed by a {@link HashMap}.
*
* @deprecated Moved to bag subpackage and rewritten internally. Due to be removed in v4.0.
* @since Commons Collections 2.0
* @version $Revision$ $Date$
*
* @author Chuck Burdick
*/
public class HashBag extends DefaultMapBag implements Bag {
/**
* Constructs an empty <Code>HashBag</Code>.
*/
public HashBag() {
super(new HashMap());
}
/**
* Constructs a {@link Bag} containing all the members of the given
* collection.
*
* @param coll a collection to copy into this bag
*/
public HashBag(Collection coll) {
this();
addAll(coll);
}
}

View File

@ -1,207 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.Iterator;
/**
* <p>
* An implementation of a Map which has a maximum size and uses a Least Recently Used
* algorithm to remove items from the Map when the maximum size is reached and new items are added.
* </p>
*
* <p>
* A synchronized version can be obtained with:
* <code>Collections.synchronizedMap( theMapToSynchronize )</code>
* If it will be accessed by multiple threads, you _must_ synchronize access
* to this Map. Even concurrent get(Object) operations produce indeterminate
* behaviour.
* </p>
*
* <p>
* Unlike the Collections 1.0 version, this version of LRUMap does use a true
* LRU algorithm. The keys for all gets and puts are moved to the front of
* the list. LRUMap is now a subclass of SequencedHashMap, and the "LRU"
* key is now equivalent to LRUMap.getFirst().
* </p>
*
* @deprecated Moved to map subpackage. Due to be removed in v4.0.
* @since Commons Collections 1.0
* @version $Revision$ $Date$
*
* @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
* @author <a href="mailto:morgand@apache.org">Morgan Delagrange</a>
*/
public class LRUMap extends SequencedHashMap implements Externalizable {
private int maximumSize = 0;
/**
* Default constructor, primarily for the purpose of
* de-externalization. This constructors sets a default
* LRU limit of 100 keys, but this value may be overridden
* internally as a result of de-externalization.
*/
public LRUMap() {
this( 100 );
}
/**
* Create a new LRUMap with a maximum capacity of <i>i</i>.
* Once <i>i</i> capacity is achieved, subsequent gets
* and puts will push keys out of the map. See .
*
* @param i Maximum capacity of the LRUMap
*/
public LRUMap(int i) {
super( i );
maximumSize = i;
}
/**
* <p>Get the value for a key from the Map. The key
* will be promoted to the Most Recently Used position.
* Note that get(Object) operations will modify
* the underlying Collection. Calling get(Object)
* inside of an iteration over keys, values, etc. is
* currently unsupported.</p>
*
* @param key Key to retrieve
* @return Returns the value. Returns null if the key has a
* null value <i>or</i> if the key has no value.
*/
public Object get(Object key) {
if(!containsKey(key)) return null;
Object value = remove(key);
super.put(key,value);
return value;
}
/**
* <p>Removes the key and its Object from the Map.</p>
*
* <p>(Note: this may result in the "Least Recently Used"
* object being removed from the Map. In that case,
* the removeLRU() method is called. See javadoc for
* removeLRU() for more details.)</p>
*
* @param key Key of the Object to add.
* @param value Object to add
* @return Former value of the key
*/
public Object put( Object key, Object value ) {
int mapSize = size();
Object retval = null;
if ( mapSize >= maximumSize ) {
// don't retire LRU if you are just
// updating an existing key
if (!containsKey(key)) {
// lets retire the least recently used item in the cache
removeLRU();
}
}
retval = super.put(key,value);
return retval;
}
/**
* This method is used internally by the class for
* finding and removing the LRU Object.
*/
protected void removeLRU() {
Object key = getFirstKey();
// be sure to call super.get(key), or you're likely to
// get infinite promotion recursion
Object value = super.get(key);
remove(key);
processRemovedLRU(key,value);
}
/**
* Subclasses of LRUMap may hook into this method to
* provide specialized actions whenever an Object is
* automatically removed from the cache. By default,
* this method does nothing.
*
* @param key key that was removed
* @param value value of that key (can be null)
*/
protected void processRemovedLRU(Object key, Object value) {
}
// Externalizable interface
//-------------------------------------------------------------------------
public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException {
maximumSize = in.readInt();
int size = in.readInt();
for( int i = 0; i < size; i++ ) {
Object key = in.readObject();
Object value = in.readObject();
put(key,value);
}
}
public void writeExternal( ObjectOutput out ) throws IOException {
out.writeInt( maximumSize );
out.writeInt( size() );
for( Iterator iterator = keySet().iterator(); iterator.hasNext(); ) {
Object key = iterator.next();
out.writeObject( key );
// be sure to call super.get(key), or you're likely to
// get infinite promotion recursion
Object value = super.get( key );
out.writeObject( value );
}
}
// Properties
//-------------------------------------------------------------------------
/** Getter for property maximumSize.
* @return Value of property maximumSize.
*/
public int getMaximumSize() {
return maximumSize;
}
/** Setter for property maximumSize.
* @param maximumSize New value of property maximumSize.
*/
public void setMaximumSize(int maximumSize) {
this.maximumSize = maximumSize;
while (size() > maximumSize) {
removeLRU();
}
}
// add a serial version uid, so that if we change things in the future
// without changing the format, we can still deserialize properly.
private static final long serialVersionUID = 2197433140769957051L;
}

View File

@ -1,493 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.apache.commons.collections.iterators.EmptyIterator;
/**
* <code>MultiHashMap</code> is the default implementation of the
* {@link org.apache.commons.collections.MultiMap MultiMap} interface.
* <p>
* A <code>MultiMap</code> is a Map with slightly different semantics.
* Putting a value into the map will add the value to a Collection at that key.
* Getting a value will return a Collection, holding all the values put to that key.
* <p>
* This implementation uses an <code>ArrayList</code> as the collection.
* The internal storage list is made available without cloning via the
* <code>get(Object)</code> and <code>entrySet()</code> methods.
* The implementation returns <code>null</code> when there are no values mapped to a key.
* <p>
* For example:
* <pre>
* MultiMap mhm = new MultiHashMap();
* mhm.put(key, "A");
* mhm.put(key, "B");
* mhm.put(key, "C");
* List list = (List) mhm.get(key);</pre>
* <p>
* <code>list</code> will be a list containing "A", "B", "C".
*
* @deprecated Class now available as MultiValueMap in map subpackage.
* This version is due to be removed in collections v4.0.
*
* @since Commons Collections 2.0
* @version $Revision$ $Date$
*
* @author Christopher Berry
* @author James Strachan
* @author Steve Downey
* @author Stephen Colebourne
* @author Julien Buret
* @author Serhiy Yevtushenko
* @author Robert Ribnitz
*/
public class MultiHashMap extends HashMap implements MultiMap {
// backed values collection
private transient Collection values = null;
// compatibility with commons-collection releases 2.0/2.1
private static final long serialVersionUID = 1943563828307035349L;
/**
* Constructor.
*/
public MultiHashMap() {
super();
}
/**
* Constructor.
*
* @param initialCapacity the initial map capacity
*/
public MultiHashMap(int initialCapacity) {
super(initialCapacity);
}
/**
* Constructor.
*
* @param initialCapacity the initial map capacity
* @param loadFactor the amount 0.0-1.0 at which to resize the map
*/
public MultiHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
/**
* Constructor that copies the input map creating an independent copy.
* <p>
* This method performs different behaviour depending on whether the map
* specified is a MultiMap or not. If a MultiMap is specified, each internal
* collection is also cloned. If the specified map only implements Map, then
* the values are not cloned.
* <p>
* NOTE: From Commons Collections 3.1 this method correctly copies a MultiMap
* to form a truly independent new map.
* NOTE: From Commons Collections 3.2 this method delegates to the newly
* added putAll(Map) override method.
*
* @param mapToCopy a Map to copy
*/
public MultiHashMap(Map mapToCopy) {
// be careful of JDK 1.3 vs 1.4 differences
super((int) (mapToCopy.size() * 1.4f));
putAll(mapToCopy);
}
/**
* Read the object during deserialization.
*/
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
// This method is needed because the 1.2/1.3 Java deserialisation called
// put and thus messed up that method
// default read object
s.defaultReadObject();
// problem only with jvm <1.4
String version = "1.2";
try {
version = System.getProperty("java.version");
} catch (SecurityException ex) {
// ignore and treat as 1.2/1.3
}
if (version.startsWith("1.2") || version.startsWith("1.3")) {
for (Iterator iterator = entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
// put has created a extra collection level, remove it
super.put(entry.getKey(), ((Collection) entry.getValue()).iterator().next());
}
}
}
//-----------------------------------------------------------------------
/**
* Gets the total size of the map by counting all the values.
*
* @return the total size of the map counting all values
* @since Commons Collections 3.1
*/
public int totalSize() {
int total = 0;
Collection values = super.values();
for (Iterator it = values.iterator(); it.hasNext();) {
Collection coll = (Collection) it.next();
total += coll.size();
}
return total;
}
/**
* Gets the collection mapped to the specified key.
* This method is a convenience method to typecast the result of <code>get(key)</code>.
*
* @param key the key to retrieve
* @return the collection mapped to the key, null if no mapping
* @since Commons Collections 3.1
*/
public Collection getCollection(Object key) {
return (Collection) get(key);
}
/**
* Gets the size of the collection mapped to the specified key.
*
* @param key the key to get size for
* @return the size of the collection at the key, zero if key not in map
* @since Commons Collections 3.1
*/
public int size(Object key) {
Collection coll = getCollection(key);
if (coll == null) {
return 0;
}
return coll.size();
}
/**
* Gets an iterator for the collection mapped to the specified key.
*
* @param key the key to get an iterator for
* @return the iterator of the collection at the key, empty iterator if key not in map
* @since Commons Collections 3.1
*/
public Iterator iterator(Object key) {
Collection coll = getCollection(key);
if (coll == null) {
return EmptyIterator.INSTANCE;
}
return coll.iterator();
}
/**
* Adds the value to the collection associated with the specified key.
* <p>
* Unlike a normal <code>Map</code> the previous value is not replaced.
* Instead the new value is added to the collection stored against the key.
*
* @param key the key to store against
* @param value the value to add to the collection at the key
* @return the value added if the map changed and null if the map did not change
*/
public Object put(Object key, Object value) {
// NOTE:: put is called during deserialization in JDK < 1.4 !!!!!!
// so we must have a readObject()
Collection coll = getCollection(key);
if (coll == null) {
coll = createCollection(null);
super.put(key, coll);
}
boolean results = coll.add(value);
return (results ? value : null);
}
/**
* Override superclass to ensure that MultiMap instances are
* correctly handled.
* <p>
* NOTE: Prior to version 3.2, putAll(map) did not work properly
* when passed a MultiMap.
*
* @param map the map to copy (either a normal or multi map)
*/
public void putAll(Map map) {
if (map instanceof MultiMap) {
for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
Collection coll = (Collection) entry.getValue();
putAll(entry.getKey(), coll);
}
} else {
for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
put(entry.getKey(), entry.getValue());
}
}
}
/**
* Adds a collection of values to the collection associated with the specified key.
*
* @param key the key to store against
* @param values the values to add to the collection at the key, null ignored
* @return true if this map changed
* @since Commons Collections 3.1
*/
public boolean putAll(Object key, Collection values) {
if (values == null || values.size() == 0) {
return false;
}
Collection coll = getCollection(key);
if (coll == null) {
coll = createCollection(values);
if (coll.size() == 0) {
return false;
}
super.put(key, coll);
return true;
} else {
return coll.addAll(values);
}
}
/**
* Checks whether the map contains the value specified.
* <p>
* This checks all collections against all keys for the value, and thus could be slow.
*
* @param value the value to search for
* @return true if the map contains the value
*/
public boolean containsValue(Object value) {
Set pairs = super.entrySet();
if (pairs == null) {
return false;
}
Iterator pairsIterator = pairs.iterator();
while (pairsIterator.hasNext()) {
Map.Entry keyValuePair = (Map.Entry) pairsIterator.next();
Collection coll = (Collection) keyValuePair.getValue();
if (coll.contains(value)) {
return true;
}
}
return false;
}
/**
* Checks whether the collection at the specified key contains the value.
*
* @param value the value to search for
* @return true if the map contains the value
* @since Commons Collections 3.1
*/
public boolean containsValue(Object key, Object value) {
Collection coll = getCollection(key);
if (coll == null) {
return false;
}
return coll.contains(value);
}
/**
* Removes a specific value from map.
* <p>
* The item is removed from the collection mapped to the specified key.
* Other values attached to that key are unaffected.
* <p>
* If the last value for a key is removed, <code>null</code> will be returned
* from a subsequant <code>get(key)</code>.
*
* @param key the key to remove from
* @param item the value to remove
* @return the value removed (which was passed in), null if nothing removed
*/
public Object remove(Object key, Object item) {
Collection valuesForKey = getCollection(key);
if (valuesForKey == null) {
return null;
}
boolean removed = valuesForKey.remove(item);
if (removed == false) {
return null;
}
// remove the list if it is now empty
// (saves space, and allows equals to work)
if (valuesForKey.isEmpty()){
remove(key);
}
return item;
}
/**
* Clear the map.
* <p>
* This clears each collection in the map, and so may be slow.
*/
public void clear() {
// For gc, clear each list in the map
Set pairs = super.entrySet();
Iterator pairsIterator = pairs.iterator();
while (pairsIterator.hasNext()) {
Map.Entry keyValuePair = (Map.Entry) pairsIterator.next();
Collection coll = (Collection) keyValuePair.getValue();
coll.clear();
}
super.clear();
}
/**
* Gets a collection containing all the values in the map.
* <p>
* This returns a collection containing the combination of values from all keys.
*
* @return a collection view of the values contained in this map
*/
public Collection values() {
Collection vs = values;
return (vs != null ? vs : (values = new Values()));
}
/**
* Gets the values iterator from the superclass, as used by inner class.
*
* @return iterator
*/
Iterator superValuesIterator() {
return super.values().iterator();
}
//-----------------------------------------------------------------------
/**
* Inner class to view the elements.
*/
private class Values extends AbstractCollection {
public Iterator iterator() {
return new ValueIterator();
}
public int size() {
int compt = 0;
Iterator it = iterator();
while (it.hasNext()) {
it.next();
compt++;
}
return compt;
}
public void clear() {
MultiHashMap.this.clear();
}
}
/**
* Inner iterator to view the elements.
*/
private class ValueIterator implements Iterator {
private Iterator backedIterator;
private Iterator tempIterator;
private ValueIterator() {
backedIterator = MultiHashMap.this.superValuesIterator();
}
private boolean searchNextIterator() {
while (tempIterator == null || tempIterator.hasNext() == false) {
if (backedIterator.hasNext() == false) {
return false;
}
tempIterator = ((Collection) backedIterator.next()).iterator();
}
return true;
}
public boolean hasNext() {
return searchNextIterator();
}
public Object next() {
if (searchNextIterator() == false) {
throw new NoSuchElementException();
}
return tempIterator.next();
}
public void remove() {
if (tempIterator == null) {
throw new IllegalStateException();
}
tempIterator.remove();
}
}
//-----------------------------------------------------------------------
/**
* Clones the map creating an independent copy.
* <p>
* The clone will shallow clone the collections as well as the map.
*
* @return the cloned map
*/
public Object clone() {
MultiHashMap cloned = (MultiHashMap) super.clone();
// clone each Collection container
for (Iterator it = cloned.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
Collection coll = (Collection) entry.getValue();
Collection newColl = createCollection(coll);
entry.setValue(newColl);
}
return cloned;
}
/**
* Creates a new instance of the map value Collection container.
* <p>
* This method can be overridden to use your own collection type.
*
* @param coll the collection to copy, may be null
* @return the new collection
*/
protected Collection createCollection(Collection coll) {
if (coll == null) {
return new ArrayList();
} else {
return new ArrayList(coll);
}
}
}

View File

@ -1,72 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
/**
* Defines a collection for priority queues, which can insert, peek and pop.
* <p>
* This interface is now replaced by the <code>Buffer</code> interface.
*
* @deprecated Replaced by the Buffer interface and implementations in buffer subpackage.
* Due to be removed in v4.0.
* @since Commons Collections 1.0
* @version $Revision$ $Date$
*
* @author Peter Donald
*/
public interface PriorityQueue {
/**
* Clear all elements from queue.
*/
void clear();
/**
* Test if queue is empty.
*
* @return true if queue is empty else false.
*/
boolean isEmpty();
/**
* Insert an element into queue.
*
* @param element the element to be inserted
*
* @throws ClassCastException if the specified <code>element</code>'s
* type prevents it from being compared to other items in the queue to
* determine its relative priority.
*/
void insert(Object element);
/**
* Return element on top of heap but don't remove it.
*
* @return the element at top of heap
* @throws java.util.NoSuchElementException if <code>isEmpty() == true</code>
*/
Object peek();
/**
* Return element on top of heap and remove it.
*
* @return the element at top of heap
* @throws java.util.NoSuchElementException if <code>isEmpty() == true</code>
*/
Object pop();
}

View File

@ -1,163 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
/**
* <p>This <code>Map</code> wraps another <code>Map</code>
* implementation, using the wrapped instance for its default
* implementation. This class is used as a framework on which to
* build to extensions for its wrapped <code>Map</code> object which
* would be unavailable or inconvenient via sub-classing (but usable
* via composition).</p>
*
* <p>This implementation does not perform any special processing with
* {@link #entrySet()}, {@link #keySet()} or {@link #values()}. Instead
* it simply returns the set/collection from the wrapped map. This may be
* undesirable, for example if you are trying to write a validating
* implementation it would provide a loophole around the validation. But,
* you might want that loophole, so this class is kept simple.</p>
*
* @deprecated Moved to map subpackage as AbstractMapDecorator. It will be removed in v4.0.
* @since Commons Collections 2.0
* @version $Revision$ $Date$
*
* @author Daniel Rall
* @author Stephen Colebourne
*/
public abstract class ProxyMap implements Map {
/**
* The <code>Map</code> to delegate to.
*/
protected Map map;
/**
* Constructor that uses the specified map to delegate to.
* <p>
* Note that the map is used for delegation, and is not copied. This is
* different to the normal use of a <code>Map</code> parameter in
* collections constructors.
*
* @param map the <code>Map</code> to delegate to
*/
public ProxyMap(Map map) {
this.map = map;
}
/**
* Invokes the underlying {@link Map#clear()} method.
*/
public void clear() {
map.clear();
}
/**
* Invokes the underlying {@link Map#containsKey(Object)} method.
*/
public boolean containsKey(Object key) {
return map.containsKey(key);
}
/**
* Invokes the underlying {@link Map#containsValue(Object)} method.
*/
public boolean containsValue(Object value) {
return map.containsValue(value);
}
/**
* Invokes the underlying {@link Map#entrySet()} method.
*/
public Set entrySet() {
return map.entrySet();
}
/**
* Invokes the underlying {@link Map#equals(Object)} method.
*/
public boolean equals(Object m) {
return map.equals(m);
}
/**
* Invokes the underlying {@link Map#get(Object)} method.
*/
public Object get(Object key) {
return map.get(key);
}
/**
* Invokes the underlying {@link Map#hashCode()} method.
*/
public int hashCode() {
return map.hashCode();
}
/**
* Invokes the underlying {@link Map#isEmpty()} method.
*/
public boolean isEmpty() {
return map.isEmpty();
}
/**
* Invokes the underlying {@link Map#keySet()} method.
*/
public Set keySet() {
return map.keySet();
}
/**
* Invokes the underlying {@link Map#put(Object,Object)} method.
*/
public Object put(Object key, Object value) {
return map.put(key, value);
}
/**
* Invokes the underlying {@link Map#putAll(Map)} method.
*/
public void putAll(Map t) {
map.putAll(t);
}
/**
* Invokes the underlying {@link Map#remove(Object)} method.
*/
public Object remove(Object key) {
return map.remove(key);
}
/**
* Invokes the underlying {@link Map#size()} method.
*/
public int size() {
return map.size();
}
/**
* Invokes the underlying {@link Map#values()} method.
*/
public Collection values() {
return map.values();
}
}

View File

@ -1,958 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.apache.commons.collections.keyvalue.DefaultMapEntry;
/**
* Hash-based {@link Map} implementation that allows
* mappings to be removed by the garbage collector.<p>
*
* When you construct a <code>ReferenceMap</code>, you can
* specify what kind of references are used to store the
* map's keys and values. If non-hard references are
* used, then the garbage collector can remove mappings
* if a key or value becomes unreachable, or if the
* JVM's memory is running low. For information on how
* the different reference types behave, see
* {@link Reference}.<p>
*
* Different types of references can be specified for keys
* and values. The keys can be configured to be weak but
* the values hard, in which case this class will behave
* like a <a href="http://java.sun.com/j2se/1.4/docs/api/java/util/WeakHashMap.html">
* <code>WeakHashMap</code></a>. However, you
* can also specify hard keys and weak values, or any other
* combination. The default constructor uses hard keys
* and soft values, providing a memory-sensitive cache.<p>
*
* The algorithms used are basically the same as those
* in {@link java.util.HashMap}. In particular, you
* can specify a load factor and capacity to suit your
* needs. All optional {@link Map} operations are
* supported.<p>
*
* However, this {@link Map} implementation does <I>not</I>
* allow null elements. Attempting to add a null key or
* or a null value to the map will raise a
* <code>NullPointerException</code>.<p>
*
* As usual, this implementation is not synchronized. You
* can use {@link java.util.Collections#synchronizedMap} to
* provide synchronized access to a <code>ReferenceMap</code>.
*
* @see java.lang.ref.Reference
*
* @deprecated Moved to map subpackage. Due to be removed in v4.0.
* @since Commons Collections 2.1
* @version $Revision$ $Date$
*
* @author Paul Jack
*/
public class ReferenceMap extends AbstractMap {
/**
* For serialization.
*/
private static final long serialVersionUID = -3370601314380922368L;
/**
* Constant indicating that hard references should be used.
*/
final public static int HARD = 0;
/**
* Constant indicating that soft references should be used.
*/
final public static int SOFT = 1;
/**
* Constant indicating that weak references should be used.
*/
final public static int WEAK = 2;
// --- serialized instance variables:
/**
* The reference type for keys. Must be HARD, SOFT, WEAK.
* Note: I originally marked this field as final, but then this class
* didn't compile under JDK1.2.2.
* @serial
*/
private int keyType;
/**
* The reference type for values. Must be HARD, SOFT, WEAK.
* Note: I originally marked this field as final, but then this class
* didn't compile under JDK1.2.2.
* @serial
*/
private int valueType;
/**
* The threshold variable is calculated by multiplying
* table.length and loadFactor.
* Note: I originally marked this field as final, but then this class
* didn't compile under JDK1.2.2.
* @serial
*/
private float loadFactor;
/**
* Should the value be automatically purged when the associated key has been collected?
*/
private boolean purgeValues = false;
// -- Non-serialized instance variables
/**
* ReferenceQueue used to eliminate stale mappings.
* See purge.
*/
private transient ReferenceQueue queue = new ReferenceQueue();
/**
* The hash table. Its length is always a power of two.
*/
private transient Entry[] table;
/**
* Number of mappings in this map.
*/
private transient int size;
/**
* When size reaches threshold, the map is resized.
* See resize().
*/
private transient int threshold;
/**
* Number of times this map has been modified.
*/
private transient volatile int modCount;
/**
* Cached key set. May be null if key set is never accessed.
*/
private transient Set keySet;
/**
* Cached entry set. May be null if entry set is never accessed.
*/
private transient Set entrySet;
/**
* Cached values. May be null if values() is never accessed.
*/
private transient Collection values;
/**
* Constructs a new <code>ReferenceMap</code> that will
* use hard references to keys and soft references to values.
*/
public ReferenceMap() {
this(HARD, SOFT);
}
/**
* Constructs a new <code>ReferenceMap</code> that will
* use the specified types of references.
*
* @param keyType the type of reference to use for keys;
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
* @param valueType the type of reference to use for values;
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
* @param purgeValues should the value be automatically purged when the
* key is garbage collected
*/
public ReferenceMap(int keyType, int valueType, boolean purgeValues) {
this(keyType, valueType);
this.purgeValues = purgeValues;
}
/**
* Constructs a new <code>ReferenceMap</code> that will
* use the specified types of references.
*
* @param keyType the type of reference to use for keys;
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
* @param valueType the type of reference to use for values;
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
*/
public ReferenceMap(int keyType, int valueType) {
this(keyType, valueType, 16, 0.75f);
}
/**
* Constructs a new <code>ReferenceMap</code> with the
* specified reference types, load factor and initial
* capacity.
*
* @param keyType the type of reference to use for keys;
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
* @param valueType the type of reference to use for values;
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
* @param capacity the initial capacity for the map
* @param loadFactor the load factor for the map
* @param purgeValues should the value be automatically purged when the
* key is garbage collected
*/
public ReferenceMap(
int keyType,
int valueType,
int capacity,
float loadFactor,
boolean purgeValues) {
this(keyType, valueType, capacity, loadFactor);
this.purgeValues = purgeValues;
}
/**
* Constructs a new <code>ReferenceMap</code> with the
* specified reference types, load factor and initial
* capacity.
*
* @param keyType the type of reference to use for keys;
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
* @param valueType the type of reference to use for values;
* must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
* @param capacity the initial capacity for the map
* @param loadFactor the load factor for the map
*/
public ReferenceMap(int keyType, int valueType, int capacity, float loadFactor) {
super();
verify("keyType", keyType);
verify("valueType", valueType);
if (capacity <= 0) {
throw new IllegalArgumentException("capacity must be positive");
}
if ((loadFactor <= 0.0f) || (loadFactor >= 1.0f)) {
throw new IllegalArgumentException("Load factor must be greater than 0 and less than 1.");
}
this.keyType = keyType;
this.valueType = valueType;
int v = 1;
while (v < capacity) v *= 2;
this.table = new Entry[v];
this.loadFactor = loadFactor;
this.threshold = (int)(v * loadFactor);
}
// used by constructor
private static void verify(String name, int type) {
if ((type < HARD) || (type > WEAK)) {
throw new IllegalArgumentException(name +
" must be HARD, SOFT, WEAK.");
}
}
/**
* Writes this object to the given output stream.
*
* @param out the output stream to write to
* @throws IOException if the stream raises it
*/
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeInt(table.length);
// Have to use null-terminated list because size might shrink
// during iteration
for (Iterator iter = entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry)iter.next();
out.writeObject(entry.getKey());
out.writeObject(entry.getValue());
}
out.writeObject(null);
}
/**
* Reads the contents of this object from the given input stream.
*
* @param inp the input stream to read from
* @throws IOException if the stream raises it
* @throws ClassNotFoundException if the stream raises it
*/
private void readObject(ObjectInputStream inp) throws IOException, ClassNotFoundException {
inp.defaultReadObject();
table = new Entry[inp.readInt()];
threshold = (int)(table.length * loadFactor);
queue = new ReferenceQueue();
Object key = inp.readObject();
while (key != null) {
Object value = inp.readObject();
put(key, value);
key = inp.readObject();
}
}
/**
* Constructs a reference of the given type to the given
* referent. The reference is registered with the queue
* for later purging.
*
* @param type HARD, SOFT or WEAK
* @param referent the object to refer to
* @param hash the hash code of the <I>key</I> of the mapping;
* this number might be different from referent.hashCode() if
* the referent represents a value and not a key
*/
private Object toReference(int type, Object referent, int hash) {
switch (type) {
case HARD: return referent;
case SOFT: return new SoftRef(hash, referent, queue);
case WEAK: return new WeakRef(hash, referent, queue);
default: throw new Error();
}
}
/**
* Returns the entry associated with the given key.
*
* @param key the key of the entry to look up
* @return the entry associated with that key, or null
* if the key is not in this map
*/
private Entry getEntry(Object key) {
if (key == null) return null;
int hash = key.hashCode();
int index = indexFor(hash);
for (Entry entry = table[index]; entry != null; entry = entry.next) {
if ((entry.hash == hash) && key.equals(entry.getKey())) {
return entry;
}
}
return null;
}
/**
* Converts the given hash code into an index into the
* hash table.
*/
private int indexFor(int hash) {
// mix the bits to avoid bucket collisions...
hash += ~(hash << 15);
hash ^= (hash >>> 10);
hash += (hash << 3);
hash ^= (hash >>> 6);
hash += ~(hash << 11);
hash ^= (hash >>> 16);
return hash & (table.length - 1);
}
/**
* Resizes this hash table by doubling its capacity.
* This is an expensive operation, as entries must
* be copied from the old smaller table to the new
* bigger table.
*/
private void resize() {
Entry[] old = table;
table = new Entry[old.length * 2];
for (int i = 0; i < old.length; i++) {
Entry next = old[i];
while (next != null) {
Entry entry = next;
next = next.next;
int index = indexFor(entry.hash);
entry.next = table[index];
table[index] = entry;
}
old[i] = null;
}
threshold = (int)(table.length * loadFactor);
}
/**
* Purges stale mappings from this map.
* <p>
* Ordinarily, stale mappings are only removed during
* a write operation, although this method is called for both
* read and write operations to maintain a consistent state.
* <p>
* Note that this method is not synchronized! Special
* care must be taken if, for instance, you want stale
* mappings to be removed on a periodic basis by some
* background thread.
*/
private void purge() {
Reference ref = queue.poll();
while (ref != null) {
purge(ref);
ref = queue.poll();
}
}
private void purge(Reference ref) {
// The hashCode of the reference is the hashCode of the
// mapping key, even if the reference refers to the
// mapping value...
int hash = ref.hashCode();
int index = indexFor(hash);
Entry previous = null;
Entry entry = table[index];
while (entry != null) {
if (entry.purge(ref)) {
if (previous == null) table[index] = entry.next;
else previous.next = entry.next;
this.size--;
return;
}
previous = entry;
entry = entry.next;
}
}
/**
* Returns the size of this map.
*
* @return the size of this map
*/
public int size() {
purge();
return size;
}
/**
* Returns <code>true</code> if this map is empty.
*
* @return <code>true</code> if this map is empty
*/
public boolean isEmpty() {
purge();
return size == 0;
}
/**
* Returns <code>true</code> if this map contains the given key.
*
* @return true if the given key is in this map
*/
public boolean containsKey(Object key) {
purge();
Entry entry = getEntry(key);
if (entry == null) return false;
return entry.getValue() != null;
}
/**
* Returns the value associated with the given key, if any.
*
* @return the value associated with the given key, or <code>null</code>
* if the key maps to no value
*/
public Object get(Object key) {
purge();
Entry entry = getEntry(key);
if (entry == null) return null;
return entry.getValue();
}
/**
* Associates the given key with the given value.<p>
* Neither the key nor the value may be null.
*
* @param key the key of the mapping
* @param value the value of the mapping
* @return the last value associated with that key, or
* null if no value was associated with the key
* @throws NullPointerException if either the key or value
* is null
*/
public Object put(Object key, Object value) {
if (key == null) throw new NullPointerException("null keys not allowed");
if (value == null) throw new NullPointerException("null values not allowed");
purge();
if (size + 1 > threshold) resize();
int hash = key.hashCode();
int index = indexFor(hash);
Entry entry = table[index];
while (entry != null) {
if ((hash == entry.hash) && key.equals(entry.getKey())) {
Object result = entry.getValue();
entry.setValue(value);
return result;
}
entry = entry.next;
}
this.size++;
modCount++;
key = toReference(keyType, key, hash);
value = toReference(valueType, value, hash);
table[index] = new Entry(key, hash, value, table[index]);
return null;
}
/**
* Removes the key and its associated value from this map.
*
* @param key the key to remove
* @return the value associated with that key, or null if
* the key was not in the map
*/
public Object remove(Object key) {
if (key == null) return null;
purge();
int hash = key.hashCode();
int index = indexFor(hash);
Entry previous = null;
Entry entry = table[index];
while (entry != null) {
if ((hash == entry.hash) && key.equals(entry.getKey())) {
if (previous == null) table[index] = entry.next;
else previous.next = entry.next;
this.size--;
modCount++;
return entry.getValue();
}
previous = entry;
entry = entry.next;
}
return null;
}
/**
* Clears this map.
*/
public void clear() {
Arrays.fill(table, null);
size = 0;
while (queue.poll() != null); // drain the queue
}
/**
* Returns a set view of this map's entries.
*
* @return a set view of this map's entries
*/
public Set entrySet() {
if (entrySet != null) {
return entrySet;
}
entrySet = new AbstractSet() {
public int size() {
return ReferenceMap.this.size();
}
public void clear() {
ReferenceMap.this.clear();
}
public boolean contains(Object o) {
if (o == null) return false;
if (!(o instanceof Map.Entry)) return false;
Map.Entry e = (Map.Entry)o;
Entry e2 = getEntry(e.getKey());
return (e2 != null) && e.equals(e2);
}
public boolean remove(Object o) {
boolean r = contains(o);
if (r) {
Map.Entry e = (Map.Entry)o;
ReferenceMap.this.remove(e.getKey());
}
return r;
}
public Iterator iterator() {
return new EntryIterator();
}
public Object[] toArray() {
return toArray(new Object[0]);
}
public Object[] toArray(Object[] arr) {
ArrayList list = new ArrayList();
Iterator iterator = iterator();
while (iterator.hasNext()) {
Entry e = (Entry)iterator.next();
list.add(new DefaultMapEntry(e.getKey(), e.getValue()));
}
return list.toArray(arr);
}
};
return entrySet;
}
/**
* Returns a set view of this map's keys.
*
* @return a set view of this map's keys
*/
public Set keySet() {
if (keySet != null) return keySet;
keySet = new AbstractSet() {
public int size() {
return ReferenceMap.this.size();
}
public Iterator iterator() {
return new KeyIterator();
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
Object r = ReferenceMap.this.remove(o);
return r != null;
}
public void clear() {
ReferenceMap.this.clear();
}
public Object[] toArray() {
return toArray(new Object[0]);
}
public Object[] toArray(Object[] array) {
Collection c = new ArrayList(size());
for (Iterator it = iterator(); it.hasNext(); ) {
c.add(it.next());
}
return c.toArray(array);
}
};
return keySet;
}
/**
* Returns a collection view of this map's values.
*
* @return a collection view of this map's values.
*/
public Collection values() {
if (values != null) return values;
values = new AbstractCollection() {
public int size() {
return ReferenceMap.this.size();
}
public void clear() {
ReferenceMap.this.clear();
}
public Iterator iterator() {
return new ValueIterator();
}
public Object[] toArray() {
return toArray(new Object[0]);
}
public Object[] toArray(Object[] array) {
Collection c = new ArrayList(size());
for (Iterator it = iterator(); it.hasNext(); ) {
c.add(it.next());
}
return c.toArray(array);
}
};
return values;
}
// If getKey() or getValue() returns null, it means
// the mapping is stale and should be removed.
private class Entry implements Map.Entry, KeyValue {
Object key;
Object value;
int hash;
Entry next;
public Entry(Object key, int hash, Object value, Entry next) {
this.key = key;
this.hash = hash;
this.value = value;
this.next = next;
}
public Object getKey() {
return (keyType > HARD) ? ((Reference)key).get() : key;
}
public Object getValue() {
return (valueType > HARD) ? ((Reference)value).get() : value;
}
public Object setValue(Object object) {
Object old = getValue();
if (valueType > HARD) ((Reference)value).clear();
value = toReference(valueType, object, hash);
return old;
}
public boolean equals(Object o) {
if (o == null) return false;
if (o == this) return true;
if (!(o instanceof Map.Entry)) return false;
Map.Entry entry = (Map.Entry)o;
Object key = entry.getKey();
Object value = entry.getValue();
if ((key == null) || (value == null)) return false;
return key.equals(getKey()) && value.equals(getValue());
}
public int hashCode() {
Object v = getValue();
return hash ^ ((v == null) ? 0 : v.hashCode());
}
public String toString() {
return getKey() + "=" + getValue();
}
boolean purge(Reference ref) {
boolean r = (keyType > HARD) && (key == ref);
r = r || ((valueType > HARD) && (value == ref));
if (r) {
if (keyType > HARD) ((Reference)key).clear();
if (valueType > HARD) {
((Reference)value).clear();
} else if (purgeValues) {
value = null;
}
}
return r;
}
}
private class EntryIterator implements Iterator {
// These fields keep track of where we are in the table.
int index;
Entry entry;
Entry previous;
// These Object fields provide hard references to the
// current and next entry; this assures that if hasNext()
// returns true, next() will actually return a valid element.
Object nextKey, nextValue;
Object currentKey, currentValue;
int expectedModCount;
public EntryIterator() {
index = (size() != 0 ? table.length : 0);
// have to do this here! size() invocation above
// may have altered the modCount.
expectedModCount = modCount;
}
public boolean hasNext() {
checkMod();
while (nextNull()) {
Entry e = entry;
int i = index;
while ((e == null) && (i > 0)) {
i--;
e = table[i];
}
entry = e;
index = i;
if (e == null) {
currentKey = null;
currentValue = null;
return false;
}
nextKey = e.getKey();
nextValue = e.getValue();
if (nextNull()) entry = entry.next;
}
return true;
}
private void checkMod() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
private boolean nextNull() {
return (nextKey == null) || (nextValue == null);
}
protected Entry nextEntry() {
checkMod();
if (nextNull() && !hasNext()) throw new NoSuchElementException();
previous = entry;
entry = entry.next;
currentKey = nextKey;
currentValue = nextValue;
nextKey = null;
nextValue = null;
return previous;
}
public Object next() {
return nextEntry();
}
public void remove() {
checkMod();
if (previous == null) throw new IllegalStateException();
ReferenceMap.this.remove(currentKey);
previous = null;
currentKey = null;
currentValue = null;
expectedModCount = modCount;
}
}
private class ValueIterator extends EntryIterator {
public Object next() {
return nextEntry().getValue();
}
}
private class KeyIterator extends EntryIterator {
public Object next() {
return nextEntry().getKey();
}
}
// These two classes store the hashCode of the key of
// of the mapping, so that after they're dequeued a quick
// lookup of the bucket in the table can occur.
private static class SoftRef extends SoftReference {
private int hash;
public SoftRef(int hash, Object r, ReferenceQueue q) {
super(r, q);
this.hash = hash;
}
public int hashCode() {
return hash;
}
}
private static class WeakRef extends WeakReference {
private int hash;
public WeakRef(int hash, Object r, ReferenceQueue q) {
super(r, q);
this.hash = hash;
}
public int hashCode() {
return hash;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,711 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* A StaticBucketMap is an efficient, thread-safe implementation of
* <code>java.util.Map</code> that performs well in in a highly
* thread-contentious environment. The map supports very efficient
* {@link #get(Object) get}, {@link #put(Object,Object) put},
* {@link #remove(Object) remove} and {@link #containsKey(Object) containsKey}
* operations, assuming (approximate) uniform hashing and
* that the number of entries does not exceed the number of buckets. If the
* number of entries exceeds the number of buckets or if the hash codes of the
* objects are not uniformly distributed, these operations have a worst case
* scenario that is proportional to the number of elements in the map
* (<i>O(n)</i>).<p>
*
* Each bucket in the hash table has its own monitor, so two threads can
* safely operate on the map at the same time, often without incurring any
* monitor contention. This means that you don't have to wrap instances
* of this class with {@link java.util.Collections#synchronizedMap(Map)};
* instances are already thread-safe. Unfortunately, however, this means
* that this map implementation behaves in ways you may find disconcerting.
* Bulk operations, such as {@link #putAll(Map) putAll} or the
* {@link Collection#retainAll(Collection) retainAll} operation in collection
* views, are <i>not</i> atomic. If two threads are simultaneously
* executing
*
* <pre>
* staticBucketMapInstance.putAll(map);
* </pre>
*
* and
*
* <pre>
* staticBucketMapInstance.entrySet().removeAll(map.entrySet());
* </pre>
*
* then the results are generally random. Those two statement could cancel
* each other out, leaving <code>staticBucketMapInstance</code> essentially
* unchanged, or they could leave some random subset of <code>map</code> in
* <code>staticBucketMapInstance</code>.<p>
*
* Also, much like an encyclopedia, the results of {@link #size()} and
* {@link #isEmpty()} are out-of-date as soon as they are produced.<p>
*
* The iterators returned by the collection views of this class are <i>not</i>
* fail-fast. They will <i>never</i> raise a
* {@link java.util.ConcurrentModificationException}. Keys and values
* added to the map after the iterator is created do not necessarily appear
* during iteration. Similarly, the iterator does not necessarily fail to
* return keys and values that were removed after the iterator was created.<p>
*
* Finally, unlike {@link java.util.HashMap}-style implementations, this
* class <i>never</i> rehashes the map. The number of buckets is fixed
* at construction time and never altered. Performance may degrade if
* you do not allocate enough buckets upfront.<p>
*
* The {@link #atomic(Runnable)} method is provided to allow atomic iterations
* and bulk operations; however, overuse of {@link #atomic(Runnable) atomic}
* will basically result in a map that's slower than an ordinary synchronized
* {@link java.util.HashMap}.
*
* Use this class if you do not require reliable bulk operations and
* iterations, or if you can make your own guarantees about how bulk
* operations will affect the map.<p>
*
* @deprecated Moved to map subpackage. Due to be removed in v4.0.
* @since Commons Collections 2.1
* @version $Revision$ $Date$
*
* @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
* @author <a href="mailto:g-froehlich@gmx.de">Gerhard Froehlich</a>
* @author <a href="mailto:mas@apache.org">Michael A. Smith</a>
* @author Paul Jack
* @author Leo Sutic
* @author Janek Bogucki
* @author Kazuya Ujihara
*/
public final class StaticBucketMap implements Map {
private static final int DEFAULT_BUCKETS = 255;
private Node[] m_buckets;
private Lock[] m_locks;
/**
* Initializes the map with the default number of buckets (255).
*/
public StaticBucketMap()
{
this( DEFAULT_BUCKETS );
}
/**
* Initializes the map with a specified number of buckets. The number
* of buckets is never below 17, and is always an odd number (StaticBucketMap
* ensures this). The number of buckets is inversely proportional to the
* chances for thread contention. The fewer buckets, the more chances for
* thread contention. The more buckets the fewer chances for thread
* contention.
*
* @param numBuckets the number of buckets for this map
*/
public StaticBucketMap( int numBuckets )
{
int size = Math.max( 17, numBuckets );
// Ensure that bucketSize is never a power of 2 (to ensure maximal distribution)
if( size % 2 == 0 )
{
size--;
}
m_buckets = new Node[ size ];
m_locks = new Lock[ size ];
for( int i = 0; i < size; i++ )
{
m_locks[ i ] = new Lock();
}
}
/**
* Determine the exact hash entry for the key. The hash algorithm
* is rather simplistic, but it does the job:
*
* <pre>
* He = |Hk mod n|
* </pre>
*
* <p>
* He is the entry's hashCode, Hk is the key's hashCode, and n is
* the number of buckets.
* </p>
*/
private final int getHash( Object key )
{
if( key == null ) return 0;
int hash = key.hashCode();
hash += ~(hash << 15);
hash ^= (hash >>> 10);
hash += (hash << 3);
hash ^= (hash >>> 6);
hash += ~(hash << 11);
hash ^= (hash >>> 16);
hash %= m_buckets.length;
return ( hash < 0 ) ? hash * -1 : hash;
}
/**
* Implements {@link Map#keySet()}.
*/
public Set keySet()
{
return new KeySet();
}
/**
* Implements {@link Map#size()}.
*/
public int size()
{
int cnt = 0;
for( int i = 0; i < m_buckets.length; i++ )
{
cnt += m_locks[i].size;
}
return cnt;
}
/**
* Implements {@link Map#put(Object, Object)}.
*/
public Object put( final Object key, final Object value )
{
int hash = getHash( key );
synchronized( m_locks[ hash ] )
{
Node n = m_buckets[ hash ];
if( n == null )
{
n = new Node();
n.key = key;
n.value = value;
m_buckets[ hash ] = n;
m_locks[hash].size++;
return null;
}
// Set n to the last node in the linked list. Check each key along the way
// If the key is found, then change the value of that node and return
// the old value.
for( Node next = n; next != null; next = next.next )
{
n = next;
if( n.key == key || ( n.key != null && n.key.equals( key ) ) )
{
Object returnVal = n.value;
n.value = value;
return returnVal;
}
}
// The key was not found in the current list of nodes, add it to the end
// in a new node.
Node newNode = new Node();
newNode.key = key;
newNode.value = value;
n.next = newNode;
m_locks[hash].size++;
}
return null;
}
/**
* Implements {@link Map#get(Object)}.
*/
public Object get( final Object key )
{
int hash = getHash( key );
synchronized( m_locks[ hash ] )
{
Node n = m_buckets[ hash ];
while( n != null )
{
if( n.key == key || ( n.key != null && n.key.equals( key ) ) )
{
return n.value;
}
n = n.next;
}
}
return null;
}
/**
* Implements {@link Map#containsKey(Object)}.
*/
public boolean containsKey( final Object key )
{
int hash = getHash( key );
synchronized( m_locks[ hash ] )
{
Node n = m_buckets[ hash ];
while( n != null )
{
if( n.key == key || ( n.key != null && n.key.equals( key ) ) )
{
return true;
}
n = n.next;
}
}
return false;
}
/**
* Implements {@link Map#containsValue(Object)}.
*/
public boolean containsValue( final Object value )
{
for( int i = 0; i < m_buckets.length; i++ )
{
synchronized( m_locks[ i ] )
{
Node n = m_buckets[ i ];
while( n != null )
{
if( n.value == value ||
(n.value != null && n.value.equals( value ) ) )
{
return true;
}
n = n.next;
}
}
}
return false;
}
/**
* Implements {@link Map#values()}.
*/
public Collection values()
{
return new Values();
}
/**
* Implements {@link Map#entrySet()}.
*/
public Set entrySet()
{
return new EntrySet();
}
/**
* Implements {@link Map#putAll(Map)}.
*/
public void putAll( Map other )
{
Iterator i = other.keySet().iterator();
while( i.hasNext() )
{
Object key = i.next();
put( key, other.get( key ) );
}
}
/**
* Implements {@link Map#remove(Object)}.
*/
public Object remove( Object key )
{
int hash = getHash( key );
synchronized( m_locks[ hash ] )
{
Node n = m_buckets[ hash ];
Node prev = null;
while( n != null )
{
if( n.key == key || ( n.key != null && n.key.equals( key ) ) )
{
// Remove this node from the linked list of nodes.
if( null == prev )
{
// This node was the head, set the next node to be the new head.
m_buckets[ hash ] = n.next;
}
else
{
// Set the next node of the previous node to be the node after this one.
prev.next = n.next;
}
m_locks[hash].size--;
return n.value;
}
prev = n;
n = n.next;
}
}
return null;
}
/**
* Implements {@link Map#isEmpty()}.
*/
public final boolean isEmpty()
{
return size() == 0;
}
/**
* Implements {@link Map#clear()}.
*/
public final void clear()
{
for( int i = 0; i < m_buckets.length; i++ )
{
Lock lock = m_locks[i];
synchronized (lock) {
m_buckets[ i ] = null;
lock.size = 0;
}
}
}
/**
* Implements {@link Map#equals(Object)}.
*/
public final boolean equals( Object obj )
{
if( obj == null ) return false;
if( obj == this ) return true;
if( !( obj instanceof Map ) ) return false;
Map other = (Map)obj;
return entrySet().equals(other.entrySet());
}
/**
* Implements {@link Map#hashCode()}.
*/
public final int hashCode()
{
int hashCode = 0;
for( int i = 0; i < m_buckets.length; i++ )
{
synchronized( m_locks[ i ] )
{
Node n = m_buckets[ i ];
while( n != null )
{
hashCode += n.hashCode();
n = n.next;
}
}
}
return hashCode;
}
/**
* The Map.Entry for the StaticBucketMap.
*/
private static final class Node implements Map.Entry, KeyValue
{
protected Object key;
protected Object value;
protected Node next;
public Object getKey()
{
return key;
}
public Object getValue()
{
return value;
}
public int hashCode()
{
return ( ( key == null ? 0 : key.hashCode() ) ^
( value == null ? 0 : value.hashCode() ) );
}
public boolean equals(Object o) {
if( o == null ) return false;
if( o == this ) return true;
if ( ! (o instanceof Map.Entry ) )
return false;
Map.Entry e2 = (Map.Entry)o;
return ((key == null ?
e2.getKey() == null : key.equals(e2.getKey())) &&
(value == null ?
e2.getValue() == null : value.equals(e2.getValue())));
}
public Object setValue( Object val )
{
Object retVal = value;
value = val;
return retVal;
}
}
private final static class Lock {
public int size;
}
private class EntryIterator implements Iterator {
private ArrayList current = new ArrayList();
private int bucket;
private Map.Entry last;
public boolean hasNext() {
if (current.size() > 0) return true;
while (bucket < m_buckets.length) {
synchronized (m_locks[bucket]) {
Node n = m_buckets[bucket];
while (n != null) {
current.add(n);
n = n.next;
}
bucket++;
if (current.size() > 0) return true;
}
}
return false;
}
protected Map.Entry nextEntry() {
if (!hasNext()) throw new NoSuchElementException();
last = (Map.Entry)current.remove(current.size() - 1);
return last;
}
public Object next() {
return nextEntry();
}
public void remove() {
if (last == null) throw new IllegalStateException();
StaticBucketMap.this.remove(last.getKey());
last = null;
}
}
private class ValueIterator extends EntryIterator {
public Object next() {
return nextEntry().getValue();
}
}
private class KeyIterator extends EntryIterator {
public Object next() {
return nextEntry().getKey();
}
}
private class EntrySet extends AbstractSet {
public int size() {
return StaticBucketMap.this.size();
}
public void clear() {
StaticBucketMap.this.clear();
}
public Iterator iterator() {
return new EntryIterator();
}
public boolean contains(Object o) {
Map.Entry entry = (Map.Entry)o;
int hash = getHash(entry.getKey());
synchronized (m_locks[hash]) {
for (Node n = m_buckets[hash]; n != null; n = n.next) {
if (n.equals(entry)) return true;
}
}
return false;
}
public boolean remove(Object obj) {
if (obj instanceof Map.Entry == false) {
return false;
}
Map.Entry entry = (Map.Entry) obj;
int hash = getHash(entry.getKey());
synchronized (m_locks[hash]) {
for (Node n = m_buckets[hash]; n != null; n = n.next) {
if (n.equals(entry)) {
StaticBucketMap.this.remove(n.getKey());
return true;
}
}
}
return false;
}
}
private class KeySet extends AbstractSet {
public int size() {
return StaticBucketMap.this.size();
}
public void clear() {
StaticBucketMap.this.clear();
}
public Iterator iterator() {
return new KeyIterator();
}
public boolean contains(Object o) {
return StaticBucketMap.this.containsKey(o);
}
public boolean remove(Object o) {
int hash = getHash(o);
synchronized (m_locks[hash]) {
for (Node n = m_buckets[hash]; n != null; n = n.next) {
Object k = n.getKey();
if ((k == o) || ((k != null) && k.equals(o))) {
StaticBucketMap.this.remove(k);
return true;
}
}
}
return false;
}
}
private class Values extends AbstractCollection {
public int size() {
return StaticBucketMap.this.size();
}
public void clear() {
StaticBucketMap.this.clear();
}
public Iterator iterator() {
return new ValueIterator();
}
}
/**
* Prevents any operations from occurring on this map while the
* given {@link Runnable} executes. This method can be used, for
* instance, to execute a bulk operation atomically:
*
* <pre>
* staticBucketMapInstance.atomic(new Runnable() {
* public void run() {
* staticBucketMapInstance.putAll(map);
* }
* });
* </pre>
*
* It can also be used if you need a reliable iterator:
*
* <pre>
* staticBucketMapInstance.atomic(new Runnable() {
* public void run() {
* Iterator iterator = staticBucketMapInstance.iterator();
* while (iterator.hasNext()) {
* foo(iterator.next();
* }
* }
* });
* </pre>
*
* <B>Implementation note:</B> This method requires a lot of time
* and a ton of stack space. Essentially a recursive algorithm is used
* to enter each bucket's monitor. If you have twenty thousand buckets
* in your map, then the recursive method will be invoked twenty thousand
* times. You have been warned.
*
* @param r the code to execute atomically
*/
public void atomic(Runnable r) {
if (r == null) throw new NullPointerException();
atomic(r, 0);
}
private void atomic(Runnable r, int bucket) {
if (bucket >= m_buckets.length) {
r.run();
return;
}
synchronized (m_locks[bucket]) {
atomic(r, bucket + 1);
}
}
}

View File

@ -1,103 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.NoSuchElementException;
/**
* A thread safe version of the PriorityQueue.
* Provides synchronized wrapper methods for all the methods
* defined in the PriorityQueue interface.
*
* @deprecated PriorityQueue is replaced by the Buffer interface, see buffer subpackage.
* Due to be removed in v4.0.
* @since Commons Collections 1.0
* @version $Revision$ $Date$
*
* @author Ram Chidambaram
*/
public final class SynchronizedPriorityQueue implements PriorityQueue {
/**
* The underlying priority queue.
*/
protected final PriorityQueue m_priorityQueue;
/**
* Constructs a new synchronized priority queue.
*
* @param priorityQueue the priority queue to synchronize
*/
public SynchronizedPriorityQueue(final PriorityQueue priorityQueue) {
m_priorityQueue = priorityQueue;
}
/**
* Clear all elements from queue.
*/
public synchronized void clear() {
m_priorityQueue.clear();
}
/**
* Test if queue is empty.
*
* @return true if queue is empty else false.
*/
public synchronized boolean isEmpty() {
return m_priorityQueue.isEmpty();
}
/**
* Insert an element into queue.
*
* @param element the element to be inserted
*/
public synchronized void insert(final Object element) {
m_priorityQueue.insert(element);
}
/**
* Return element on top of heap but don't remove it.
*
* @return the element at top of heap
* @throws NoSuchElementException if isEmpty() == true
*/
public synchronized Object peek() throws NoSuchElementException {
return m_priorityQueue.peek();
}
/**
* Return element on top of heap and remove it.
*
* @return the element at top of heap
* @throws NoSuchElementException if isEmpty() == true
*/
public synchronized Object pop() throws NoSuchElementException {
return m_priorityQueue.pop();
}
/**
* Returns a string representation of the underlying queue.
*
* @return a string representation of the underlying queue
*/
public synchronized String toString() {
return m_priorityQueue.toString();
}
}

View File

@ -1,77 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.Collection;
import java.util.Comparator;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* A {@link Bag} that is backed by a {@link TreeMap}.
* Order will be maintained among the unique representative
* members.
*
* @deprecated Moved to bag subpackage and rewritten internally. Due to be removed in v4.0.
* @since Commons Collections 2.0
* @version $Revision$ $Date$
*
* @author Chuck Burdick
*/
public class TreeBag extends DefaultMapBag implements SortedBag {
/**
* Constructs an empty <code>TreeBag</code>.
*/
public TreeBag() {
super(new TreeMap());
}
/**
* Constructs an empty {@link Bag} that maintains order on its unique
* representative members according to the given {@link Comparator}.
*
* @param comparator the comparator to use
*/
public TreeBag(Comparator comparator) {
super(new TreeMap(comparator));
}
/**
* Constructs a {@link Bag} containing all the members of the given
* collection.
*
* @param coll the collection to copy into the bag
*/
public TreeBag(Collection coll) {
this();
addAll(coll);
}
public Object first() {
return ((SortedMap) getMap()).firstKey();
}
public Object last() {
return ((SortedMap) getMap()).lastKey();
}
public Comparator comparator() {
return ((SortedMap) getMap()).comparator();
}
}

View File

@ -1,274 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.AbstractCollection;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* UnboundedFifoBuffer is a very efficient buffer implementation.
* According to performance testing, it exhibits a constant access time, but it
* also outperforms ArrayList when used for the same purpose.
* <p>
* The removal order of an <code>UnboundedFifoBuffer</code> is based on the insertion
* order; elements are removed in the same order in which they were added.
* The iteration order is the same as the removal order.
* <p>
* The {@link #remove()} and {@link #get()} operations perform in constant time.
* The {@link #add(Object)} operation performs in amortized constant time. All
* other operations perform in linear time or worse.
* <p>
* Note that this implementation is not synchronized. The following can be
* used to provide synchronized access to your <code>UnboundedFifoBuffer</code>:
* <pre>
* Buffer fifo = BufferUtils.synchronizedBuffer(new UnboundedFifoBuffer());
* </pre>
* <p>
* This buffer prevents null objects from being added.
*
* @deprecated Moved to buffer subpackage. Due to be removed in v4.0.
* @since Commons Collections 2.1
* @version $Revision$ $Date$
*
* @author Avalon
* @author Federico Barbieri
* @author Berin Loritsch
* @author Paul Jack
* @author Stephen Colebourne
* @author Andreas Schlosser
*/
public class UnboundedFifoBuffer extends AbstractCollection implements Buffer {
protected Object[] m_buffer;
protected int m_head;
protected int m_tail;
/**
* Constructs an UnboundedFifoBuffer with the default number of elements.
* It is exactly the same as performing the following:
*
* <pre>
* new UnboundedFifoBuffer(32);
* </pre>
*/
public UnboundedFifoBuffer() {
this(32);
}
/**
* Constructs an UnboundedFifoBuffer with the specified number of elements.
* The integer must be a positive integer.
*
* @param initialSize the initial size of the buffer
* @throws IllegalArgumentException if the size is less than 1
*/
public UnboundedFifoBuffer(int initialSize) {
if (initialSize <= 0) {
throw new IllegalArgumentException("The size must be greater than 0");
}
m_buffer = new Object[initialSize + 1];
m_head = 0;
m_tail = 0;
}
/**
* Returns the number of elements stored in the buffer.
*
* @return this buffer's size
*/
public int size() {
int size = 0;
if (m_tail < m_head) {
size = m_buffer.length - m_head + m_tail;
} else {
size = m_tail - m_head;
}
return size;
}
/**
* Returns true if this buffer is empty; false otherwise.
*
* @return true if this buffer is empty
*/
public boolean isEmpty() {
return (size() == 0);
}
/**
* Adds the given element to this buffer.
*
* @param obj the element to add
* @return true, always
* @throws NullPointerException if the given element is null
* @throws BufferOverflowException if this buffer is full
*/
public boolean add(final Object obj) {
if (obj == null) {
throw new NullPointerException("Attempted to add null object to buffer");
}
if (size() + 1 >= m_buffer.length) {
Object[] tmp = new Object[((m_buffer.length - 1) * 2) + 1];
int j = 0;
for (int i = m_head; i != m_tail;) {
tmp[j] = m_buffer[i];
m_buffer[i] = null;
j++;
i++;
if (i == m_buffer.length) {
i = 0;
}
}
m_buffer = tmp;
m_head = 0;
m_tail = j;
}
m_buffer[m_tail] = obj;
m_tail++;
if (m_tail >= m_buffer.length) {
m_tail = 0;
}
return true;
}
/**
* Returns the next object in the buffer.
*
* @return the next object in the buffer
* @throws BufferUnderflowException if this buffer is empty
*/
public Object get() {
if (isEmpty()) {
throw new BufferUnderflowException("The buffer is already empty");
}
return m_buffer[m_head];
}
/**
* Removes the next object from the buffer
*
* @return the removed object
* @throws BufferUnderflowException if this buffer is empty
*/
public Object remove() {
if (isEmpty()) {
throw new BufferUnderflowException("The buffer is already empty");
}
Object element = m_buffer[m_head];
if (null != element) {
m_buffer[m_head] = null;
m_head++;
if (m_head >= m_buffer.length) {
m_head = 0;
}
}
return element;
}
/**
* Increments the internal index.
*
* @param index the index to increment
* @return the updated index
*/
private int increment(int index) {
index++;
if (index >= m_buffer.length) {
index = 0;
}
return index;
}
/**
* Decrements the internal index.
*
* @param index the index to decrement
* @return the updated index
*/
private int decrement(int index) {
index--;
if (index < 0) {
index = m_buffer.length - 1;
}
return index;
}
/**
* Returns an iterator over this buffer's elements.
*
* @return an iterator over this buffer's elements
*/
public Iterator iterator() {
return new Iterator() {
private int index = m_head;
private int lastReturnedIndex = -1;
public boolean hasNext() {
return index != m_tail;
}
public Object next() {
if (!hasNext())
throw new NoSuchElementException();
lastReturnedIndex = index;
index = increment(index);
return m_buffer[lastReturnedIndex];
}
public void remove() {
if (lastReturnedIndex == -1)
throw new IllegalStateException();
// First element can be removed quickly
if (lastReturnedIndex == m_head) {
UnboundedFifoBuffer.this.remove();
lastReturnedIndex = -1;
return;
}
// Other elements require us to shift the subsequent elements
int i = increment(lastReturnedIndex);
while (i != m_tail) {
m_buffer[decrement(i)] = m_buffer[i];
i = increment(i);
}
lastReturnedIndex = -1;
m_tail = decrement(m_tail);
m_buffer[m_tail] = null;
index = decrement(index);
}
};
}
}

View File

@ -1,102 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections.iterators;
import java.util.Iterator;
/**
* A Proxy {@link Iterator Iterator} which delegates its methods to a proxy instance.
*
* @deprecated Use AbstractIteratorDecorator. Will be removed in v4.0
* @since Commons Collections 1.0
* @version $Revision$ $Date$
*
* @author James Strachan
*/
public class ProxyIterator implements Iterator {
/** Holds value of property iterator. */
private Iterator iterator;
// Constructors
//-------------------------------------------------------------------------
/**
* Constructs a new <code>ProxyIterator</code> that will not function
* until {@link #setIterator(Iterator)} is called.
*/
public ProxyIterator() {
super();
}
/**
* Constructs a new <code>ProxyIterator</code> that will use the
* given iterator.
*
* @param iterator the underlying iterator
*/
public ProxyIterator(Iterator iterator) {
super();
this.iterator = iterator;
}
// Iterator interface
//-------------------------------------------------------------------------
/**
* Returns true if the underlying iterator has more elements.
*
* @return true if the underlying iterator has more elements
*/
public boolean hasNext() {
return getIterator().hasNext();
}
/**
* Returns the next element from the underlying iterator.
*
* @return the next element from the underlying iterator
* @throws java.util.NoSuchElementException if the underlying iterator
* raises it because it has no more elements
*/
public Object next() {
return getIterator().next();
}
/**
* Removes the last returned element from the collection that spawned
* the underlying iterator.
*/
public void remove() {
getIterator().remove();
}
// Properties
//-------------------------------------------------------------------------
/** Getter for property iterator.
* @return Value of property iterator.
*/
public Iterator getIterator() {
return iterator;
}
/** Setter for property iterator.
* @param iterator New value of property iterator.
*/
public void setIterator(Iterator iterator) {
this.iterator = iterator;
}
}

View File

@ -1,163 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections.iterators;
import java.util.ListIterator;
/**
* A proxy {@link ListIterator ListIterator} which delegates its
* methods to a proxy instance.
*
* @deprecated Use AbstractListIteratorDecorator. Will be removed in v4.0
* @since Commons Collections 2.0
* @version $Revision$ $Date$
*
* @author Rodney Waldhoff
*/
public class ProxyListIterator implements ListIterator {
/** Holds value of property "iterator". */
private ListIterator iterator;
// Constructors
//-------------------------------------------------------------------------
/**
* Constructs a new <code>ProxyListIterator</code> that will not
* function until {@link #setListIterator(ListIterator) setListIterator}
* is invoked.
*/
public ProxyListIterator() {
super();
}
/**
* Constructs a new <code>ProxyListIterator</code> that will use the
* given list iterator.
*
* @param iterator the list iterator to use
*/
public ProxyListIterator(ListIterator iterator) {
super();
this.iterator = iterator;
}
// ListIterator interface
//-------------------------------------------------------------------------
/**
* Invokes the underlying {@link ListIterator#add(Object)} method.
*
* @throws NullPointerException if the underlying iterator is null
*/
public void add(Object o) {
getListIterator().add(o);
}
/**
* Invokes the underlying {@link ListIterator#hasNext()} method.
*
* @throws NullPointerException if the underlying iterator is null
*/
public boolean hasNext() {
return getListIterator().hasNext();
}
/**
* Invokes the underlying {@link ListIterator#hasPrevious()} method.
*
* @throws NullPointerException if the underlying iterator is null
*/
public boolean hasPrevious() {
return getListIterator().hasPrevious();
}
/**
* Invokes the underlying {@link ListIterator#next()} method.
*
* @throws NullPointerException if the underlying iterator is null
*/
public Object next() {
return getListIterator().next();
}
/**
* Invokes the underlying {@link ListIterator#nextIndex()} method.
*
* @throws NullPointerException if the underlying iterator is null
*/
public int nextIndex() {
return getListIterator().nextIndex();
}
/**
* Invokes the underlying {@link ListIterator#previous()} method.
*
* @throws NullPointerException if the underlying iterator is null
*/
public Object previous() {
return getListIterator().previous();
}
/**
* Invokes the underlying {@link ListIterator#previousIndex()} method.
*
* @throws NullPointerException if the underlying iterator is null
*/
public int previousIndex() {
return getListIterator().previousIndex();
}
/**
* Invokes the underlying {@link ListIterator#remove()} method.
*
* @throws NullPointerException if the underlying iterator is null
*/
public void remove() {
getListIterator().remove();
}
/**
* Invokes the underlying {@link ListIterator#set(Object)} method.
*
* @throws NullPointerException if the underlying iterator is null
*/
public void set(Object o) {
getListIterator().set(o);
}
// Properties
//-------------------------------------------------------------------------
/**
* Getter for property iterator.
* @return Value of property iterator.
*/
public ListIterator getListIterator() {
return iterator;
}
/**
* Setter for property iterator.
* @param iterator New value of property iterator.
*/
public void setListIterator(ListIterator iterator) {
this.iterator = iterator;
}
}

View File

@ -54,7 +54,6 @@ public class MapPerformance {
Map unmodHashMap = Collections.unmodifiableMap(new HashMap(hashMap));
Map fastHashMap = new FastHashMap(hashMap);
Map treeMap = new TreeMap(hashMap);
Map seqMap = new SequencedHashMap(hashMap);
// Map linkedMap = new LinkedHashMap(hashMap);
// Map syncMap = Collections.unmodifiableMap(new HashMap(hashMap));
// Map bucketMap = new StaticBucketMap();

View File

@ -41,6 +41,7 @@ public class TestAll extends TestCase {
suite.addTest(TestBufferUtils.suite());
suite.addTest(TestEnumerationUtils.suite());
suite.addTest(TestFactoryUtils.suite());
suite.addTest(TestIteratorUtils.suite());
suite.addTest(TestListUtils.suite());
suite.addTest(TestMapUtils.suite());
suite.addTest(TestPredicateUtils.suite());
@ -48,12 +49,6 @@ public class TestAll extends TestCase {
suite.addTest(TestTransformerUtils.suite());
suite.addTest(TestArrayStack.suite());
suite.addTest(TestBeanMap.suite());
suite.addTest(TestBinaryHeap.suite());
suite.addTest(TestBoundedFifoBuffer.suite());
suite.addTest(TestBoundedFifoBuffer2.suite());
suite.addTest(TestCursorableLinkedList.suite());
suite.addTest(TestDoubleOrderedMap.suite());
suite.addTest(TestExtendedProperties.suite());
suite.addTest(TestFastArrayList.suite());
suite.addTest(TestFastArrayList1.suite());
@ -61,15 +56,6 @@ public class TestAll extends TestCase {
suite.addTest(TestFastHashMap1.suite());
suite.addTest(TestFastTreeMap.suite());
suite.addTest(TestFastTreeMap1.suite());
suite.addTest(TestHashBag.suite());
suite.addTest(TestIteratorUtils.suite());
suite.addTest(TestLRUMap.suite());
suite.addTest(TestMultiHashMap.suite());
suite.addTest(TestReferenceMap.suite());
suite.addTest(TestSequencedHashMap.suite());
suite.addTest(TestStaticBucketMap.suite());
suite.addTest(TestTreeBag.suite());
suite.addTest(TestUnboundedFifoBuffer.suite());
return suite;
}

View File

@ -1,344 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Map;
import junit.framework.Test;
import junit.textui.TestRunner;
import org.apache.commons.collections.map.AbstractTestMap;
/**
* Test cases for BeanMap
*
* @version $Revision$ $Date$
*
* @author Morgan Delagrange
* @author Stephen Colebourne
*/
public class TestBeanMap extends AbstractTestMap {
public TestBeanMap(String testName) {
super(testName);
}
public static void main(String[] args) {
TestRunner.run(suite());
}
public static Test suite() {
return BulkTest.makeSuite(TestBeanMap.class);
}
/*
note to self. The getter and setter methods were generated by copying the
field declarations and using the following regular expression search and
replace:
From:
private \(.*\) some\(.*\);
To:
public \1 getSome\2Value() {
return some\2;
}
public void setSome\2Value(\1 value) {
some\2 = value;
}
Also note: The sample keys and mappings were generated manually.
*/
public static class BeanWithProperties implements Serializable {
private int someInt;
private long someLong;
private double someDouble;
private float someFloat;
private short someShort;
private byte someByte;
private char someChar;
private Integer someInteger;
private String someString;
private Object someObject;
public int getSomeIntValue() {
return someInt;
}
public void setSomeIntValue(int value) {
someInt = value;
}
public long getSomeLongValue() {
return someLong;
}
public void setSomeLongValue(long value) {
someLong = value;
}
public double getSomeDoubleValue() {
return someDouble;
}
public void setSomeDoubleValue(double value) {
someDouble = value;
}
public float getSomeFloatValue() {
return someFloat;
}
public void setSomeFloatValue(float value) {
someFloat = value;
}
public short getSomeShortValue() {
return someShort;
}
public void setSomeShortValue(short value) {
someShort = value;
}
public byte getSomeByteValue() {
return someByte;
}
public void setSomeByteValue(byte value) {
someByte = value;
}
public char getSomeCharValue() {
return someChar;
}
public void setSomeCharValue(char value) {
someChar = value;
}
public String getSomeStringValue() {
return someString;
}
public void setSomeStringValue(String value) {
someString = value;
}
public Integer getSomeIntegerValue() {
return someInteger;
}
public void setSomeIntegerValue(Integer value) {
someInteger = value;
}
public Object getSomeObjectValue() {
return someObject;
}
public void setSomeObjectValue(Object value) {
someObject = value;
}
}
// note to self. The Sample keys were generated by copying the field
// declarations and using the following regular expression search and replace:
//
// From:
// private \(.*\) some\(.*\);
// To:
// "some\2Value",
//
// Then, I manually added the "class" key, which is a property that exists for
// all beans (and all objects for that matter.
public Object[] getSampleKeys() {
Object[] keys = new Object[] {
"someIntValue",
"someLongValue",
"someDoubleValue",
"someFloatValue",
"someShortValue",
"someByteValue",
"someCharValue",
"someIntegerValue",
"someStringValue",
"someObjectValue",
"class",
};
return keys;
}
/**
* An object value that will be stored in the bean map as a value. Need
* to save this externally so that we can make sure the object instances
* are equivalent since getSampleValues() would otherwise construct a new
* and different Object each time.
**/
private Object objectInFullMap = new Object();
// note to self: the sample values were created manually
public Object[] getSampleValues() {
Object[] values = new Object[] {
new Integer(1234),
new Long(1298341928234L),
new Double(123423.34),
new Float(1213332.12f),
new Short((short)134),
new Byte((byte)10),
new Character('a'),
new Integer(1432),
"SomeStringValue",
objectInFullMap,
BeanWithProperties.class,
};
return values;
}
public Object[] getNewSampleValues() {
Object[] values = new Object[] {
new Integer(223),
new Long(23341928234L),
new Double(23423.34),
new Float(213332.12f),
new Short((short)234),
new Byte((byte)20),
new Character('b'),
new Integer(232),
"SomeNewStringValue",
new Object(),
null,
};
return values;
}
/**
* Values is a dead copy in BeanMap, so refresh each time.
*/
public void verifyValues() {
values = map.values();
super.verifyValues();
}
/**
* The mappings in a BeanMap are fixed on the properties the underlying
* bean has. Adding and removing mappings is not possible, thus this
* method is overridden to return false.
*/
public boolean isPutAddSupported() {
return false;
}
/**
* The mappings in a BeanMap are fixed on the properties the underlying
* bean has. Adding and removing mappings is not possible, thus this
* method is overridden to return false.
*/
public boolean isRemoveSupported() {
return false;
}
public Map makeFullMap() {
// note: These values must match (i.e. .equals() must return true)
// those returned from getSampleValues().
BeanWithProperties bean = new BeanWithProperties();
bean.setSomeIntValue(1234);
bean.setSomeLongValue(1298341928234L);
bean.setSomeDoubleValue(123423.34);
bean.setSomeFloatValue(1213332.12f);
bean.setSomeShortValue((short)134);
bean.setSomeByteValue((byte)10);
bean.setSomeCharValue('a');
bean.setSomeIntegerValue(new Integer(1432));
bean.setSomeStringValue("SomeStringValue");
bean.setSomeObjectValue(objectInFullMap);
return new BeanMap(bean);
}
public Map makeEmptyMap() {
return new BeanMap();
}
public String[] ignoredTests() {
// Ignore the serialization tests on collection views.
return new String[] {
"TestBeanMap.bulkTestMapEntrySet.testCanonicalEmptyCollectionExists",
"TestBeanMap.bulkTestMapEntrySet.testCanonicalFullCollectionExists",
"TestBeanMap.bulkTestMapKeySet.testCanonicalEmptyCollectionExists",
"TestBeanMap.bulkTestMapKeySet.testCanonicalFullCollectionExists",
"TestBeanMap.bulkTestMapValues.testCanonicalEmptyCollectionExists",
"TestBeanMap.bulkTestMapValues.testCanonicalFullCollectionExists",
"TestBeanMap.bulkTestMapEntrySet.testSimpleSerialization",
"TestBeanMap.bulkTestMapKeySet.testSimpleSerialization",
"TestBeanMap.bulkTestMapEntrySet.testSerializeDeserializeThenCompare",
"TestBeanMap.bulkTestMapKeySet.testSerializeDeserializeThenCompare"
};
}
/**
* Need to override this method because the "clear()" method on the bean
* map just returns the bean properties to their default states. It does
* not actually remove the mappings as per the map contract. The default
* testClear() methods checks that the clear method throws an
* UnsupportedOperationException since this class is not add/remove
* modifiable. In our case though, we do not always throw that exception.
*/
public void testMapClear() {
//TODO: make sure a call to BeanMap.clear returns the bean to its
//default initialization values.
}
/**
* Need to override this method because the "put()" method on the bean
* doesn't work for this type of Map.
*/
public void testMapPut() {
// see testBeanMapPutAllWriteable
}
public void testBeanMapClone() {
BeanMap map = (BeanMap)makeFullMap();
try {
BeanMap map2 = (BeanMap)((BeanMap)map).clone();
// make sure containsKey is working to verify the bean was cloned
// ok, and the read methods were properly initialized
Object[] keys = getSampleKeys();
for(int i = 0; i < keys.length; i++) {
assertTrue("Cloned BeanMap should contain the same keys",
map2.containsKey(keys[i]));
}
} catch (CloneNotSupportedException exception) {
fail("BeanMap.clone() should not throw a " +
"CloneNotSupportedException when clone should succeed.");
}
}
public void testBeanMapPutAllWriteable() {
BeanMap map1 = (BeanMap)makeFullMap();
BeanMap map2 = (BeanMap)makeFullMap();
map2.put("someIntValue", new Integer(0));
map1.putAllWriteable(map2);
assertEquals(map1.get("someIntValue"), new Integer(0));
}
public void testMethodAccessor() throws Exception {
BeanMap map = (BeanMap) makeFullMap();
Method method = BeanWithProperties.class.getDeclaredMethod("getSomeIntegerValue", (Class[]) null);
assertEquals(method, map.getReadMethod("someIntegerValue"));
}
public void testMethodMutator() throws Exception {
BeanMap map = (BeanMap) makeFullMap();
Method method = BeanWithProperties.class.getDeclaredMethod("setSomeIntegerValue", new Class[] {Integer.class});
assertEquals(method, map.getWriteMethod("someIntegerValue"));
}
}

View File

@ -1,344 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.NoSuchElementException;
import java.util.Random;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.collections.collection.AbstractTestCollection;
import org.apache.commons.collections.comparators.ComparableComparator;
import org.apache.commons.collections.comparators.ReverseComparator;
/**
* Tests the BinaryHeap.
*
* @version $Revision$ $Date$
*
* @author Michael A. Smith
*/
public class TestBinaryHeap extends AbstractTestCollection {
public static Test suite() {
return new TestSuite(TestBinaryHeap.class);
}
public TestBinaryHeap(String testName) {
super(testName);
}
//-----------------------------------------------------------------------
public void verify() {
super.verify();
BinaryHeap heap = (BinaryHeap) collection;
Comparator c = heap.m_comparator;
if (c == null)
c = ComparatorUtils.naturalComparator();
if (!heap.m_isMinHeap)
c = ComparatorUtils.reversedComparator(c);
Object[] tree = heap.m_elements;
for (int i = 1; i <= heap.m_size; i++) {
Object parent = tree[i];
if (i * 2 <= heap.m_size) {
assertTrue("Parent is less than or equal to its left child", c.compare(parent, tree[i * 2]) <= 0);
}
if (i * 2 + 1 < heap.m_size) {
assertTrue("Parent is less than or equal to its right child", c.compare(parent, tree[i * 2 + 1]) <= 0);
}
}
}
//-----------------------------------------------------------------------
/**
* Overridden because UnboundedFifoBuffer isn't fail fast.
* @return false
*/
public boolean isFailFastSupported() {
return false;
}
//-----------------------------------------------------------------------
public Collection makeConfirmedCollection() {
return new ArrayList();
}
public Collection makeConfirmedFullCollection() {
ArrayList list = new ArrayList();
list.addAll(Arrays.asList(getFullElements()));
return list;
}
/**
* Return a new, empty {@link Object} to used for testing.
*/
public Collection makeCollection() {
return new BinaryHeap();
}
//-----------------------------------------------------------------------
public Object[] getFullElements() {
return getFullNonNullStringElements();
}
public Object[] getOtherElements() {
return getOtherNonNullStringElements();
}
//-----------------------------------------------------------------------
public void testBasicOps() {
BinaryHeap heap = new BinaryHeap();
assertTrue("heap should be empty after create", heap.isEmpty());
try {
heap.peek();
fail("NoSuchElementException should be thrown if peek is called before any elements are inserted");
} catch (NoSuchElementException e) {
// expected
}
try {
heap.pop();
fail("NoSuchElementException should be thrown if pop is called before any elements are inserted");
} catch (NoSuchElementException e) {
// expected
}
heap.insert("a");
heap.insert("c");
heap.insert("e");
heap.insert("b");
heap.insert("d");
heap.insert("n");
heap.insert("m");
heap.insert("l");
heap.insert("k");
heap.insert("j");
heap.insert("i");
heap.insert("h");
heap.insert("g");
heap.insert("f");
assertTrue("heap should not be empty after inserts", !heap.isEmpty());
for (int i = 0; i < 14; i++) {
assertEquals(
"peek using default constructor should return minimum value in the binary heap",
String.valueOf((char) ('a' + i)),
heap.peek());
assertEquals(
"pop using default constructor should return minimum value in the binary heap",
String.valueOf((char) ('a' + i)),
heap.pop());
if (i + 1 < 14) {
assertTrue("heap should not be empty before all elements are popped", !heap.isEmpty());
} else {
assertTrue("heap should be empty after all elements are popped", heap.isEmpty());
}
}
try {
heap.peek();
fail("NoSuchElementException should be thrown if peek is called after all elements are popped");
} catch (NoSuchElementException e) {
// expected
}
try {
heap.pop();
fail("NoSuchElementException should be thrown if pop is called after all elements are popped");
} catch (NoSuchElementException e) {
// expected
}
}
public void testBasicComparatorOps() {
BinaryHeap heap = new BinaryHeap(new ReverseComparator(new ComparableComparator()));
assertTrue("heap should be empty after create", heap.isEmpty());
try {
heap.peek();
fail("NoSuchElementException should be thrown if peek is called before any elements are inserted");
} catch (NoSuchElementException e) {
// expected
}
try {
heap.pop();
fail("NoSuchElementException should be thrown if pop is called before any elements are inserted");
} catch (NoSuchElementException e) {
// expected
}
heap.insert("a");
heap.insert("c");
heap.insert("e");
heap.insert("b");
heap.insert("d");
heap.insert("n");
heap.insert("m");
heap.insert("l");
heap.insert("k");
heap.insert("j");
heap.insert("i");
heap.insert("h");
heap.insert("g");
heap.insert("f");
assertTrue("heap should not be empty after inserts", !heap.isEmpty());
for (int i = 0; i < 14; i++) {
// note: since we're using a comparator that reverses items, the
// "minimum" item is "n", and the "maximum" item is "a".
assertEquals(
"peek using default constructor should return minimum value in the binary heap",
String.valueOf((char) ('n' - i)),
heap.peek());
assertEquals(
"pop using default constructor should return minimum value in the binary heap",
String.valueOf((char) ('n' - i)),
heap.pop());
if (i + 1 < 14) {
assertTrue("heap should not be empty before all elements are popped", !heap.isEmpty());
} else {
assertTrue("heap should be empty after all elements are popped", heap.isEmpty());
}
}
try {
heap.peek();
fail("NoSuchElementException should be thrown if peek is called after all elements are popped");
} catch (NoSuchElementException e) {
// expected
}
try {
heap.pop();
fail("NoSuchElementException should be thrown if pop is called after all elements are popped");
} catch (NoSuchElementException e) {
// expected
}
}
/**
* Illustrates bad internal heap state reported in Bugzilla PR #235818.
*/
public void testAddRemove() {
resetEmpty();
BinaryHeap heap = (BinaryHeap) collection;
heap.add(new Integer(0));
heap.add(new Integer(2));
heap.add(new Integer(4));
heap.add(new Integer(3));
heap.add(new Integer(8));
heap.add(new Integer(10));
heap.add(new Integer(12));
heap.add(new Integer(3));
confirmed.addAll(heap);
// System.out.println(heap);
Object obj = new Integer(10);
heap.remove(obj);
confirmed.remove(obj);
// System.out.println(heap);
verify();
}
/**
* Generate heaps staring with Integers from 0 - heapSize - 1.
* Then perform random add / remove operations, checking
* heap order after modifications. Alternates minHeaps, maxHeaps.
*
* Based on code provided by Steve Phelps in PR #25818
*
*/
public void testRandom() {
int iterations = 500;
int heapSize = 100;
int operations = 20;
Random randGenerator = new Random();
BinaryHeap h = null;
for(int i=0; i < iterations; i++) {
if (i < iterations / 2) {
h = new BinaryHeap(true);
} else {
h = new BinaryHeap(false);
}
for(int r = 0; r < heapSize; r++) {
h.add( new Integer( randGenerator.nextInt(heapSize)) );
}
for( int r = 0; r < operations; r++ ) {
h.remove(new Integer(r));
h.add(new Integer(randGenerator.nextInt(heapSize)));
}
checkOrder(h);
}
}
/**
* Pops all elements from the heap and verifies that the elements come off
* in the correct order. NOTE: this method empties the heap.
*/
protected void checkOrder(BinaryHeap h) {
Integer lastNum = null;
Integer num = null;
boolean fail = false;
while (!h.isEmpty()) {
num = (Integer) h.pop();
if (h.m_isMinHeap) {
assertTrue(lastNum == null || num.intValue() >= lastNum.intValue());
} else { // max heap
assertTrue(lastNum == null || num.intValue() <= lastNum.intValue());
}
lastNum = num;
num = null;
}
}
/**
* Returns a string showing the contents of the heap formatted as a tree.
* Makes no attempt at padding levels or handling wrapping.
*/
protected String showTree(BinaryHeap h) {
int count = 1;
StringBuffer buffer = new StringBuffer();
for (int offset = 1; count < h.size() + 1; offset *= 2) {
for (int i = offset; i < offset * 2; i++) {
if (i < h.m_elements.length && h.m_elements[i] != null)
buffer.append(h.m_elements[i] + " ");
count++;
}
buffer.append('\n');
}
return buffer.toString();
}
}

View File

@ -1,166 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import junit.framework.Test;
import org.apache.commons.collections.collection.AbstractTestCollection;
/**
* Test cases for BoundedFifoBuffer.
*
* @version $Revision$ $Date$
*
* @author Paul Jack
*/
public class TestBoundedFifoBuffer extends AbstractTestCollection {
public TestBoundedFifoBuffer(String n) {
super(n);
}
public static Test suite() {
return BulkTest.makeSuite(TestBoundedFifoBuffer.class);
}
//-----------------------------------------------------------------------
/**
* Runs through the regular verifications, but also verifies that
* the buffer contains the same elements in the same sequence as the
* list.
*/
public void verify() {
super.verify();
Iterator iterator1 = collection.iterator();
Iterator iterator2 = confirmed.iterator();
while (iterator2.hasNext()) {
assertTrue(iterator1.hasNext());
Object o1 = iterator1.next();
Object o2 = iterator2.next();
assertEquals(o1, o2);
}
}
//-----------------------------------------------------------------------
/**
* Overridden because UnboundedFifoBuffer doesn't allow null elements.
* @return false
*/
public boolean isNullSupported() {
return false;
}
/**
* Overridden because UnboundedFifoBuffer isn't fail fast.
* @return false
*/
public boolean isFailFastSupported() {
return false;
}
//-----------------------------------------------------------------------
/**
* Returns an empty ArrayList.
*
* @return an empty ArrayList
*/
public Collection makeConfirmedCollection() {
return new ArrayList();
}
/**
* Returns a full ArrayList.
*
* @return a full ArrayList
*/
public Collection makeConfirmedFullCollection() {
Collection c = makeConfirmedCollection();
c.addAll(java.util.Arrays.asList(getFullElements()));
return c;
}
/**
* Returns an empty BoundedFifoBuffer that won't overflow.
*
* @return an empty BoundedFifoBuffer
*/
public Collection makeCollection() {
return new BoundedFifoBuffer(100);
}
//-----------------------------------------------------------------------
/**
* Tests that the removal operation actually removes the first element.
*/
public void testBoundedFifoBufferRemove() {
resetFull();
int size = confirmed.size();
for (int i = 0; i < size; i++) {
Object o1 = ((BoundedFifoBuffer)collection).remove();
Object o2 = ((ArrayList)confirmed).remove(0);
assertEquals("Removed objects should be equal", o1, o2);
verify();
}
try {
((BoundedFifoBuffer)collection).remove();
fail("Empty buffer should raise Underflow.");
} catch (BufferUnderflowException e) {
// expected
}
}
/**
* Tests that the constructor correctly throws an exception.
*/
public void testConstructorException1() {
try {
new BoundedFifoBuffer(0);
} catch (IllegalArgumentException ex) {
return;
}
fail();
}
/**
* Tests that the constructor correctly throws an exception.
*/
public void testConstructorException2() {
try {
new BoundedFifoBuffer(-20);
} catch (IllegalArgumentException ex) {
return;
}
fail();
}
/**
* Tests that the constructor correctly throws an exception.
*/
public void testConstructorException3() {
try {
new BoundedFifoBuffer(null);
} catch (NullPointerException ex) {
return;
}
fail();
}
}

View File

@ -1,120 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.Arrays;
import java.util.Collection;
import junit.framework.Test;
/**
* Runs tests against a full BoundedFifoBuffer, since many of the algorithms
* differ depending on whether the fifo is full or not.
*
* @version $Revision$ $Date$
*
* @author Unknown
*/
public class TestBoundedFifoBuffer2 extends TestBoundedFifoBuffer {
public TestBoundedFifoBuffer2(String n) {
super(n);
}
public static Test suite() {
return BulkTest.makeSuite(TestBoundedFifoBuffer2.class);
}
/**
* Returns a BoundedFifoBuffer that's filled to capacity.
* Any attempt to add to the returned buffer will result in a
* BufferOverflowException.
*
* @return a full BoundedFifoBuffer
*/
public Collection makeFullCollection() {
return new BoundedFifoBuffer(Arrays.asList(getFullElements()));
}
/**
* Overridden to skip the add tests. All of them would fail with a
* BufferOverflowException.
*
* @return false
*/
public boolean isAddSupported() {
return false;
}
/**
* Overridden because the add operations raise BufferOverflowException
* instead of UnsupportedOperationException.
*/
public void testUnsupportedAdd() {
}
/**
* Tests to make sure the add operations raise BufferOverflowException.
*/
public void testBufferOverflow() {
resetFull();
try {
collection.add(getOtherElements()[0]);
fail("add should raise BufferOverflow.");
} catch (BufferOverflowException e) {
// expected
}
verify();
try {
collection.addAll(Arrays.asList(getOtherElements()));
fail("addAll should raise BufferOverflow.");
} catch (BufferOverflowException e) {
// expected
}
verify();
}
/**
* Tests is full
*/
public void testIsFull() {
resetFull();
assertEquals(true, ((BoundedCollection) collection).isFull());
((BoundedFifoBuffer) collection).remove();
assertEquals(false, ((BoundedCollection) collection).isFull());
((BoundedFifoBuffer) collection).add("jj");
assertEquals(true, ((BoundedCollection) collection).isFull());
}
/**
* Tests max size
*/
public void testMaxSize() {
resetFull();
assertEquals(getFullElements().length, ((BoundedCollection) collection).maxSize());
((BoundedFifoBuffer) collection).remove();
assertEquals(getFullElements().length, ((BoundedCollection) collection).maxSize());
((BoundedFifoBuffer) collection).add("jj");
assertEquals(getFullElements().length, ((BoundedCollection) collection).maxSize());
}
}

View File

@ -325,14 +325,6 @@ public class TestExtendedProperties extends TestCase {
assertEquals("import", a.getInclude());
assertEquals("include", b.getInclude());
a.setInclude("");
assertEquals(null, a.getInclude());
assertEquals("include", b.getInclude());
a.setInclude("hi");
assertEquals("hi", a.getInclude());
assertEquals("include", b.getInclude());
a.setInclude(null);
assertEquals(null, a.getInclude());
assertEquals("include", b.getInclude());

View File

@ -1,51 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.collections.bag.AbstractTestBag;
/**
* Extension of {@link TestBag} for exercising the {@link HashBag}
* implementation.
*
* @version $Revision$ $Date$
*
* @author Chuck Burdick
*/
public class TestHashBag extends AbstractTestBag {
public TestHashBag(String testName) {
super(testName);
}
public static Test suite() {
return new TestSuite(TestHashBag.class);
}
public static void main(String args[]) {
String[] testCaseName = { TestHashBag.class.getName()};
junit.textui.TestRunner.main(testCaseName);
}
public Bag makeBag() {
return new HashBag();
}
}

View File

@ -1,212 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import junit.framework.Test;
/**
* Tests LRUMap.
*
* @version $Revision$ $Date$
*
* @author James Strachan
* @author Morgan Delagrange
* @author Stephen Colebourne
*/
public class TestLRUMap extends TestSequencedHashMap {
public TestLRUMap(String testName) {
super(testName);
}
public static Test suite() {
return BulkTest.makeSuite(TestLRUMap.class);
}
public static void main(String args[]) {
String[] testCaseName = { TestLRUMap.class.getName() };
junit.textui.TestRunner.main(testCaseName);
}
//-----------------------------------------------------------------------
public Map makeEmptyMap() {
LRUMap map = new LRUMap();
return map;
}
/**
* Override as test uses iterator() and getKey() in combination which doesn't work.
*/
public String[] ignoredTests() {
return new String[] {"TestLRUMap.bulkTestMapEntrySet.testMapEntrySetIteratorEntry"};
}
//-----------------------------------------------------------------------
public void testRemoveLRU() {
LRUMap map2 = new LRUMap(3);
map2.put(new Integer(1),"foo");
map2.put(new Integer(2),"foo");
map2.put(new Integer(3),"foo");
map2.put(new Integer(4),"foo"); // removes 1 since max size exceeded
map2.removeLRU(); // should be Integer(2)
assertTrue("Second to last value should exist",map2.get(new Integer(3)).equals("foo"));
assertTrue("First value inserted should not exist", map2.get(new Integer(1)) == null);
}
public void testMultiplePuts() {
LRUMap map2 = new LRUMap(2);
map2.put(new Integer(1),"foo");
map2.put(new Integer(2),"bar");
map2.put(new Integer(3),"foo");
map2.put(new Integer(4),"bar");
assertTrue("last value should exist",map2.get(new Integer(4)).equals("bar"));
assertTrue("LRU should not exist", map2.get(new Integer(1)) == null);
}
/**
* Confirm that putAll(Map) does not cause the LRUMap
* to exceed its maxiumum size.
*/
public void testPutAll() {
LRUMap map2 = new LRUMap(3);
map2.put(new Integer(1),"foo");
map2.put(new Integer(2),"foo");
map2.put(new Integer(3),"foo");
HashMap hashMap = new HashMap();
hashMap.put(new Integer(4),"foo");
map2.putAll(hashMap);
assertTrue("max size is 3, but actual size is " + map2.size(),
map2.size() == 3);
assertTrue("map should contain the Integer(4) object",
map2.containsKey(new Integer(4)));
}
/**
* Test that the size of the map is reduced immediately
* when setMaximumSize(int) is called
*/
public void testSetMaximumSize() {
LRUMap map = new LRUMap(6);
map.put("1","1");
map.put("2","2");
map.put("3","3");
map.put("4","4");
map.put("5","5");
map.put("6","6");
map.setMaximumSize(3);
assertTrue("map should have size = 3, but actually = " + map.size(),
map.size() == 3);
}
public void testGetPromotion() {
LRUMap map = new LRUMap(3);
map.put("1","1");
map.put("2","2");
map.put("3","3");
// LRU is now 1 (then 2 then 3)
// promote 1 to top
// eviction order is now 2,3,1
map.get("1");
// add another value, forcing a remove
// 2 should be evicted (then 3,1,4)
map.put("4","4");
Iterator keyIterator = map.keySet().iterator();
Object[] keys = new Object[3];
for (int i = 0; keyIterator.hasNext() ; ++i) {
keys[i] = keyIterator.next();
}
assertTrue("first evicted should be 3, was " + keys[0], keys[0].equals("3"));
assertTrue("second evicted should be 1, was " + keys[1], keys[1].equals("1"));
assertTrue("third evicted should be 4, was " + keys[2], keys[2].equals("4"));
}
/**
* You should be able to subclass LRUMap and perform a
* custom action when items are removed automatically
* by the LRU algorithm (the removeLRU() method).
*/
public void testLRUSubclass() {
LRUCounter counter = new LRUCounter(3);
// oldest <--> newest
// 1
counter.put("1","foo");
// 1 2
counter.put("2","foo");
// 1 2 3
counter.put("3","foo");
// 2 3 1
counter.put("1","foo");
// 3 1 4 (2 goes out)
counter.put("4","foo");
// 1 4 5 (3 goes out)
counter.put("5","foo");
// 4 5 2 (1 goes out)
counter.put("2","foo");
// 4 2
counter.remove("5");
assertTrue("size should be 2, but was " + counter.size(), counter.size() == 2);
assertTrue("removedCount should be 3 but was " + counter.removedCount,
counter.removedCount == 3);
assertTrue("first removed was '2'",counter.list.get(0).equals("2"));
assertTrue("second removed was '3'",counter.list.get(1).equals("3"));
assertTrue("third removed was '1'",counter.list.get(2).equals("1"));
assertTrue("oldest key is '4'",counter.get(0).equals("4"));
assertTrue("newest key is '2'",counter.get(1).equals("2"));
}
protected void entrySetEqualsMap(Set set, Map m) {
// Overridden because LRUMap.get(Object) actually alters the map,
// so there's no way to verify that the entry set and map contain
// the same entries
}
private class LRUCounter extends LRUMap {
int removedCount = 0;
ArrayList list = new ArrayList(3);
LRUCounter(int i) {
super(i);
}
protected void processRemovedLRU(Object key, Object value) {
++removedCount;
list.add(key);
}
}
}

View File

@ -1,475 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.collections.map.AbstractTestMap;
/**
* Unit Tests for <code>MultiHashMap</code>.
*
* @version $Revision$ $Date$
*
* @author Unknown
*/
public class TestMultiHashMap extends AbstractTestMap {
public TestMultiHashMap(String testName) {
super(testName);
}
public static Test suite() {
return new TestSuite(TestMultiHashMap.class);
}
public static void main(String args[]) {
String[] testCaseName = { TestMultiHashMap.class.getName()};
junit.textui.TestRunner.main(testCaseName);
}
// MutltiHashMap was introduced in Collections 2.x
public String getCompatibilityVersion() {
return "2";
}
public Map makeEmptyMap() {
return new MultiHashMap();
}
//----------------------------
// Tests
//----------------------------
public void testPutNGet() {
MultiHashMap map = new MultiHashMap();
loadMap(map);
checkMap(map);
assertTrue(map.get(new Integer(99)) == null);
map.clear();
assertTrue(map.size() == 0);
}
public void testContainsValue() {
MultiHashMap map = new MultiHashMap();
loadMap(map);
assertTrue(map.containsValue("uno"));
assertTrue(map.containsValue("quatro"));
assertTrue(map.containsValue("two"));
assertTrue(!map.containsValue("uggaBugga"));
map.clear();
}
public void testValues() {
MultiHashMap map = new MultiHashMap();
loadMap(map);
Collection vals = map.values();
assertTrue(vals.size() == getFullSize());
map.clear();
}
static private class MapPair {
MapPair(int key, String val) {
mKey = new Integer(key);
mValue = val;
}
Integer mKey = null;
String mValue = null;
}
static private MapPair[][] sMapPairs =
{
{new MapPair(0,"zero")},
{new MapPair(1,"one"), new MapPair(1,"ONE"), new MapPair(1,"uno")},
{new MapPair(2,"two"), new MapPair(2,"two") },
{new MapPair(3,"three"), new MapPair(3,"THREE"), new MapPair(3,"tres")},
{new MapPair(4,"four"), new MapPair(4,"quatro")}
};
private void loadMap(MultiHashMap map) {
// Set up so that we load the keys "randomly"
// (i.e. we don't want to load int row-order, so that all like keys
// load together. We want to mix it up...)
int numRows = sMapPairs.length;
int maxCols = 0;
for (int ii = 0; ii < sMapPairs.length; ii++) {
if (sMapPairs[ii].length > maxCols) {
maxCols = sMapPairs[ii].length;
}
}
for (int ii = 0; ii < maxCols; ii++) {
for (int jj = 0; jj < numRows; jj++) {
if (ii < sMapPairs[jj].length) {
map.put(sMapPairs[jj][ii].mKey, sMapPairs[jj][ii].mValue);
//---------------------------------------------------------
}
}
}
assertTrue(map.size() == sMapPairs.length);
}
private void checkMap(MultiHashMap map) {
for (int ii = 0; ii < sMapPairs.length; ii++) {
checkKeyList(map, ii);
}
}
private void checkKeyList(MultiHashMap map, int index) {
assertTrue(index < sMapPairs.length);
Integer key = sMapPairs[index][0].mKey;
Object obj = map.get(key);
//--------------------------
assertTrue(obj != null);
assertTrue(obj instanceof Collection);
Collection keyList = (Collection) obj;
assertTrue(keyList.size() == sMapPairs[index].length);
Iterator iter = keyList.iterator();
while (iter.hasNext()) {
Object oval = iter.next();
assertTrue(oval != null);
assertTrue(oval instanceof String);
String val = (String) oval;
boolean foundIt = false;
for (int ii = 0; ii < sMapPairs[index].length; ii++) {
if (val.equals(sMapPairs[index][ii].mValue)) {
foundIt = true;
}
}
assertTrue(foundIt);
}
}
public int getFullSize() {
int len = 0;
for (int ii = 0; ii < sMapPairs.length; ii++) {
len += sMapPairs[ii].length;
}
return len;
}
public void testEntrySetIterator() {
}
public void testEntrySetContainsProperMappings() {
}
public void testEntrySetIteratorHasProperMappings() {
// override and ignore test -- it will fail when verifying the iterator for
// the set contains the right value -- we're not returning the value, we're
// returning a collection.
// TODO: re-implement this test to ensure the values of the iterator match
// the proper collection rather than the value the superclass is checking
// for.
return;
}
// Next methods are overriden because MultiHashMap values are always a
// collection, and deviate from the Map contract because of this.
// TODO: implement the tests to ensure that Map.get(Object) returns the
// appropriate collection of values
public void testMapGet() {
}
public void testMapPut() {
}
public void testMapPutAll() {
}
public void testMapRemove() {
}
public void testMapEquals() {
MultiHashMap one = new MultiHashMap();
Integer value = new Integer(1);
one.put("One", value);
one.remove("One", value);
MultiHashMap two = new MultiHashMap();
assertEquals(two, one);
}
public void testMapHashCode() {
}
// The verification for the map and its entry set must also be overridden
// because the values are not going to be the same as the values in the
// confirmed map (they're going to be collections of values instead).
public void verifyMap() {
// TODO: implement test to ensure that map is the same as confirmed if
// its values were converted into collections.
}
public void verifyEntrySet() {
// TODO: implement test to ensure that each entry is the same as one in
// the confirmed map, but with the value wrapped in a collection.
}
// The verification method must be overridden because MultiHashMap's
// values() is not properly backed by the map (Bug 9573).
public void verifyValues() {
// update the values view to the latest version, then proceed to verify
// as usual.
values = map.values();
super.verifyValues();
}
//-----------------------------------------------------------------------
public void testGetCollection() {
MultiHashMap map = new MultiHashMap();
map.put("A", "AA");
assertSame(map.get("A"), map.getCollection("A"));
}
public void testTotalSize() {
MultiHashMap map = new MultiHashMap();
assertEquals(0, map.totalSize());
map.put("A", "AA");
assertEquals(1, map.totalSize());
map.put("B", "BA");
assertEquals(2, map.totalSize());
map.put("B", "BB");
assertEquals(3, map.totalSize());
map.put("B", "BC");
assertEquals(4, map.totalSize());
map.remove("A");
assertEquals(3, map.totalSize());
map.remove("B", "BC");
assertEquals(2, map.totalSize());
}
public void testSize_Key() {
MultiHashMap map = new MultiHashMap();
assertEquals(0, map.size("A"));
assertEquals(0, map.size("B"));
map.put("A", "AA");
assertEquals(1, map.size("A"));
assertEquals(0, map.size("B"));
map.put("B", "BA");
assertEquals(1, map.size("A"));
assertEquals(1, map.size("B"));
map.put("B", "BB");
assertEquals(1, map.size("A"));
assertEquals(2, map.size("B"));
map.put("B", "BC");
assertEquals(1, map.size("A"));
assertEquals(3, map.size("B"));
map.remove("A");
assertEquals(0, map.size("A"));
assertEquals(3, map.size("B"));
map.remove("B", "BC");
assertEquals(0, map.size("A"));
assertEquals(2, map.size("B"));
}
public void testIterator_Key() {
MultiHashMap map = new MultiHashMap();
assertEquals(false, map.iterator("A").hasNext());
map.put("A", "AA");
Iterator it = map.iterator("A");
assertEquals(true, it.hasNext());
it.next();
assertEquals(false, it.hasNext());
}
public void testContainsValue_Key() {
MultiHashMap map = new MultiHashMap();
assertEquals(false, map.containsValue("A", "AA"));
assertEquals(false, map.containsValue("B", "BB"));
map.put("A", "AA");
assertEquals(true, map.containsValue("A", "AA"));
assertEquals(false, map.containsValue("A", "AB"));
}
public void testPutAll_Map1() {
MultiMap original = new MultiHashMap();
original.put("key", "object1");
original.put("key", "object2");
MultiHashMap test = new MultiHashMap();
test.put("keyA", "objectA");
test.put("key", "object0");
test.putAll(original);
assertEquals(2, test.size());
assertEquals(4, test.totalSize());
assertEquals(1, test.getCollection("keyA").size());
assertEquals(3, test.getCollection("key").size());
assertEquals(true, test.containsValue("objectA"));
assertEquals(true, test.containsValue("object0"));
assertEquals(true, test.containsValue("object1"));
assertEquals(true, test.containsValue("object2"));
}
public void testPutAll_Map2() {
Map original = new HashMap();
original.put("keyX", "object1");
original.put("keyY", "object2");
MultiHashMap test = new MultiHashMap();
test.put("keyA", "objectA");
test.put("keyX", "object0");
test.putAll(original);
assertEquals(3, test.size());
assertEquals(4, test.totalSize());
assertEquals(1, test.getCollection("keyA").size());
assertEquals(2, test.getCollection("keyX").size());
assertEquals(1, test.getCollection("keyY").size());
assertEquals(true, test.containsValue("objectA"));
assertEquals(true, test.containsValue("object0"));
assertEquals(true, test.containsValue("object1"));
assertEquals(true, test.containsValue("object2"));
}
public void testPutAll_KeyCollection() {
MultiHashMap map = new MultiHashMap();
Collection coll = Arrays.asList(new Object[] {"X", "Y", "Z"});
assertEquals(true, map.putAll("A", coll));
assertEquals(3, map.size("A"));
assertEquals(true, map.containsValue("A", "X"));
assertEquals(true, map.containsValue("A", "Y"));
assertEquals(true, map.containsValue("A", "Z"));
assertEquals(false, map.putAll("A", null));
assertEquals(3, map.size("A"));
assertEquals(true, map.containsValue("A", "X"));
assertEquals(true, map.containsValue("A", "Y"));
assertEquals(true, map.containsValue("A", "Z"));
assertEquals(false, map.putAll("A", new ArrayList()));
assertEquals(3, map.size("A"));
assertEquals(true, map.containsValue("A", "X"));
assertEquals(true, map.containsValue("A", "Y"));
assertEquals(true, map.containsValue("A", "Z"));
coll = Arrays.asList(new Object[] {"M"});
assertEquals(true, map.putAll("A", coll));
assertEquals(4, map.size("A"));
assertEquals(true, map.containsValue("A", "X"));
assertEquals(true, map.containsValue("A", "Y"));
assertEquals(true, map.containsValue("A", "Z"));
assertEquals(true, map.containsValue("A", "M"));
}
public void testClone() {
MultiHashMap map = new MultiHashMap();
map.put("A", "1");
map.put("A", "2");
Collection coll = (Collection) map.get("A");
assertEquals(1, map.size());
assertEquals(2, coll.size());
MultiHashMap cloned = (MultiHashMap) map.clone();
Collection clonedColl = (Collection) cloned.get("A");
assertNotSame(map, cloned);
assertNotSame(coll, clonedColl);
assertEquals(1, map.size());
assertEquals(2, coll.size());
assertEquals(1, cloned.size());
assertEquals(2, clonedColl.size());
map.put("A", "3");
assertEquals(1, map.size());
assertEquals(3, coll.size());
assertEquals(1, cloned.size());
assertEquals(2, clonedColl.size());
}
public void testConstructorCopy1() {
MultiHashMap map = new MultiHashMap();
map.put("A", "1");
map.put("A", "2");
Collection coll = (Collection) map.get("A");
assertEquals(1, map.size());
assertEquals(2, coll.size());
MultiHashMap newMap = new MultiHashMap(map);
Collection newColl = (Collection) newMap.get("A");
assertNotSame(map, newMap);
assertNotSame(coll, newColl);
assertEquals(1, map.size());
assertEquals(2, coll.size());
assertEquals(1, newMap.size());
assertEquals(2, newColl.size());
map.put("A", "3");
assertEquals(1, map.size());
assertEquals(3, coll.size());
assertEquals(1, newMap.size());
assertEquals(2, newColl.size());
}
public void testConstructorCopy2() {
Map map = new HashMap();
map.put("A", "1");
map.put("B", "2");
assertEquals(2, map.size());
MultiHashMap newMap = new MultiHashMap(map);
Collection newColl = (Collection) newMap.get("A");
assertNotSame(map, newMap);
assertEquals(2, map.size());
assertEquals(2, newMap.size());
assertEquals(1, newColl.size());
map.put("A", "3");
assertEquals(2, map.size());
assertEquals(2, newMap.size());
assertEquals(1, newColl.size());
map.put("C", "4");
assertEquals(3, map.size());
assertEquals(2, newMap.size());
assertEquals(1, newColl.size());
}
public void testRemove_KeyItem() {
MultiHashMap map = new MultiHashMap();
map.put("A", "AA");
map.put("A", "AB");
map.put("A", "AC");
assertEquals(null, map.remove("C", "CA"));
assertEquals(null, map.remove("A", "AD"));
assertEquals("AC", map.remove("A", "AC"));
assertEquals("AB", map.remove("A", "AB"));
assertEquals("AA", map.remove("A", "AA"));
assertEquals(new MultiHashMap(), map);
}
}

View File

@ -1,212 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.lang.ref.WeakReference;
import java.util.Map;
import junit.framework.Test;
import org.apache.commons.collections.map.AbstractTestMap;
/**
* Tests for ReferenceMap.
*
* @version $Revision$ $Date$
*
* @author Paul Jack
* @author Guilhem Lavaux
*/
public class TestReferenceMap extends AbstractTestMap {
public TestReferenceMap(String testName) {
super(testName);
}
public static Test suite() {
return BulkTest.makeSuite(TestReferenceMap.class);
}
public static void main(String args[]) {
String[] testCaseName = { TestReferenceMap.class.getName() };
junit.textui.TestRunner.main(testCaseName);
}
public Map makeEmptyMap() {
ReferenceMap map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK);
return map;
}
public boolean isAllowNullKey() {
return false;
}
public boolean isAllowNullValue() {
return false;
}
public String getCompatibilityVersion() {
return "2.1";
}
//-----------------------------------------------------------------------
public void testNullHandling() {
resetFull();
assertEquals(null, map.get(null));
assertEquals(false, map.containsKey(null));
assertEquals(false, map.containsValue(null));
assertEquals(null, map.remove(null));
assertEquals(false, map.entrySet().contains(null));
assertEquals(false, map.keySet().contains(null));
assertEquals(false, map.values().contains(null));
try {
map.put(null, null);
fail();
} catch (NullPointerException ex) {}
try {
map.put(new Object(), null);
fail();
} catch (NullPointerException ex) {}
try {
map.put(null, new Object());
fail();
} catch (NullPointerException ex) {}
}
//-----------------------------------------------------------------------
/*
// Tests often fail because gc is uncontrollable
public void testPurge() {
ReferenceMap map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK);
Object[] hard = new Object[10];
for (int i = 0; i < hard.length; i++) {
hard[i] = new Object();
map.put(hard[i], new Object());
}
gc();
assertTrue("map should be empty after purge of weak values", map.isEmpty());
for (int i = 0; i < hard.length; i++) {
map.put(new Object(), hard[i]);
}
gc();
assertTrue("map should be empty after purge of weak keys", map.isEmpty());
for (int i = 0; i < hard.length; i++) {
map.put(new Object(), hard[i]);
map.put(hard[i], new Object());
}
gc();
assertTrue("map should be empty after purge of weak keys and values", map.isEmpty());
}
public void testGetAfterGC() {
ReferenceMap map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK);
for (int i = 0; i < 10; i++) {
map.put(new Integer(i), new Integer(i));
}
gc();
for (int i = 0; i < 10; i++) {
Integer I = new Integer(i);
assertTrue("map.containsKey should return false for GC'd element", !map.containsKey(I));
assertTrue("map.get should return null for GC'd element", map.get(I) == null);
}
}
public void testEntrySetIteratorAfterGC() {
ReferenceMap map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK);
Object[] hard = new Object[10];
for (int i = 0; i < 10; i++) {
hard[i] = new Integer(10 + i);
map.put(new Integer(i), new Integer(i));
map.put(hard[i], hard[i]);
}
gc();
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry)iterator.next();
Integer key = (Integer)entry.getKey();
Integer value = (Integer)entry.getValue();
assertTrue("iterator should skip GC'd keys", key.intValue() >= 10);
assertTrue("iterator should skip GC'd values", value.intValue() >= 10);
}
}
*/
WeakReference keyReference;
WeakReference valueReference;
public Map buildRefMap() {
Object key = new Object();
Object value = new Object();
keyReference = new WeakReference(key);
valueReference = new WeakReference(value);
Map testMap = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.HARD, true);
testMap.put(key, value);
assertEquals("In map", value, testMap.get(key));
assertNotNull("Weak reference released early (1)", keyReference.get());
assertNotNull("Weak reference released early (2)", valueReference.get());
return testMap;
}
/** Tests whether purge values setting works */
public void testPurgeValues() throws Exception {
// many thanks to Juozas Baliuka for suggesting this method
Map testMap = buildRefMap();
int iterations = 0;
int bytz = 2;
while(true) {
System.gc();
if(iterations++ > 50){
fail("Max iterations reached before resource released.");
}
testMap.isEmpty();
if(
keyReference.get() == null &&
valueReference.get() == null) {
break;
} else {
// create garbage:
byte[] b = new byte[bytz];
bytz = bytz * 2;
}
}
}
private static void gc() {
try {
// trigger GC
byte[][] tooLarge = new byte[1000000000][1000000000];
fail("you have too much RAM");
} catch (OutOfMemoryError ex) {
System.gc(); // ignore
}
}
}

View File

@ -1,194 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.io.IOException;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import junit.framework.Test;
import org.apache.commons.collections.map.AbstractTestMap;
/**
* Unit tests
* {@link org.apache.commons.collections.SequencedHashMap}.
* Be sure to use the "labRat" instance whenever possible,
* so that subclasses will be tested correctly.
*
* @version $Revision$ $Date$
*
* @author Morgan Delagrange
* @author Daniel Rall
* @author Henning P. Schmiedehausen
* @author James Strachan
*/
public class TestSequencedHashMap extends AbstractTestMap {
/**
* The instance to experiment on.
*/
protected SequencedHashMap labRat;
public TestSequencedHashMap(String name) {
super(name);
}
public static Test suite() {
return BulkTest.makeSuite(TestSequencedHashMap.class);
}
// current versions of SequencedHashMap and subclasses are not
// compatible with Collections 1.x
public String getCompatibilityVersion() {
return "2";
}
public static void main(String[] args) {
String[] testCaseName = { TestSequencedHashMap.class.getName() };
junit.textui.TestRunner.main(testCaseName);
}
public void setUp() throws Exception {
super.setUp();
// use makeMap and cast the result to a SeqHashMap
// so that subclasses of SeqHashMap can share these tests
labRat = (SequencedHashMap) makeEmptyMap();
}
public Map makeEmptyMap() {
return new SequencedHashMap();
}
protected Object[] getKeys() {
return new Object[] { "foo", "baz", "eek" };
}
protected Object[] getValues() {
return new Object[] { "bar", "frob", new Object() };
}
public void testSequenceMap() throws Throwable {
Object[] keys = getKeys();
int expectedSize = keys.length;
Object[] values = getValues();
for (int i = 0; i < expectedSize; i++) {
labRat.put(keys[i], values[i]);
}
// Test size().
assertEquals("size() does not match expected size",
expectedSize, labRat.size());
// Test clone(), iterator(), and get(Object).
SequencedHashMap clone = (SequencedHashMap) labRat.clone();
assertEquals("Size of clone does not match original",
labRat.size(), clone.size());
Iterator origEntries = labRat.entrySet().iterator();
Iterator copiedEntries = clone.entrySet().iterator();
while (origEntries.hasNext()) {
Map.Entry origEntry = (Map.Entry)origEntries.next();
Map.Entry copiedEntry = (Map.Entry)copiedEntries.next();
assertEquals("Cloned key does not match original",
origEntry.getKey(), copiedEntry.getKey());
assertEquals("Cloned value does not match original",
origEntry.getValue(), copiedEntry.getValue());
assertEquals("Cloned entry does not match original",
origEntry, copiedEntry);
}
assertTrue("iterator() returned different number of elements than keys()",
!copiedEntries.hasNext());
// Test sequence()
List seq = labRat.sequence();
assertEquals("sequence() returns more keys than in the Map",
expectedSize, seq.size());
for (int i = 0; i < seq.size(); i++) {
assertEquals("Key " + i + " is not the same as the key in the Map",
keys[i], seq.get(i));
}
}
public void testYoungest() {
labRat.put(new Integer(1),"foo");
labRat.put(new Integer(2),"bar");
assertTrue("first key is correct",labRat.get(0).equals(new Integer(1)));
labRat.put(new Integer(1),"boo");
assertTrue("second key is reassigned to first",labRat.get(0).equals(new Integer(2)));
}
public void testYoungestReplaceNullWithValue() {
labRat.put(new Integer(1),null);
labRat.put(new Integer(2),"foo");
assertTrue("first key is correct",labRat.get(0).equals(new Integer(1)));
labRat.put(new Integer(1),"bar");
assertTrue("second key is reassigned to first",labRat.get(0).equals(new Integer(2)));
}
public void testYoungestReplaceValueWithNull() {
labRat.put(new Integer(1),"bar");
labRat.put(new Integer(2),"foo");
assertTrue("first key is correct",labRat.get(0).equals(new Integer(1)));
labRat.put(new Integer(1),null);
assertTrue("second key is reassigned to first",labRat.get(0).equals(new Integer(2)));
}
// override TestMap method with more specific tests
public void testFullMapSerialization()
throws IOException, ClassNotFoundException {
SequencedHashMap map = (SequencedHashMap) makeFullMap();
if (!(map instanceof Serializable)) return;
byte[] objekt = writeExternalFormToBytes((Serializable) map);
SequencedHashMap map2 = (SequencedHashMap) readExternalFormFromBytes(objekt);
assertEquals("Both maps are same size",map.size(), getSampleKeys().length);
assertEquals("Both maps are same size",map2.size(),getSampleKeys().length);
assertEquals("Both maps have the same first key",
map.getFirstKey(),getSampleKeys()[0]);
assertEquals("Both maps have the same first key",
map2.getFirstKey(),getSampleKeys()[0]);
assertEquals("Both maps have the same last key",
map.getLastKey(),getSampleKeys()[getSampleKeys().length - 1]);
assertEquals("Both maps have the same last key",
map2.getLastKey(),getSampleKeys()[getSampleKeys().length - 1]);
}
public void testIndexOf() throws Exception {
Object[] keys = getKeys();
int expectedSize = keys.length;
Object[] values = getValues();
for (int i = 0; i < expectedSize; i++) {
labRat.put(keys[i], values[i]);
}
// test that the index returned are in the same order that they were
// placed in the map
for (int i = 0; i < keys.length; i++) {
assertEquals("indexOf with existing key failed", i, labRat.indexOf(keys[i]));
}
// test non existing key..
assertEquals("test with non-existing key failed", -1, labRat.indexOf("NonExistingKey"));
}
public void tearDown() throws Exception {
labRat = null;
}
}

View File

@ -1,96 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.Map;
import junit.framework.Test;
import org.apache.commons.collections.map.AbstractTestMap;
/**
* Unit tests.
* {@link org.apache.commons.collections.StaticBucketMap}.
*
* @version $Revision$ $Date$
*
* @author Michael A. Smith
*/
public class TestStaticBucketMap extends AbstractTestMap {
public TestStaticBucketMap(String name) {
super(name);
}
public static Test suite() {
return BulkTest.makeSuite(TestStaticBucketMap.class);
}
public static void main(String[] args[]) {
String[] testCaseName = { TestStaticBucketMap.class.getName() };
junit.textui.TestRunner.main(testCaseName);
}
public Map makeEmptyMap() {
return new StaticBucketMap(30);
}
public String[] ignoredTests() {
String pre = "TestStaticBucketMap.bulkTestMap";
String post = ".testCollectionIteratorFailFast";
return new String[] {
pre + "EntrySet" + post,
pre + "KeySet" + post,
pre + "Values" + post
};
}
// Bugzilla 37567
public void test_get_nullMatchesIncorrectly() {
StaticBucketMap map = new StaticBucketMap(17);
map.put(null, "A");
assertEquals("A", map.get(null));
// loop so we find a string that is in the same bucket as the null
for (int i = 'A'; i <= 'Z'; i++) {
String str = String.valueOf((char) i);
assertEquals("String: " + str, null, map.get(str));
}
}
public void test_containsKey_nullMatchesIncorrectly() {
StaticBucketMap map = new StaticBucketMap(17);
map.put(null, "A");
assertEquals(true, map.containsKey(null));
// loop so we find a string that is in the same bucket as the null
for (int i = 'A'; i <= 'Z'; i++) {
String str = String.valueOf((char) i);
assertEquals("String: " + str, false, map.containsKey(str));
}
}
public void test_containsValue_nullMatchesIncorrectly() {
StaticBucketMap map = new StaticBucketMap(17);
map.put("A", null);
assertEquals(true, map.containsValue(null));
// loop so we find a string that is in the same bucket as the null
for (int i = 'A'; i <= 'Z'; i++) {
String str = String.valueOf((char) i);
assertEquals("String: " + str, false, map.containsValue(str));
}
}
}

View File

@ -1,73 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.apache.commons.collections.bag.AbstractTestBag;
/**
* Extension of {@link TestBag} for exercising the {@link TreeBag}
* implementation.
*
* @version $Revision$ $Date$
*
* @author Chuck Burdick
*/
public class TestTreeBag extends AbstractTestBag {
public TestTreeBag(String testName) {
super(testName);
}
public static Test suite() {
return new TestSuite(TestTreeBag.class);
}
public static void main(String args[]) {
String[] testCaseName = { TestTreeBag.class.getName() };
junit.textui.TestRunner.main(testCaseName);
}
public Bag makeBag() {
return new TreeBag();
}
public SortedBag setupBag() {
SortedBag bag = (SortedBag)makeBag();
bag.add("C");
bag.add("A");
bag.add("B");
bag.add("D");
return bag;
}
public void testOrdering() {
Bag bag = setupBag();
assertEquals("Should get elements in correct order",
"A", bag.toArray()[0]);
assertEquals("Should get elements in correct order",
"B", bag.toArray()[1]);
assertEquals("Should get elements in correct order",
"C", bag.toArray()[2]);
assertEquals("Should get first key",
"A", ((SortedBag)bag).first());
assertEquals("Should get last key",
"D", ((SortedBag)bag).last());
}
}

View File

@ -1,414 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import junit.framework.Test;
import org.apache.commons.collections.collection.AbstractTestCollection;
/**
* Test cases for UnboundedFifoBuffer.
*
* @version $Revision$ $Date$
*
* @author Unknown
*/
public class TestUnboundedFifoBuffer extends AbstractTestCollection {
public TestUnboundedFifoBuffer(String n) {
super(n);
}
public static Test suite() {
return BulkTest.makeSuite(TestUnboundedFifoBuffer.class);
}
//-----------------------------------------------------------------------
/**
* Verifies that the ArrayList has the same elements in the same
* sequence as the UnboundedFifoBuffer.
*/
public void verify() {
super.verify();
Iterator iterator1 = collection.iterator();
Iterator iterator2 = confirmed.iterator();
while (iterator2.hasNext()) {
assertTrue(iterator1.hasNext());
Object o1 = iterator1.next();
Object o2 = iterator2.next();
assertEquals(o1, o2);
}
}
//-----------------------------------------------------------------------
/**
* Overridden because UnboundedFifoBuffer doesn't allow null elements.
* @return false
*/
public boolean isNullSupported() {
return false;
}
/**
* Overridden because UnboundedFifoBuffer isn't fail fast.
* @return false
*/
public boolean isFailFastSupported() {
return false;
}
//-----------------------------------------------------------------------
/**
* Returns an empty ArrayList.
*
* @return an empty ArrayList
*/
public Collection makeConfirmedCollection() {
return new ArrayList();
}
/**
* Returns a full ArrayList.
*
* @return a full ArrayList
*/
public Collection makeConfirmedFullCollection() {
Collection c = makeConfirmedCollection();
c.addAll(java.util.Arrays.asList(getFullElements()));
return c;
}
/**
* Returns an empty UnboundedFifoBuffer with a small capacity.
*
* @return an empty UnboundedFifoBuffer
*/
public Collection makeCollection() {
return new UnboundedFifoBuffer(5);
}
//-----------------------------------------------------------------------
/**
* Tests that UnboundedFifoBuffer removes elements in the right order.
*/
public void testUnboundedFifoBufferRemove() {
resetFull();
int size = confirmed.size();
for (int i = 0; i < size; i++) {
Object o1 = ((UnboundedFifoBuffer)collection).remove();
Object o2 = ((ArrayList)confirmed).remove(0);
assertEquals("Removed objects should be equal", o1, o2);
verify();
}
}
/**
* Tests that the constructor correctly throws an exception.
*/
public void testConstructorException1() {
try {
new UnboundedFifoBuffer(0);
} catch (IllegalArgumentException ex) {
return;
}
fail();
}
/**
* Tests that the constructor correctly throws an exception.
*/
public void testConstructorException2() {
try {
new UnboundedFifoBuffer(-20);
} catch (IllegalArgumentException ex) {
return;
}
fail();
}
//-----------------------------------------------------------------------
public void testInternalStateAdd() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(2);
assertEquals(3, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(0, test.m_tail);
test.add("A");
assertEquals(3, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(1, test.m_tail);
test.add("B");
assertEquals(3, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(2, test.m_tail);
test.add("C"); // forces m_buffer increase
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
test.add("D");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(4, test.m_tail);
}
public void testInternalStateAddWithWrap() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
assertEquals(4, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(0, test.m_tail);
test.add("A");
assertEquals(4, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(1, test.m_tail);
test.add("B");
assertEquals(4, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(2, test.m_tail);
test.add("C");
assertEquals(4, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
test.remove("A");
assertEquals(4, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(3, test.m_tail);
test.remove("B");
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(3, test.m_tail);
test.add("D");
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(0, test.m_tail);
test.add("E");
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(1, test.m_tail);
}
public void testInternalStateRemove1() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
test.add("A");
test.add("B");
test.add("C");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
test.remove("A");
assertEquals(5, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(3, test.m_tail);
test.add("D");
assertEquals(5, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(4, test.m_tail);
}
public void testInternalStateRemove2() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
test.add("A");
test.add("B");
test.add("C");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
test.remove("B");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(2, test.m_tail);
test.add("D");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
}
public void testInternalStateIteratorRemove1() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
test.add("A");
test.add("B");
test.add("C");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
Iterator it = test.iterator();
it.next();
it.remove();
assertEquals(5, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(3, test.m_tail);
test.add("D");
assertEquals(5, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(4, test.m_tail);
}
public void testInternalStateIteratorRemove2() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(4);
test.add("A");
test.add("B");
test.add("C");
Iterator it = test.iterator();
it.next();
it.next();
it.remove();
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(2, test.m_tail);
test.add("D");
assertEquals(5, test.m_buffer.length);
assertEquals(0, test.m_head);
assertEquals(3, test.m_tail);
}
public void testInternalStateIteratorRemoveWithTailAtEnd1() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.add("D");
assertEquals(4, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(0, test.m_tail);
Iterator it = test.iterator();
assertEquals("B", it.next());
it.remove();
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(0, test.m_tail);
}
public void testInternalStateIteratorRemoveWithTailAtEnd2() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.add("D");
assertEquals(4, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(0, test.m_tail);
Iterator it = test.iterator();
assertEquals("B", it.next());
assertEquals("C", it.next());
it.remove();
assertEquals(4, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(3, test.m_tail);
}
public void testInternalStateIteratorRemoveWithTailAtEnd3() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.add("D");
assertEquals(4, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(0, test.m_tail);
Iterator it = test.iterator();
assertEquals("B", it.next());
assertEquals("C", it.next());
assertEquals("D", it.next());
it.remove();
assertEquals(4, test.m_buffer.length);
assertEquals(1, test.m_head);
assertEquals(3, test.m_tail);
}
public void testInternalStateIteratorRemoveWithWrap1() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.remove("B");
test.add("D");
test.add("E");
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(1, test.m_tail);
Iterator it = test.iterator();
assertEquals("C", it.next());
it.remove();
assertEquals(4, test.m_buffer.length);
assertEquals(3, test.m_head);
assertEquals(1, test.m_tail);
}
public void testInternalStateIteratorRemoveWithWrap2() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.remove("B");
test.add("D");
test.add("E");
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(1, test.m_tail);
Iterator it = test.iterator();
assertEquals("C", it.next());
assertEquals("D", it.next());
it.remove();
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(0, test.m_tail);
}
public void testInternalStateIteratorRemoveWithWrap3() {
UnboundedFifoBuffer test = new UnboundedFifoBuffer(3);
test.add("A");
test.add("B");
test.add("C");
test.remove("A");
test.remove("B");
test.add("D");
test.add("E");
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(1, test.m_tail);
Iterator it = test.iterator();
assertEquals("C", it.next());
assertEquals("D", it.next());
assertEquals("E", it.next());
it.remove();
assertEquals(4, test.m_buffer.length);
assertEquals(2, test.m_head);
assertEquals(0, test.m_tail);
}
}

View File

@ -1473,4 +1473,15 @@ public class TestCursorableLinkedList extends TestAbstractLinkedList {
return (String[])list.toArray(new String[0]);
}
public String getCompatibilityVersion() {
return "4.0";
}
// public void testCreate() throws Exception {
// resetEmpty();
// writeExternalFormToDisk((java.io.Serializable) collection, "C:/commons/collections/data/test/CursorableLinkedList.emptyCollection.version4.0.obj");
// resetFull();
// writeExternalFormToDisk((java.io.Serializable) collection, "C:/commons/collections/data/test/CursorableLinkedList.fullCollection.version4.0.obj");
// }
}