[med-svn] [libjung-java] 02/02: initial Debianization
Michael Crusoe
misterc-guest at moszumanska.debian.org
Fri Feb 13 22:55:16 UTC 2015
This is an automated email from the git hooks/post-receive script.
misterc-guest pushed a commit to branch master
in repository libjung-java.
commit 6fbbe8d563ab6602827975bed6490aea83fd0882
Author: Michael R. Crusoe <mcrusoe at msu.edu>
Date: Fri Feb 13 11:56:31 2015 -0500
initial Debianization
---
debian/changelog | 5 +
debian/compat | 1 +
debian/control | 37 +
debian/copyright | 54 +
debian/createmanpages | 16 +
debian/patches/collections15 | 53359 +++++++++++++++++++++++++++++++++++++++++
debian/patches/series | 1 +
debian/rules | 51 +
debian/source/format | 1 +
debian/upstream/metadata | 12 +
debian/watch | 37 +
11 files changed, 53574 insertions(+)
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..3abf8e0
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,5 @@
+libjung-java (2.0.1-1) UNRELEASED; urgency=low
+
+ * Initial release (Closes: #<bug>)
+
+ -- Michael R. Crusoe <mcrusoe at msu.edu> Fri, 13 Feb 2015 11:52:45 -0500
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..41442f1
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,37 @@
+Source: libjung-java
+Section: java
+Priority: optional
+Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.org>
+Uploaders: Michael R. Crusoe <mcrusoe at msu.edu>
+Build-Depends: debhelper (>= 9), javahelper, libcommons-collections4-java
+Standards-Version: 3.9.6
+Vcs-Browser: http://anonscm.debian.org/viewvc/debian-med/trunk/packages/<pkg>/trunk/
+Vcs-Svn: svn://anonscm.debian.org/debian-med/trunk/packages/<pkg>/trunk/
+Homepage: http://jung.sourceforge.net/
+
+Package: libjung-java
+Architecture: any
+Depends: ${java:Depends}, ${misc:Depends}
+Description: Java Universal Network/Graph Framework
+ JUNG provides a common and extendible language for the modeling, analysis, and
+ visualization of data that can be represented as a graph or network.
+ .
+ The JUNG architecture is designed to support a variety of representations of
+ entities and their relations, such as directed and undirected graphs,
+ multi-modal graphs, graphs with parallel edges, and hypergraphs. It provides
+ a mechanism for annotating graphs, entities, and relations with metadata. This
+ facilitates the creation of analytic tools for complex data sets that can
+ examine the relations between entities as well as the metadata attached to each
+ entity and relation.
+ .
+ The current distribution of JUNG includes implementations of a number of
+ algorithms from graph theory, data mining, and social network analysis, such as
+ routines for clustering, decomposition, optimization, random graph generation,
+ statistical analysis, and calculation of network distances, flows, and
+ importance measures (centrality, PageRank, HITS, etc.).
+ .
+ JUNG also provides a visualization framework that makes it easy to construct
+ tools for the interactive exploration of network data. Users can use one of the
+ layout algorithms provided, or use the framework to create their own custom
+ layouts. In addition, filtering mechanisms are provided which allow users to
+ focus their attention, or their algorithms, on specific portions of the graph.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..66b0a1f
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,54 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: JUNG
+Source: http://sourceforge.net/projects/jung/files/jung/jung-2.0.1/jung2-2_0_1-sources.zip/download
+
+Files: *
+Copyright: © 2003-2004, Regents of the University of California and the JUNG Project
+License: BSD-3-clause
+
+Files: debian/*
+Copyright: © 2014 Michigan State University
+License: BSD-3-clause
+
+Files: debian/patches/collections15
+Copyright: 1999-2004, The Apache Software Foundation
+Comment: Source http://sourceforge.net/projects/collections/
+License: Apache-2.0
+ Licensed 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.
+ .
+ On Debian systems, the complete text of the Apache License version 2.0
+ can be found in "/usr/share/common-licenses/Apache-2.0".
+
+License: BSD-3-clause
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ .
+ * Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the University of California nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/debian/createmanpages b/debian/createmanpages
new file mode 100755
index 0000000..febcd91
--- /dev/null
+++ b/debian/createmanpages
@@ -0,0 +1,16 @@
+#!/bin/sh
+MANDIR=debian
+mkdir -p $MANDIR
+
+VERSION=`dpkg-parsechangelog | awk '/^Version:/ {print $2}' | sed -e 's/^[0-9]*://' -e 's/-.*//' -e 's/[+~]dfsg$//'`
+
+help2man --no-info --no-discard-stderr --help-option=" " \
+ --name='<optional description of the program>' \
+ --version-string="$VERSION" <programname> > $MANDIR/<programname>.1
+
+cat <<EOT
+Please enhance the help2man output.
+The following web page might be helpful in doing so:
+ http://liw.fi/manpages/
+EOT
+
diff --git a/debian/patches/collections15 b/debian/patches/collections15
new file mode 100644
index 0000000..b5a96a1
--- /dev/null
+++ b/debian/patches/collections15
@@ -0,0 +1,53359 @@
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/ArrayStack.java
+@@ -0,0 +1,195 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.ArrayList;
++import java.util.EmptyStackException;
++
++/**
++ * An implementation of the {@link java.util.Stack} API that is based on an
++ * <code>ArrayList</code> instead of a <code>Vector</code>, so it is not
++ * synchronized to protect against multi-threaded access. The implementation
++ * is therefore operates faster in environments where you do not need to
++ * worry about multiple thread contention.
++ * <p/>
++ * The removal order of an <code>ArrayStack</code> is based on insertion
++ * order: The most recently added element is removed first. The iteration
++ * order is <i>not</i> the same as the removal order. The iterator returns
++ * elements from the bottom up, whereas the {@link #remove()} method removes
++ * them from the top down.
++ * <p/>
++ * Unlike <code>Stack</code>, <code>ArrayStack</code> accepts null entries.
++ *
++ * @author Craig R. McClanahan
++ * @author Paul Jack
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @see java.util.Stack
++ * @since Commons Collections 1.0
++ */
++public class ArrayStack <E> extends ArrayList<E> implements Buffer<E> {
++
++ /**
++ * Ensure serialization compatibility
++ */
++ private static final long serialVersionUID = 2130079159931574599L;
++
++ /**
++ * Constructs a new empty <code>ArrayStack</code>. The initial size
++ * is controlled by <code>ArrayList</code> and is currently 10.
++ */
++ public ArrayStack() {
++ super();
++ }
++
++ /**
++ * Constructs a new empty <code>ArrayStack</code> with an initial size.
++ *
++ * @param initialSize the initial size to use
++ * @throws IllegalArgumentException if the specified initial size
++ * is negative
++ */
++ public ArrayStack(int initialSize) {
++ super(initialSize);
++ }
++
++ /**
++ * Return <code>true</code> if this stack is currently empty.
++ * <p/>
++ * This method exists for compatibility with <code>java.util.Stack</code>.
++ * New users of this class should use <code>isEmpty</code> instead.
++ *
++ * @return true if the stack is currently empty
++ */
++ public boolean empty() {
++ return isEmpty();
++ }
++
++ /**
++ * Returns the top item off of this stack without removing it.
++ *
++ * @return the top item on the stack
++ * @throws EmptyStackException if the stack is empty
++ */
++ public E peek() throws EmptyStackException {
++ int n = size();
++ if (n <= 0) {
++ throw new EmptyStackException();
++ } else {
++ return get(n - 1);
++ }
++ }
++
++ /**
++ * Returns the n'th item down (zero-relative) from the top of this
++ * stack without removing it.
++ *
++ * @param n the number of items down to go
++ * @return the n'th item on the stack, zero relative
++ * @throws EmptyStackException if there are not enough items on the
++ * stack to satisfy this request
++ */
++ public E peek(int n) throws EmptyStackException {
++ int m = (size() - n) - 1;
++ if (m < 0) {
++ throw new EmptyStackException();
++ } else {
++ return get(m);
++ }
++ }
++
++ /**
++ * Pops the top item off of this stack and return it.
++ *
++ * @return the top item on the stack
++ * @throws EmptyStackException if the stack is empty
++ */
++ public E pop() throws EmptyStackException {
++ int n = size();
++ if (n <= 0) {
++ throw new EmptyStackException();
++ } else {
++ return remove(n - 1);
++ }
++ }
++
++ /**
++ * Pushes a new item onto the top of this stack. The pushed item is also
++ * returned. This is equivalent to calling <code>add</code>.
++ *
++ * @param item the item to be added
++ * @return the item just pushed
++ */
++ public E push(E item) {
++ add(item);
++ return item;
++ }
++
++ /**
++ * Returns the one-based position of the distance from the top that the
++ * specified object exists on this stack, where the top-most element is
++ * considered to be at distance <code>1</code>. If the object is not
++ * present on the stack, return <code>-1</code> instead. The
++ * <code>equals()</code> method is used to compare to the items
++ * in this stack.
++ *
++ * @param object the object to be searched for
++ * @return the 1-based depth into the stack of the object, or -1 if not found
++ */
++ public int search(E object) {
++ int i = size() - 1; // Current index
++ int n = 1; // Current distance
++ while (i >= 0) {
++ E current = get(i);
++ if ((object == null && current == null) || (object != null && object.equals(current))) {
++ return n;
++ }
++ i--;
++ n++;
++ }
++ return -1;
++ }
++
++ /**
++ * Returns the element on the top of the stack.
++ *
++ * @return the element on the top of the stack
++ * @throws BufferUnderflowException if the stack is empty
++ */
++ public E get() {
++ int size = size();
++ if (size == 0) {
++ throw new BufferUnderflowException();
++ }
++ return get(size - 1);
++ }
++
++ /**
++ * Removes the element on the top of the stack.
++ *
++ * @return the removed element
++ * @throws BufferUnderflowException if the stack is empty
++ */
++ public E remove() {
++ int size = size();
++ if (size == 0) {
++ throw new BufferUnderflowException();
++ }
++ return remove(size - 1);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/Bag.java
+@@ -0,0 +1,221 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.Set;
++
++/**
++ * Defines a collection that counts the number of times an object appears in
++ * the collection.
++ * <p/>
++ * Suppose you have a Bag that contains <code>{a, a, b, c}</code>.
++ * Calling {@link #getCount(Object)} on <code>a</code> would return 2, while
++ * calling {@link #uniqueSet()} would return <code>{a, b, c}</code>.
++ * <p/>
++ * <i>NOTE: This interface violates the {@link Collection} contract.</i>
++ * The behavior specified in many of these methods is <i>not</i> the same
++ * as the behavior specified by <code>Collection</code>.
++ * The noncompliant methods are clearly marked with "(Violation)".
++ * Exercise caution when using a bag as a <code>Collection</code>.
++ * <p/>
++ * This violation resulted from the original specification of this interface.
++ * In an ideal world, the interface would be changed to fix the problems, however
++ * it has been decided to maintain backwards compatibility instead.
++ *
++ * @author Chuck Burdick
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 2.0
++ */
++public interface Bag <E> extends Collection<E> {
++
++ /**
++ * Returns the number of occurrences (cardinality) of the given
++ * object currently in the bag. If the object does not exist in the
++ * bag, return 0.
++ *
++ * @param object the object to search for
++ * @return the number of occurrences of the object, zero if not found
++ */
++ int getCount(E object);
++
++ /**
++ * <i>(Violation)</i>
++ * Adds one copy the specified object to the Bag.
++ * <p/>
++ * If the object is already in the {@link #uniqueSet()} then increment its
++ * count as reported by {@link #getCount(Object)}. Otherwise add it to the
++ * {@link #uniqueSet()} and report its count as 1.
++ * <p/>
++ * Since this method always increases the size of the bag,
++ * according to the {@link Collection#add(Object)} contract, it
++ * should always return <code>true</code>. Since it sometimes returns
++ * <code>false</code>, this method violates the contract.
++ *
++ * @param object the object to add
++ * @return <code>true</code> if the object was not already in the <code>uniqueSet</code>
++ */
++ boolean add(E object);
++
++ /**
++ * Adds <code>nCopies</code> copies of the specified object to the Bag.
++ * <p/>
++ * If the object is already in the {@link #uniqueSet()} then increment its
++ * count as reported by {@link #getCount(Object)}. Otherwise add it to the
++ * {@link #uniqueSet()} and report its count as <code>nCopies</code>.
++ *
++ * @param object the object to add
++ * @param nCopies the number of copies to add
++ * @return <code>true</code> if the object was not already in the <code>uniqueSet</code>
++ */
++ boolean add(E object, int nCopies);
++
++ /**
++ * <i>(Violation)</i>
++ * Removes all occurrences of the given object from the bag.
++ * <p/>
++ * This will also remove the object from the {@link #uniqueSet()}.
++ * <p/>
++ * According to the {@link Collection#remove(Object)} method,
++ * this method should only remove the <i>first</i> occurrence of the
++ * given object, not <i>all</i> occurrences.
++ *
++ * @return <code>true</code> if this call changed the collection
++ */
++ boolean remove(Object object);
++
++ /**
++ * Removes <code>nCopies</code> copies of the specified object from the Bag.
++ * <p/>
++ * If the number of copies to remove is greater than the actual number of
++ * copies in the Bag, no error is thrown.
++ *
++ * @param object the object to remove
++ * @param nCopies the number of copies to remove
++ * @return <code>true</code> if this call changed the collection
++ */
++ boolean remove(E object, int nCopies);
++
++ /**
++ * Returns a {@link Set} of unique elements in the Bag.
++ * <p/>
++ * Uniqueness constraints are the same as those in {@link java.util.Set}.
++ *
++ * @return the Set of unique Bag elements
++ */
++ Set<E> uniqueSet();
++
++ /**
++ * Returns the total number of items in the bag across all types.
++ *
++ * @return the total size of the Bag
++ */
++ int size();
++
++ /**
++ * <i>(Violation)</i>
++ * Returns <code>true</code> if the bag contains all elements in
++ * the given collection, respecting cardinality. That is, if the
++ * given collection <code>coll</code> contains <code>n</code> copies
++ * of a given object, calling {@link #getCount(Object)} on that object must
++ * be <code>>= n</code> for all <code>n</code> in <code>coll</code>.
++ * <p/>
++ * The {@link Collection#containsAll(Collection)} method specifies
++ * that cardinality should <i>not</i> be respected; this method should
++ * return true if the bag contains at least one of every object contained
++ * in the given collection.
++ *
++ * @param coll the collection to check against
++ * @return <code>true</code> if the Bag contains all the collection
++ */
++ boolean containsAll(Collection<?> coll);
++
++ /**
++ * <i>(Violation)</i>
++ * Remove all elements represented in the given collection,
++ * respecting cardinality. That is, if the given collection
++ * <code>coll</code> contains <code>n</code> copies of a given object,
++ * the bag will have <code>n</code> fewer copies, assuming the bag
++ * had at least <code>n</code> copies to begin with.
++ * <p/>
++ * <P>The {@link Collection#removeAll(Collection)} method specifies
++ * that cardinality should <i>not</i> be respected; this method should
++ * remove <i>all</i> occurrences of every object contained in the
++ * given collection.
++ *
++ * @param coll the collection to remove
++ * @return <code>true</code> if this call changed the collection
++ */
++ boolean removeAll(Collection<?> coll);
++
++ /**
++ * <i>(Violation)</i>
++ * Remove any members of the bag that are not in the given
++ * collection, respecting cardinality. That is, if the given
++ * collection <code>coll</code> contains <code>n</code> copies of a
++ * given object and the bag has <code>m > n</code> copies, then
++ * delete <code>m - n</code> copies from the bag. In addition, if
++ * <code>e</code> is an object in the bag but
++ * <code>!coll.contains(e)</code>, then remove <code>e</code> and any
++ * of its copies.
++ * <p/>
++ * <P>The {@link Collection#retainAll(Collection)} method specifies
++ * that cardinality should <i>not</i> be respected; this method should
++ * keep <i>all</i> occurrences of every object contained in the
++ * given collection.
++ *
++ * @param coll the collection to retain
++ * @return <code>true</code> if this call changed the collection
++ */
++ boolean retainAll(Collection<?> coll);
++
++ /**
++ * Returns an {@link Iterator} over the entire set of members,
++ * including copies due to cardinality. This iterator is fail-fast
++ * and will not tolerate concurrent modifications.
++ *
++ * @return iterator over all elements in the Bag
++ */
++ Iterator<E> iterator();
++
++ // The following is not part of the formal Bag interface, however where possible
++ // Bag implementations should follow these comments.
++ // /**
++ // * Compares this Bag to another.
++ // * This Bag equals another Bag if it contains the same number of occurrences of
++ // * the same elements.
++ // * This equals definition is compatible with the Set interface.
++ // *
++ // * @param obj the Bag to compare to
++ // * @return true if equal
++ // */
++ // boolean equals(Object obj);
++ //
++ // /**
++ // * Gets a hash code for the Bag compatible with the definition of equals.
++ // * The hash code is defined as the sum total of a hash code for each element.
++ // * The per element hash code is defined as
++ // * <code>(e==null ? 0 : e.hashCode()) ^ noOccurances)</code>.
++ // * This hash code definition is compatible with the Set interface.
++ // *
++ // * @return the hash code of the Bag
++ // */
++ // int hashCode();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/BagUtils.java
+@@ -0,0 +1,236 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.bag.*;
++
++/**
++ * Provides utility methods and decorators for
++ * {@link Bag} and {@link SortedBag} instances.
++ *
++ * @author Paul Jack
++ * @author Stephen Colebourne
++ * @author Andrew Freeman
++ * @author Matt Hall, John Watkinson, Matthew Hawthorne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 2.1
++ */
++public class BagUtils {
++
++ /**
++ * An empty unmodifiable bag.
++ */
++ public static final Bag EMPTY_BAG = UnmodifiableBag.decorate(new HashBag());
++
++ /**
++ * An empty unmodifiable sorted bag.
++ */
++ public static final Bag EMPTY_SORTED_BAG = UnmodifiableSortedBag.decorate(new TreeBag());
++
++ /**
++ * Instantiation of BagUtils is not intended or required.
++ * However, some tools require an instance to operate.
++ */
++ public BagUtils() {
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a synchronized (thread-safe) bag backed by the given bag.
++ * In order to guarantee serial access, it is critical that all
++ * access to the backing bag is accomplished through the returned bag.
++ * <p/>
++ * It is imperative that the user manually synchronize on the returned
++ * bag when iterating over it:
++ * <p/>
++ * <pre>
++ * Bag bag = BagUtils.synchronizedBag(new HashBag());
++ * ...
++ * synchronized(bag) {
++ * Iterator i = bag.iterator(); // Must be in synchronized block
++ * while (i.hasNext())
++ * foo(i.next());
++ * }
++ * }
++ * </pre>
++ * <p/>
++ * Failure to follow this advice may result in non-deterministic
++ * behavior.
++ *
++ * @param bag the bag to synchronize, must not be null
++ * @return a synchronized bag backed by that bag
++ * @throws IllegalArgumentException if the Bag is null
++ */
++ public static <E> Bag<E> synchronizedBag(Bag<E> bag) {
++ return SynchronizedBag.decorate(bag);
++ }
++
++ /**
++ * Returns an unmodifiable view of the given bag. Any modification
++ * attempts to the returned bag will raise an
++ * {@link UnsupportedOperationException}.
++ *
++ * @param bag the bag whose unmodifiable view is to be returned, must not be null
++ * @return an unmodifiable view of that bag
++ * @throws IllegalArgumentException if the Bag is null
++ */
++ public static <E> Bag<E> unmodifiableBag(Bag<E> bag) {
++ return UnmodifiableBag.decorate(bag);
++ }
++
++ /**
++ * Returns a predicated (validating) bag backed by the given bag.
++ * <p/>
++ * Only objects that pass the test in the given predicate can be added to the bag.
++ * Trying to add an invalid object results in an IllegalArgumentException.
++ * It is important not to use the original bag after invoking this method,
++ * as it is a backdoor for adding invalid objects.
++ *
++ * @param bag the bag to predicate, must not be null
++ * @param predicate the predicate for the bag, must not be null
++ * @return a predicated bag backed by the given bag
++ * @throws IllegalArgumentException if the Bag or Predicate is null
++ */
++ public static <E> Bag<E> predicatedBag(Bag<E> bag, Predicate<? super E> predicate) {
++ return PredicatedBag.decorate(bag, predicate);
++ }
++
++ /**
++ * Returns a typed bag backed by the given bag.
++ * <p/>
++ * Only objects of the specified type can be added to the bag.
++ *
++ * @param bag the bag to limit to a specific type, must not be null
++ * @param type the type of objects which may be added to the bag
++ * @return a typed bag backed by the specified bag
++ * @deprecated Java 1.5 generics makes this method no longer useful.
++ */
++ public static <E> Bag<E> typedBag(Bag<E> bag, Class<E> type) {
++ return TypedBag.decorate(bag, type);
++ }
++
++ /**
++ * Returns a transformed bag backed by the given bag.
++ * <p/>
++ * Each object is passed through the transformer as it is added to the
++ * Bag. It is important not to use the original bag after invoking this
++ * method, as it is a backdoor for adding untransformed objects.
++ *
++ * @param bag the bag to predicate, must not be null
++ * @param transformer the transformer for the bag, must not be null
++ * @return a transformed bag backed by the given bag
++ * @throws IllegalArgumentException if the Bag or Transformer is null
++ * @deprecated TransformedCollections are not type-safe in Java 1.5.
++ */
++ public static <I,O> Bag<O> transformedBag(Bag<I> bag, Transformer<I, O> transformer) {
++ return TransformedBag.decorate(bag, transformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a synchronized (thread-safe) sorted bag backed by the given
++ * sorted bag.
++ * In order to guarantee serial access, it is critical that all
++ * access to the backing bag is accomplished through the returned bag.
++ * <p/>
++ * It is imperative that the user manually synchronize on the returned
++ * bag when iterating over it:
++ * <p/>
++ * <pre>
++ * SortedBag bag = BagUtils.synchronizedSortedBag(new TreeBag());
++ * ...
++ * synchronized(bag) {
++ * Iterator i = bag.iterator(); // Must be in synchronized block
++ * while (i.hasNext())
++ * foo(i.next());
++ * }
++ * }
++ * </pre>
++ * <p/>
++ * Failure to follow this advice may result in non-deterministic
++ * behavior.
++ *
++ * @param bag the bag to synchronize, must not be null
++ * @return a synchronized bag backed by that bag
++ * @throws IllegalArgumentException if the SortedBag is null
++ */
++ public static <E> SortedBag<E> synchronizedSortedBag(SortedBag<E> bag) {
++ return SynchronizedSortedBag.decorate(bag);
++ }
++
++ /**
++ * Returns an unmodifiable view of the given sorted bag. Any modification
++ * attempts to the returned bag will raise an
++ * {@link UnsupportedOperationException}.
++ *
++ * @param bag the bag whose unmodifiable view is to be returned, must not be null
++ * @return an unmodifiable view of that bag
++ * @throws IllegalArgumentException if the SortedBag is null
++ */
++ public static <E> SortedBag<E> unmodifiableSortedBag(SortedBag<E> bag) {
++ return UnmodifiableSortedBag.decorate(bag);
++ }
++
++ /**
++ * Returns a predicated (validating) sorted bag backed by the given sorted bag.
++ * <p/>
++ * Only objects that pass the test in the given predicate can be added to the bag.
++ * Trying to add an invalid object results in an IllegalArgumentException.
++ * It is important not to use the original bag after invoking this method,
++ * as it is a backdoor for adding invalid objects.
++ *
++ * @param bag the sorted bag to predicate, must not be null
++ * @param predicate the predicate for the bag, must not be null
++ * @return a predicated bag backed by the given bag
++ * @throws IllegalArgumentException if the SortedBag or Predicate is null
++ */
++ public static <E> SortedBag<E> predicatedSortedBag(SortedBag<E> bag, Predicate<? super E> predicate) {
++ return PredicatedSortedBag.decorate(bag, predicate);
++ }
++
++ /**
++ * Returns a typed sorted bag backed by the given bag.
++ * <p/>
++ * Only objects of the specified type can be added to the bag.
++ *
++ * @param bag the bag to limit to a specific type, must not be null
++ * @param type the type of objects which may be added to the bag
++ * @return a typed bag backed by the specified bag
++ * @deprecated Java 1.5 generics makes this method no longer useful.
++ */
++ public static <E> SortedBag<E> typedSortedBag(SortedBag<E> bag, Class<E> type) {
++ return TypedSortedBag.decorate(bag, type);
++ }
++
++ /**
++ * Returns a transformed sorted bag backed by the given bag.
++ * <p/>
++ * Each object is passed through the transformer as it is added to the
++ * Bag. It is important not to use the original bag after invoking this
++ * method, as it is a backdoor for adding untransformed objects.
++ *
++ * @param bag the bag to predicate, must not be null
++ * @param transformer the transformer for the bag, must not be null
++ * @return a transformed bag backed by the given bag
++ * @throws IllegalArgumentException if the Bag or Transformer is null
++ * @deprecated This breaks the java.util.Collection interface in Java 1.5. It is recommended that it not be used.
++ */
++ public static <I,O> SortedBag<O> transformedSortedBag(SortedBag<I> bag, Transformer<I, O> transformer) {
++ return TransformedSortedBag.decorate(bag, transformer);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/BeanMap.java
+@@ -0,0 +1,733 @@
++// GenericsNote: Converted to <String,Object>.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.keyvalue.AbstractMapEntry;
++import org.apache.commons.collections15.list.UnmodifiableList;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++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.*;
++
++/**
++ * 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
++ * <p/>
++ *
++ * @author James Strachan
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 1.0
++ */
++public class BeanMap extends AbstractMap<String, Object> implements Cloneable {
++
++ private transient Object bean;
++
++ private transient HashMap<String, Method> readMethods = new HashMap<String, Method>();
++ private transient HashMap<String, Method> writeMethods = new HashMap<String, Method>();
++ private transient HashMap<String, Class> types = new HashMap<String, Class>();
++
++ /**
++ * 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:
++ * <p/>
++ * <ul>
++ * <li>If there is no underlying bean, return a cloned BeanMap without a
++ * bean.
++ * <p/>
++ * <li>Since there is an underlying bean, try to instantiate a new bean of
++ * the same type using Class.newInstance().
++ * <p/>
++ * <li>If the instantiation fails, throw a CloneNotSupportedException
++ * <p/>
++ * <li>Clone the bean map and set the newly instantiated bean as the
++ * underlying bean for the bean map.
++ * <p/>
++ * <li>Copy each property that is both readable and writable from the
++ * existing object to a cloned bean map.
++ * <p/>
++ * <li>If anything fails along the way, throw a
++ * CloneNotSupportedException.
++ * <p/>
++ * <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<String> readableKeys = readMethods.keySet().iterator();
++ while (readableKeys.hasNext()) {
++ String 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<String> readableKeys = map.readMethods.keySet().iterator();
++ while (readableKeys.hasNext()) {
++ String 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(String 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(String 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(String 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<String> 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<Entry<String, Object>> entrySet() {
++ return UnmodifiableSet.decorate(new AbstractSet<Entry<String, Object>>() {
++ public Iterator<Entry<String, Object>> 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<Object> 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<String> keyIterator() {
++ return readMethods.keySet().iterator();
++ }
++
++ /**
++ * Convenience method for getting an iterator over the values.
++ *
++ * @return an iterator over the values
++ */
++ public Iterator<Object> valueIterator() {
++ final Iterator<String> iter = keyIterator();
++ return new Iterator<Object>() {
++ 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<Entry<String, Object>> entryIterator() {
++ final Iterator<String> iter = keyIterator();
++ return new Iterator<Entry<String, Object>>() {
++ public boolean hasNext() {
++ return iter.hasNext();
++ }
++
++ public Entry<String, Object> next() {
++ String 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 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
++ //-------------------------------------------------------------------------
++
++ /**
++ * 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 (writeMethods != 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(String key, Object oldValue, Object newValue) {
++ }
++
++ // Implementation classes
++ //-------------------------------------------------------------------------
++
++ /**
++ * Map entry used by {@link BeanMap}.
++ */
++ protected static class MyMapEntry extends AbstractMapEntry<String, Object> {
++ 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, String 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) {
++ String 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>
++ * <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>
++ * <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();
++ }
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/BidiMap.java
+@@ -0,0 +1,161 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.Set;
++
++/**
++ * Defines a map that allows bidirectional lookup between key and values.
++ * <p/>
++ * This extended <code>Map</code> represents a mapping where a key may
++ * lookup a value and a value may lookup a key with equal ease.
++ * This interface extends <code>Map</code> and so may be used anywhere a map
++ * is required. The interface provides an inverse map view, enabling
++ * full access to both directions of the <code>BidiMap</code>.
++ * <p/>
++ * Implementations should allow a value to be looked up from a key and
++ * a key to be looked up from a value with equal performance.
++ * <p/>
++ * This map enforces the restriction that there is a 1:1 relation between
++ * keys and values, meaning that multiple keys cannot map to the same value.
++ * This is required so that "inverting" the map results in a map without
++ * duplicate keys. See the {@link #put} method description for more information.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface BidiMap <K,V> extends IterableMap<K, V> {
++
++ /**
++ * Obtains a <code>MapIterator</code> over the map.
++ * <p/>
++ * A map iterator is an efficient way of iterating over maps.
++ * It does not require that the map is stored using Map Entry objects
++ * which can increase performance.
++ * <pre>
++ * BidiMap map = new DualHashBidiMap();
++ * MapIterator it = map.mapIterator();
++ * while (it.hasNext()) {
++ * Object key = it.next();
++ * Object value = it.getValue();
++ * it.setValue("newValue");
++ * }
++ * </pre>
++ *
++ * @return a map iterator
++ */
++ MapIterator<K, V> mapIterator();
++
++ /**
++ * Puts the key-value pair into the map, replacing any previous pair.
++ * <p/>
++ * When adding a key-value pair, the value may already exist in the map
++ * against a different key. That mapping is removed, to ensure that the
++ * value only occurs once in the inverse map.
++ * <pre>
++ * BidiMap map1 = new DualHashBidiMap();
++ * map.put("A","B"); // contains A mapped to B, as per Map
++ * map.put("A","C"); // contains A mapped to C, as per Map
++ * <p/>
++ * BidiMap map2 = new DualHashBidiMap();
++ * map.put("A","B"); // contains A mapped to B, as per Map
++ * map.put("C","B"); // contains C mapped to B, key A is removed
++ * </pre>
++ *
++ * @param key the key to store
++ * @param value the value to store
++ * @return the previous value mapped to this key
++ * @throws UnsupportedOperationException if the <code>put</code> method is not supported
++ * @throws ClassCastException (optional) if the map limits the type of the
++ * value and the specified value is inappropriate
++ * @throws IllegalArgumentException (optional) if the map limits the values
++ * in some way and the value was invalid
++ * @throws NullPointerException (optional) if the map limits the values to
++ * non-null and null was specified
++ */
++ V put(K key, V value);
++
++ /**
++ * Gets the key that is currently mapped to the specified value.
++ * <p/>
++ * If the value is not contained in the map, <code>null</code> is returned.
++ * <p/>
++ * Implementations should seek to make this method perform equally as well
++ * as <code>get(Object)</code>.
++ *
++ * @param value the value to find the key for
++ * @return the mapped key, or <code>null</code> if not found
++ * @throws ClassCastException (optional) if the map limits the type of the
++ * value and the specified value is inappropriate
++ * @throws NullPointerException (optional) if the map limits the values to
++ * non-null and null was specified
++ */
++ K getKey(Object value);
++
++ /**
++ * Removes the key-value pair that is currently mapped to the specified
++ * value (optional operation).
++ * <p/>
++ * If the value is not contained in the map, <code>null</code> is returned.
++ * <p/>
++ * Implementations should seek to make this method perform equally as well
++ * as <code>remove(Object)</code>.
++ *
++ * @param value the value to find the key-value pair for
++ * @return the key that was removed, <code>null</code> if nothing removed
++ * @throws ClassCastException (optional) if the map limits the type of the
++ * value and the specified value is inappropriate
++ * @throws NullPointerException (optional) if the map limits the values to
++ * non-null and null was specified
++ * @throws UnsupportedOperationException if this method is not supported
++ * by the implementation
++ */
++ K removeValue(Object value);
++
++ /**
++ * Gets a view of this map where the keys and values are reversed.
++ * <p/>
++ * Changes to one map will be visible in the other and vice versa.
++ * This enables both directions of the map to be accessed as a <code>Map</code>.
++ * <p/>
++ * Implementations should seek to avoid creating a new object every time this
++ * method is called. See <code>AbstractMap.values()</code> etc. Calling this
++ * method on the inverse map should return the original.
++ *
++ * @return an inverted bidirectional map
++ */
++ BidiMap<V, K> inverseBidiMap();
++
++
++ /**
++ * Returns a set view of the values contained in this BidiMap. The
++ * set is backed by the map, so changes to the map are reflected in
++ * the collection, and vice-versa. If the map is modified while an
++ * iteration over the collection is in progress (except through the
++ * iterator's own <tt>remove</tt> operation), the results of the
++ * iteration are undefined. The collection supports element removal,
++ * which removes the corresponding mapping from the map, via the
++ * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
++ * <tt>removeAll</tt>, <tt>retainAll</tt> and <tt>clear</tt> operations.
++ * It does not support the add or <tt>addAll</tt> operations.
++ *
++ * @return a Set view of the values contained in this map.
++ */
++ Set<V> values();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/BoundedCollection.java
+@@ -0,0 +1,51 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.Collection;
++
++/**
++ * Defines a collection that is bounded in size.
++ * <p/>
++ * The size of the collection can vary, but it can never exceed a preset
++ * maximum number of elements. This interface allows the querying of details
++ * associated with the maximum number of elements.
++ *
++ * @author Matt Hall, John Watkinson, Herve Quiroz
++ * @author Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @see CollectionUtils#isFull
++ * @see CollectionUtils#maxSize
++ * @since Commons Collections 3.0
++ */
++public interface BoundedCollection <E> extends Collection<E> {
++
++ /**
++ * Returns true if this collection is full and no new elements can be added.
++ *
++ * @return <code>true</code> if the collection is full
++ */
++ boolean isFull();
++
++ /**
++ * Gets the maximum size of the collection (the bound).
++ *
++ * @return the maximum number of elements the collection can hold
++ */
++ int maxSize();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/BoundedMap.java
+@@ -0,0 +1,48 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.Map;
++
++/**
++ * Defines a map that is bounded in size.
++ * <p/>
++ * The size of the map can vary, but it can never exceed a preset
++ * maximum number of elements. This interface allows the querying of details
++ * associated with the maximum number of elements.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface BoundedMap <K,V> extends Map<K, V> {
++
++ /**
++ * Returns true if this map is full and no new elements can be added.
++ *
++ * @return <code>true</code> if the map is full
++ */
++ boolean isFull();
++
++ /**
++ * Gets the maximum size of the map (the bound).
++ *
++ * @return the maximum number of elements the map can hold
++ */
++ int maxSize();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/Buffer.java
+@@ -0,0 +1,63 @@
++// // GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.Collection;
++
++/**
++ * Defines a collection that allows objects to be removed in some well-defined order.
++ * <p/>
++ * The removal order can be based on insertion order (eg, a FIFO queue or a
++ * LIFO stack), on access order (eg, an LRU cache), on some arbitrary comparator
++ * (eg, a priority queue) or on any other well-defined ordering.
++ * <p/>
++ * Note that the removal order is not necessarily the same as the iteration
++ * order. A <code>Buffer</code> implementation may have equivalent removal
++ * and iteration orders, but this is not required.
++ * <p/>
++ * This interface does not specify any behavior for
++ * {@link Object#equals(Object)} and {@link Object#hashCode} methods. It
++ * is therefore possible for a <code>Buffer</code> implementation to also
++ * also implement {@link java.util.List}, {@link java.util.Set} or
++ * {@link Bag}.
++ *
++ * @author Avalon
++ * @author Berin Loritsch
++ * @author Paul Jack
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 2.1
++ */
++public interface Buffer <E> extends Collection<E> {
++
++ /**
++ * Gets and removes the next object from the buffer.
++ *
++ * @return the next object in the buffer, which is also removed
++ * @throws BufferUnderflowException if the buffer is already empty
++ */
++ E remove();
++
++ /**
++ * Gets the next object from the buffer without removing it.
++ *
++ * @return the next object in the buffer, which is not removed
++ * @throws BufferUnderflowException if the buffer is empty
++ */
++ E get();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/BufferOverflowException.java
+@@ -0,0 +1,75 @@
++// GenericsNote: No conversion needed.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++/**
++ * The BufferOverflowException is used when the buffer's capacity has been
++ * exceeded.
++ *
++ * @author Avalon
++ * @author <a href="mailto:bloritsch at apache.org">Berin Loritsch</a>
++ * @author <a href="mailto:jefft at apache.org">Jeff Turner</a>
++ * @author Paul Jack
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 2.1
++ */
++public class BufferOverflowException extends RuntimeException {
++
++ /**
++ * The root cause throwable
++ */
++ private final Throwable throwable;
++
++ /**
++ * Constructs a new <code>BufferOverflowException</code>.
++ */
++ public BufferOverflowException() {
++ super();
++ throwable = null;
++ }
++
++ /**
++ * Construct a new <code>BufferOverflowException</code>.
++ *
++ * @param message the detail message for this exception
++ */
++ public BufferOverflowException(String message) {
++ this(message, null);
++ }
++
++ /**
++ * Construct a new <code>BufferOverflowException</code>.
++ *
++ * @param message the detail message for this exception
++ * @param exception the root cause of the exception
++ */
++ public BufferOverflowException(String message, Throwable exception) {
++ super(message);
++ throwable = exception;
++ }
++
++ /**
++ * Gets the root cause of the exception.
++ *
++ * @return the root cause
++ */
++ public final Throwable getCause() {
++ return throwable;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/BufferUnderflowException.java
+@@ -0,0 +1,78 @@
++// GenericsNote: No conversion necessary.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.NoSuchElementException;
++
++/**
++ * The BufferUnderflowException is used when the buffer is already empty.
++ * <p/>
++ * NOTE: From version 3.0, this exception extends NoSuchElementException.
++ *
++ * @author Avalon
++ * @author Berin Loritsch
++ * @author Jeff Turner
++ * @author Paul Jack
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 2.1
++ */
++public class BufferUnderflowException extends NoSuchElementException {
++
++ /**
++ * The root cause throwable
++ */
++ private final Throwable throwable;
++
++ /**
++ * Constructs a new <code>BufferUnderflowException</code>.
++ */
++ public BufferUnderflowException() {
++ super();
++ throwable = null;
++ }
++
++ /**
++ * Construct a new <code>BufferUnderflowException</code>.
++ *
++ * @param message the detail message for this exception
++ */
++ public BufferUnderflowException(String message) {
++ this(message, null);
++ }
++
++ /**
++ * Construct a new <code>BufferUnderflowException</code>.
++ *
++ * @param message the detail message for this exception
++ * @param exception the root cause of the exception
++ */
++ public BufferUnderflowException(String message, Throwable exception) {
++ super(message);
++ throwable = exception;
++ }
++
++ /**
++ * Gets the root cause of the exception.
++ *
++ * @return the root cause
++ */
++ public final Throwable getCause() {
++ return throwable;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/BufferUtils.java
+@@ -0,0 +1,142 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.buffer.*;
++
++/**
++ * Provides utility methods and decorators for {@link Buffer} instances.
++ *
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @author Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 2.1
++ */
++public class BufferUtils {
++
++ /**
++ * An empty unmodifiable buffer.
++ */
++ public static final Buffer EMPTY_BUFFER = UnmodifiableBuffer.decorate(new ArrayStack(1));
++
++ /**
++ * <code>BufferUtils</code> should not normally be instantiated.
++ */
++ public BufferUtils() {
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a synchronized buffer backed by the given buffer.
++ * Much like the synchronized collections15 returned by
++ * {@link java.util.Collections}, you must manually synchronize on
++ * the returned buffer's iterator to avoid non-deterministic behavior:
++ * <p/>
++ * <pre>
++ * Buffer b = BufferUtils.synchronizedBuffer(myBuffer);
++ * synchronized (b) {
++ * Iterator i = b.iterator();
++ * while (i.hasNext()) {
++ * process (i.next());
++ * }
++ * }
++ * </pre>
++ *
++ * @param buffer the buffer to synchronize, must not be null
++ * @return a synchronized buffer backed by that buffer
++ * @throws IllegalArgumentException if the Buffer is null
++ */
++ public static <E> Buffer<E> synchronizedBuffer(Buffer<E> buffer) {
++ return SynchronizedBuffer.decorate(buffer);
++ }
++
++ /**
++ * Returns a synchronized buffer backed by the given buffer that will
++ * block on {@link Buffer#get()} and {@link Buffer#remove()} operations.
++ * If the buffer is empty, then the {@link Buffer#get()} and
++ * {@link Buffer#remove()} operations will block until new elements
++ * are added to the buffer, rather than immediately throwing a
++ * <code>BufferUnderflowException</code>.
++ *
++ * @param buffer the buffer to synchronize, must not be null
++ * @return a blocking buffer backed by that buffer
++ * @throws IllegalArgumentException if the Buffer is null
++ */
++ public static <E> Buffer<E> blockingBuffer(Buffer<E> buffer) {
++ return BlockingBuffer.decorate(buffer);
++ }
++
++ /**
++ * Returns an unmodifiable buffer backed by the given buffer.
++ *
++ * @param buffer the buffer to make unmodifiable, must not be null
++ * @return an unmodifiable buffer backed by that buffer
++ * @throws IllegalArgumentException if the Buffer is null
++ */
++ public static <E> Buffer<E> unmodifiableBuffer(Buffer<E> buffer) {
++ return UnmodifiableBuffer.decorate(buffer);
++ }
++
++ /**
++ * Returns a predicated (validating) buffer backed by the given buffer.
++ * <p/>
++ * Only objects that pass the test in the given predicate can be added to the buffer.
++ * Trying to add an invalid object results in an IllegalArgumentException.
++ * It is important not to use the original buffer after invoking this method,
++ * as it is a backdoor for adding invalid objects.
++ *
++ * @param buffer the buffer to predicate, must not be null
++ * @param predicate the predicate used to evaluate new elements, must not be null
++ * @return a predicated buffer
++ * @throws IllegalArgumentException if the Buffer or Predicate is null
++ */
++ public static <E> Buffer<E> predicatedBuffer(Buffer<E> buffer, Predicate<E> predicate) {
++ return PredicatedBuffer.decorate(buffer, predicate);
++ }
++
++ /**
++ * Returns a typed buffer backed by the given buffer.
++ * <p/>
++ * Only elements of the specified type can be added to the buffer.
++ *
++ * @param buffer the buffer to predicate, must not be null
++ * @param type the type to allow into the buffer, must not be null
++ * @return a typed buffer
++ * @throws IllegalArgumentException if the buffer or type is null
++ * @deprecated No longer required with Java 1.5 Generics.
++ */
++ public static <E> Buffer<E> typedBuffer(Buffer<E> buffer, Class<E> type) {
++ return TypedBuffer.decorate(buffer, type);
++ }
++
++ /**
++ * Returns a transformed buffer backed by the given buffer.
++ * <p/>
++ * Each object is passed through the transformer as it is added to the
++ * Buffer. It is important not to use the original buffer after invoking this
++ * method, as it is a backdoor for adding untransformed objects.
++ *
++ * @param buffer the buffer to predicate, must not be null
++ * @param transformer the transformer for the buffer, must not be null
++ * @return a transformed buffer backed by the given buffer
++ * @throws IllegalArgumentException if the Buffer or Transformer is null
++ */
++ public static <I,O> Buffer<O> transformedBuffer(Buffer<I> buffer, Transformer<I, O> transformer) {
++ return TransformedBuffer.decorate(buffer, transformer);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/Closure.java
+@@ -0,0 +1,46 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++/**
++ * Defines a functor interface implemented by classes that do something.
++ * <p/>
++ * A <code>Closure</code> represents a block of code which is executed from
++ * inside some block, function or iteration. It operates an input object.
++ * <p/>
++ * Standard implementations of common closures are provided by
++ * {@link ClosureUtils}. These include method invokation and for/while loops.
++ *
++ * @author James Strachan
++ * @author Nicola Ken Barozzi
++ * @author Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 1.0
++ */
++public interface Closure <T> {
++
++ /**
++ * Performs an action on the specified input object.
++ *
++ * @param input the input to execute on
++ * @throws ClassCastException (runtime) if the input is the wrong class
++ * @throws IllegalArgumentException (runtime) if the input is invalid
++ * @throws FunctorException (runtime) if any other error occurs
++ */
++ public void execute(T input);
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/ClosureUtils.java
+@@ -0,0 +1,326 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.functors.*;
++
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.Map;
++
++/**
++ * <code>ClosureUtils</code> provides reference implementations and utilities
++ * for the Closure functor interface. The supplied closures are:
++ * <ul>
++ * <li>Invoker - invokes a method on the input object
++ * <li>For - repeatedly calls a closure for a fixed number of times
++ * <li>While - repeatedly calls a closure while a predicate is true
++ * <li>DoWhile - repeatedly calls a closure while a predicate is true
++ * <li>Chained - chains two or more closures together
++ * <li>Switch - calls one closure based on one or more predicates
++ * <li>SwitchMap - calls one closure looked up from a Map
++ * <li>Transformer - wraps a Transformer as a Closure
++ * <li>NOP - does nothing
++ * <li>Exception - always throws an exception
++ * </ul>
++ * All the supplied closures are Serializable.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public class ClosureUtils {
++
++ /**
++ * This class is not normally instantiated.
++ */
++ public ClosureUtils() {
++ super();
++ }
++
++ /**
++ * Gets a Closure that always throws an exception.
++ * This could be useful during testing as a placeholder.
++ *
++ * @return the closure
++ * @see org.apache.commons.collections15.functors.ExceptionClosure
++ */
++ public static Closure exceptionClosure() {
++ return ExceptionClosure.INSTANCE;
++ }
++
++ /**
++ * Gets a Closure that will do nothing.
++ * This could be useful during testing as a placeholder.
++ *
++ * @return the closure
++ * @see org.apache.commons.collections15.functors.NOPClosure
++ */
++ public static Closure nopClosure() {
++ return NOPClosure.INSTANCE;
++ }
++
++ /**
++ * Creates a Closure that calls a Transformer each time it is called.
++ * The transformer will be called using the closure's input object.
++ * The transformer's result will be ignored.
++ *
++ * @param transformer the transformer to run each time in the closure, null means nop
++ * @return the closure
++ * @see org.apache.commons.collections15.functors.TransformerClosure
++ */
++ public static <I,O> Closure<I> asClosure(Transformer<I, O> transformer) {
++ return TransformerClosure.getInstance(transformer);
++ }
++
++ /**
++ * Creates a Closure that will call the closure <code>count</code> times.
++ * <p/>
++ * A null closure or zero count returns the <code>NOPClosure</code>.
++ *
++ * @param count the number of times to loop
++ * @param closure the closure to call repeatedly
++ * @return the <code>for</code> closure
++ * @see org.apache.commons.collections15.functors.ForClosure
++ */
++ public static <T> Closure<T> forClosure(int count, Closure<T> closure) {
++ return ForClosure.getInstance(count, closure);
++ }
++
++ /**
++ * Creates a Closure that will call the closure repeatedly until the
++ * predicate returns false.
++ *
++ * @param predicate the predicate to use as an end of loop test, not null
++ * @param closure the closure to call repeatedly, not null
++ * @return the <code>while</code> closure
++ * @throws IllegalArgumentException if either argument is null
++ * @see org.apache.commons.collections15.functors.WhileClosure
++ */
++ public static <T> Closure<T> whileClosure(Predicate<? super T> predicate, Closure<? super T> closure) {
++ return WhileClosure.<T>getInstance(predicate, closure, false);
++ }
++
++ /**
++ * Creates a Closure that will call the closure once and then repeatedly
++ * until the predicate returns false.
++ *
++ * @param closure the closure to call repeatedly, not null
++ * @param predicate the predicate to use as an end of loop test, not null
++ * @return the <code>do-while</code> closure
++ * @throws IllegalArgumentException if either argument is null
++ * @see org.apache.commons.collections15.functors.WhileClosure
++ */
++ public static <T> Closure<T> doWhileClosure(Closure<? super T> closure, Predicate<? super T> predicate) {
++ return WhileClosure.<T>getInstance(predicate, closure, true);
++ }
++
++ /**
++ * Creates a Closure that will invoke a specific method on the closure's
++ * input object by reflection.
++ *
++ * @param methodName the name of the method
++ * @return the <code>invoker</code> closure
++ * @throws IllegalArgumentException if the method name is null
++ * @see org.apache.commons.collections15.functors.InvokerTransformer
++ * @see org.apache.commons.collections15.functors.TransformerClosure
++ */
++ public static Closure invokerClosure(String methodName) {
++ // reuse transformer as it has caching - this is lazy really, should have inner class here
++ return asClosure(InvokerTransformer.getInstance(methodName));
++ }
++
++ /**
++ * Creates a Closure that will invoke a specific method on the closure's
++ * input object by reflection.
++ *
++ * @param methodName the name of the method
++ * @param paramTypes the parameter types
++ * @param args the arguments
++ * @return the <code>invoker</code> closure
++ * @throws IllegalArgumentException if the method name is null
++ * @throws IllegalArgumentException if the paramTypes and args don't match
++ * @see org.apache.commons.collections15.functors.InvokerTransformer
++ * @see org.apache.commons.collections15.functors.TransformerClosure
++ */
++ public static Closure invokerClosure(String methodName, Class[] paramTypes, Object[] args) {
++ // reuse transformer as it has caching - this is lazy really, should have inner class here
++ return asClosure(InvokerTransformer.getInstance(methodName, paramTypes, args));
++ }
++
++ /**
++ * Create a new Closure that calls two Closures, passing the result of
++ * the first into the second.
++ *
++ * @param closure1 the first closure
++ * @param closure2 the second closure
++ * @return the <code>chained</code> closure
++ * @throws IllegalArgumentException if either closure is null
++ * @see org.apache.commons.collections15.functors.ChainedClosure
++ */
++ public static <T> Closure<T> chainedClosure(Closure<T> closure1, Closure<T> closure2) {
++ return ChainedClosure.<T>getInstance(closure1, closure2);
++ }
++
++ /**
++ * Create a new Closure that calls each closure in turn, passing the
++ * result into the next closure.
++ *
++ * @param closures an array of closures to chain
++ * @return the <code>chained</code> closure
++ * @throws IllegalArgumentException if the closures array is null
++ * @throws IllegalArgumentException if any closure in the array is null
++ * @see org.apache.commons.collections15.functors.ChainedClosure
++ */
++ public static <T> Closure<T> chainedClosure(Closure<T>[] closures) {
++ return ChainedClosure.getInstance(closures);
++ }
++
++ /**
++ * Create a new Closure that calls each closure in turn, passing the
++ * result into the next closure. The ordering is that of the iterator()
++ * method on the collection.
++ *
++ * @param closures a collection of closures to chain
++ * @return the <code>chained</code> closure
++ * @throws IllegalArgumentException if the closures collection is null
++ * @throws IllegalArgumentException if the closures collection is empty
++ * @throws IllegalArgumentException if any closure in the collection is null
++ * @see org.apache.commons.collections15.functors.ChainedClosure
++ */
++ public static <T> Closure<T> chainedClosure(Collection<T> closures) {
++ return ChainedClosure.getInstance(closures);
++ }
++
++ /**
++ * Create a new Closure that calls one of two closures depending
++ * on the specified predicate.
++ *
++ * @param predicate the predicate to switch on
++ * @param trueClosure the closure called if the predicate is true
++ * @param falseClosure the closure called if the predicate is false
++ * @return the <code>switch</code> closure
++ * @throws IllegalArgumentException if the predicate is null
++ * @throws IllegalArgumentException if either closure is null
++ * @see org.apache.commons.collections15.functors.IfClosure
++ */
++ public static <T> Closure<T> ifClosure(Predicate<? super T> predicate, Closure<? super T> trueClosure, Closure<? super T> falseClosure) {
++ return IfClosure.<T>getInstance(predicate, trueClosure, falseClosure);
++ }
++
++ /**
++ * Create a new Closure that calls one of the closures depending
++ * on the predicates.
++ * <p/>
++ * The closure at array location 0 is called if the predicate at array
++ * location 0 returned true. Each predicate is evaluated
++ * until one returns true.
++ *
++ * @param predicates an array of predicates to check, not null
++ * @param closures an array of closures to call, not null
++ * @return the <code>switch</code> closure
++ * @throws IllegalArgumentException if the either array is null
++ * @throws IllegalArgumentException if any element in the arrays is null
++ * @throws IllegalArgumentException if the arrays are different sizes
++ * @see org.apache.commons.collections15.functors.SwitchClosure
++ */
++ public static <T> Closure<T> switchClosure(Predicate<? super T>[] predicates, Closure<? super T>[] closures) {
++ return SwitchClosure.<T>getInstance(predicates, closures, null);
++ }
++
++ /**
++ * Create a new Closure that calls one of the closures depending
++ * on the predicates.
++ * <p/>
++ * The closure at array location 0 is called if the predicate at array
++ * location 0 returned true. Each predicate is evaluated
++ * until one returns true. If no predicates evaluate to true, the default
++ * closure is called.
++ *
++ * @param predicates an array of predicates to check, not null
++ * @param closures an array of closures to call, not null
++ * @param defaultClosure the default to call if no predicate matches
++ * @return the <code>switch</code> closure
++ * @throws IllegalArgumentException if the either array is null
++ * @throws IllegalArgumentException if any element in the arrays is null
++ * @throws IllegalArgumentException if the arrays are different sizes
++ * @see org.apache.commons.collections15.functors.SwitchClosure
++ */
++ public static <T> Closure<T> switchClosure(Predicate<? super T>[] predicates, Closure<? super T>[] closures, Closure<? super T> defaultClosure) {
++ return SwitchClosure.<T>getInstance(predicates, closures, defaultClosure);
++ }
++
++ /**
++ * Create a new Closure that calls one of the closures depending
++ * on the predicates.
++ * <p/>
++ * The Map consists of Predicate keys and Closure values. A closure
++ * is called if its matching predicate returns true. Each predicate is evaluated
++ * until one returns true. If no predicates evaluate to true, the default
++ * closure is called. The default closure is set in the map with a
++ * null key. The ordering is that of the iterator() method on the entryset
++ * collection of the map.
++ *
++ * @param predicatesAndClosures a map of predicates to closures
++ * @return the <code>switch</code> closure
++ * @throws IllegalArgumentException if the map is null
++ * @throws IllegalArgumentException if the map is empty
++ * @throws IllegalArgumentException if any closure in the map is null
++ * @throws ClassCastException if the map elements are of the wrong type
++ * @see org.apache.commons.collections15.functors.SwitchClosure
++ */
++ public static <T> Closure<T> switchClosure(Map<Predicate<? super T>, Closure<? super T>> predicatesAndClosures) {
++ return SwitchClosure.<T>getInstance(predicatesAndClosures);
++ }
++
++ /**
++ * Create a new Closure that uses the input object as a key to find the
++ * closure to call.
++ * <p/>
++ * The Map consists of object keys and Closure values. A closure
++ * is called if the input object equals the key. If there is no match, the
++ * default closure is called. The default closure is set in the map
++ * using a null key.
++ *
++ * @param objectsAndClosures a map of objects to closures
++ * @return the closure
++ * @throws IllegalArgumentException if the map is null
++ * @throws IllegalArgumentException if the map is empty
++ * @throws IllegalArgumentException if any closure in the map is null
++ * @see org.apache.commons.collections15.functors.SwitchClosure
++ */
++ public static <T> Closure<T> switchMapClosure(Map<T, Closure<T>> objectsAndClosures) {
++ Closure[] trs = null;
++ Predicate[] preds = null;
++ if (objectsAndClosures == null) {
++ throw new IllegalArgumentException("The object and closure map must not be null");
++ }
++ Closure def = (Closure) objectsAndClosures.remove(null);
++ int size = objectsAndClosures.size();
++ trs = new Closure[size];
++ preds = new Predicate[size];
++ int i = 0;
++ for (Iterator it = objectsAndClosures.entrySet().iterator(); it.hasNext();) {
++ Map.Entry entry = (Map.Entry) it.next();
++ preds[i] = EqualPredicate.getInstance(entry.getKey());
++ trs[i] = (Closure) entry.getValue();
++ i++;
++ }
++ return switchClosure(preds, trs, def);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/CollectionUtils.java
+@@ -0,0 +1,1072 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.collection.*;
++
++import java.lang.reflect.Array;
++import java.util.*;
++
++/**
++ * Provides utility methods and decorators for {@link Collection} instances.
++ *
++ * @author Rodney Waldhoff
++ * @author Paul Jack
++ * @author Stephen Colebourne
++ * @author Steve Downey
++ * @author Herve Quiroz
++ * @author Peter KoBek
++ * @author Matthew Hawthorne
++ * @author Janek Bogucki
++ * @author Phil Steitz
++ * @author Steven Melzer
++ * @author Matt Hall, John Watkinson, Jon Schewe
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 1.0
++ */
++public class CollectionUtils {
++
++ /**
++ * Constant to avoid repeated object creation
++ */
++ private static Integer INTEGER_ONE = new Integer(1);
++
++ /**
++ * An empty unmodifiable collection.
++ * The JDK provides empty Set and List implementations which could be used for
++ * this purpose. However they could be cast to Set or List which might be
++ * undesirable. This implementation only implements Collection.
++ */
++ public static final Collection EMPTY_COLLECTION = UnmodifiableCollection.decorate(new ArrayList());
++
++ /**
++ * <code>CollectionUtils</code> should not normally be instantiated.
++ */
++ public CollectionUtils() {
++ }
++
++ /**
++ * Returns a {@link Collection} containing the union
++ * of the given {@link Collection}s.
++ * <p/>
++ * The cardinality of each element in the returned {@link Collection}
++ * will be equal to the maximum of the cardinality of that element
++ * in the two given {@link Collection}s.
++ *
++ * @param a the first collection, must not be null
++ * @param b the second collection, must not be null
++ * @return the union of the two collections15
++ * @see Collection#addAll
++ */
++ public static <E> Collection<E> union(final Collection<? extends E> a, final Collection<? extends E> b) {
++ ArrayList<E> list = new ArrayList<E>();
++ Map mapa = getCardinalityMap(a);
++ Map mapb = getCardinalityMap(b);
++ Set<E> elts = new HashSet<E>(a);
++ elts.addAll(b);
++ Iterator<E> it = elts.iterator();
++ while (it.hasNext()) {
++ E obj = it.next();
++ for (int i = 0, m = Math.max(getFreq(obj, mapa), getFreq(obj, mapb)); i < m; i++) {
++ list.add(obj);
++ }
++ }
++ return list;
++ }
++
++ /**
++ * Returns a {@link Collection} containing the intersection
++ * of the given {@link Collection}s.
++ * <p/>
++ * The cardinality of each element in the returned {@link Collection}
++ * will be equal to the minimum of the cardinality of that element
++ * in the two given {@link Collection}s.
++ *
++ * @param a the first collection, must not be null
++ * @param b the second collection, must not be null
++ * @return the intersection of the two collections15
++ * @see Collection#retainAll
++ * @see #containsAny
++ */
++ public static <E> Collection<E> intersection(final Collection<? extends E> a, final Collection<? extends E> b) {
++ ArrayList<E> list = new ArrayList<E>();
++ Map mapa = getCardinalityMap(a);
++ Map mapb = getCardinalityMap(b);
++ Set<E> elts = new HashSet<E>(a);
++ elts.addAll(b);
++ Iterator<E> it = elts.iterator();
++ while (it.hasNext()) {
++ E obj = it.next();
++ for (int i = 0, m = Math.min(getFreq(obj, mapa), getFreq(obj, mapb)); i < m; i++) {
++ list.add(obj);
++ }
++ }
++ return list;
++ }
++
++ /**
++ * Returns a {@link Collection} containing the exclusive disjunction
++ * (symmetric difference) of the given {@link Collection}s.
++ * <p/>
++ * The cardinality of each element <i>e</i> in the returned {@link Collection}
++ * will be equal to
++ * <tt>max(cardinality(<i>e</i>,<i>a</i>),cardinality(<i>e</i>,<i>b</i>)) - min(cardinality(<i>e</i>,<i>a</i>),cardinality(<i>e</i>,<i>b</i>))</tt>.
++ * <p/>
++ * This is equivalent to
++ * <tt>{@link #subtract subtract}({@link #union union(a,b)},{@link #intersection intersection(a,b)})</tt>
++ * or
++ * <tt>{@link #union union}({@link #subtract subtract(a,b)},{@link #subtract subtract(b,a)})</tt>.
++ *
++ * @param a the first collection, must not be null
++ * @param b the second collection, must not be null
++ * @return the symmetric difference of the two collections15
++ */
++ public static <E> Collection<E> disjunction(final Collection<E> a, final Collection<E> b) {
++ ArrayList<E> list = new ArrayList<E>();
++ Map mapa = getCardinalityMap(a);
++ Map mapb = getCardinalityMap(b);
++ Set<E> elts = new HashSet<E>(a);
++ elts.addAll(b);
++ Iterator<E> it = elts.iterator();
++ while (it.hasNext()) {
++ E obj = it.next();
++ for (int i = 0, m = ((Math.max(getFreq(obj, mapa), getFreq(obj, mapb))) - (Math.min(getFreq(obj, mapa), getFreq(obj, mapb)))); i < m; i++) {
++ list.add(obj);
++ }
++ }
++ return list;
++ }
++
++ /**
++ * Returns a new {@link Collection} containing <tt><i>a</i> - <i>b</i></tt>.
++ * The cardinality of each element <i>e</i> in the returned {@link Collection}
++ * will be the cardinality of <i>e</i> in <i>a</i> minus the cardinality
++ * of <i>e</i> in <i>b</i>, or zero, whichever is greater.
++ *
++ * @param a the collection to subtract from, must not be null
++ * @param b the {@link Iterable} to subtract, must not be null
++ * @return a new collection with the results
++ * @see Collection#removeAll
++ */
++ public static <E> Collection<E> subtract(final Collection<? extends E> a, final Iterable<? extends E> b) {
++ ArrayList<E> list = new ArrayList<E>(a);
++ for (E e : b) {
++ list.remove(e);
++ }
++ return list;
++ }
++
++ /**
++ * Returns <code>true</code> iff at least one element is in both collections15.
++ * <p/>
++ * In other words, this method returns <code>true</code> iff the
++ * {@link #intersection} of <i>coll1</i> and <i>coll2</i> is not empty.
++ *
++ * @param coll1 the first collection, must not be null
++ * @param coll2 the first collection, must not be null
++ * @return <code>true</code> iff the intersection of the collections15 is non-empty
++ * @see #intersection
++ * @since 2.1
++ */
++ public static <E> boolean containsAny(final Collection<? extends E> coll1, final Collection<? extends E> coll2) {
++ if (coll1.size() < coll2.size()) {
++ for (Iterator it = coll1.iterator(); it.hasNext();) {
++ if (coll2.contains(it.next())) {
++ return true;
++ }
++ }
++ } else {
++ for (Iterator it = coll2.iterator(); it.hasNext();) {
++ if (coll1.contains(it.next())) {
++ return true;
++ }
++ }
++ }
++ return false;
++ }
++
++ public static void main(String[] args) {
++ List<String> l1 = new ArrayList<String>();
++ l1.add("Test");
++ List<Integer> l2 = new ArrayList<Integer>();
++ l2.add(1);
++ containsAny(l1, l2);
++ }
++
++ /**
++ * Returns a {@link Map} mapping each unique element in the given
++ * {@link Iterable} to an {@link Integer} representing the number
++ * of occurrences of that element in the {@link Iterable}.
++ * <p/>
++ * Only those elements present in the Iterable will appear as
++ * keys in the map.
++ *
++ * @param iterable the collection to get the cardinality map for, must not be null
++ * @return the populated cardinality map
++ */
++ public static <E> Map<E, java.lang.Integer> getCardinalityMap(final Iterable<E> iterable) {
++ Map<E, Integer> count = new HashMap<E, Integer>();
++ for (Iterator<E> it = iterable.iterator(); it.hasNext();) {
++ E obj = it.next();
++ Integer c = count.get(obj);
++ if (c == null) {
++ count.put(obj, INTEGER_ONE);
++ } else {
++ count.put(obj, new Integer(c.intValue() + 1));
++ }
++ }
++ return count;
++ }
++
++ /**
++ * Returns <tt>true</tt> iff <i>a</i> is a sub-collection of <i>b</i>,
++ * that is, iff the cardinality of <i>e</i> in <i>a</i> is less
++ * than or equal to the cardinality of <i>e</i> in <i>b</i>,
++ * for each element <i>e</i> in <i>a</i>.
++ *
++ * @param a the first (sub?) collection, must not be null
++ * @param b the second (super?) collection, must not be null
++ * @return <code>true</code> iff <i>a</i> is a sub-collection of <i>b</i>
++ * @see #isProperSubCollection
++ * @see Collection#containsAll
++ */
++ public static <E> boolean isSubCollection(final Iterable<? extends E> a, final Iterable<? extends E> b) {
++ Map mapa = getCardinalityMap(a);
++ Map mapb = getCardinalityMap(b);
++ for (E obj : a) {
++ if (getFreq(obj, mapa) > getFreq(obj, mapb)) {
++ return false;
++ }
++ }
++ return true;
++ }
++
++ /**
++ * Returns <tt>true</tt> iff <i>a</i> is a <i>proper</i> sub-collection of <i>b</i>,
++ * that is, iff the cardinality of <i>e</i> in <i>a</i> is less
++ * than or equal to the cardinality of <i>e</i> in <i>b</i>,
++ * for each element <i>e</i> in <i>a</i>, and there is at least one
++ * element <i>f</i> such that the cardinality of <i>f</i> in <i>b</i>
++ * is strictly greater than the cardinality of <i>f</i> in <i>a</i>.
++ * <p/>
++ * The implementation assumes
++ * <ul>
++ * <li><code>a.size()</code> and <code>b.size()</code> represent the
++ * total cardinality of <i>a</i> and <i>b</i>, resp. </li>
++ * <li><code>a.size() < Integer.MAXVALUE</code></li>
++ * </ul>
++ *
++ * @param a the first (sub?) collection, must not be null
++ * @param b the second (super?) collection, must not be null
++ * @return <code>true</code> iff <i>a</i> is a <i>proper</i> sub-collection of <i>b</i>
++ * @see #isSubCollection
++ * @see Collection#containsAll
++ */
++ public static <E> boolean isProperSubCollection(final Collection<? extends E> a, final Collection<? extends E> b) {
++ return (a.size() < b.size()) && CollectionUtils.isSubCollection(a, b);
++ }
++
++ /**
++ * Returns <tt>true</tt> iff the given {@link Collection}s contain
++ * exactly the same elements with exactly the same cardinalities.
++ * <p/>
++ * That is, iff the cardinality of <i>e</i> in <i>a</i> is
++ * equal to the cardinality of <i>e</i> in <i>b</i>,
++ * for each element <i>e</i> in <i>a</i> or <i>b</i>.
++ *
++ * @param a the first collection, must not be null
++ * @param b the second collection, must not be null
++ * @return <code>true</code> iff the collections15 contain the same elements with the same cardinalities.
++ */
++ public static <E> boolean isEqualCollection(final Collection<? extends E> a, final Collection<? extends E> b) {
++ if (a.size() != b.size()) {
++ return false;
++ } else {
++ Map mapa = getCardinalityMap(a);
++ Map mapb = getCardinalityMap(b);
++ if (mapa.size() != mapb.size()) {
++ return false;
++ } else {
++ Iterator it = mapa.keySet().iterator();
++ while (it.hasNext()) {
++ Object obj = it.next();
++ if (getFreq(obj, mapa) != getFreq(obj, mapb)) {
++ return false;
++ }
++ }
++ return true;
++ }
++ }
++ }
++
++ /**
++ * Returns the number of occurrences of <i>obj</i> in <i>coll</i>.
++ *
++ * @param obj the object to find the cardinality of
++ * @param coll the collection to search
++ * @return the the number of occurrences of obj in coll
++ */
++ public static <E> int cardinality(E obj, final Collection<? super E> coll) {
++ if (coll instanceof Set) {
++ return (coll.contains(obj) ? 1 : 0);
++ }
++ if (coll instanceof Bag) {
++ return ((Bag) coll).getCount(obj);
++ }
++ int count = 0;
++ if (obj == null) {
++ for (Iterator it = coll.iterator(); it.hasNext();) {
++ if (it.next() == null) {
++ count++;
++ }
++ }
++ } else {
++ for (Iterator it = coll.iterator(); it.hasNext();) {
++ if (obj.equals(it.next())) {
++ count++;
++ }
++ }
++ }
++ return count;
++ }
++
++ /**
++ * Finds the first element in the given iterable which matches the given predicate.
++ * <p/>
++ * If the input iterable or predicate is null, or no element of the iterable
++ * matches the predicate, null is returned.
++ *
++ * @param iterable the iterable to search, may be null
++ * @param predicate the predicate to use, may be null
++ * @return the first element of the iterable which matches the predicate or null if none could be found
++ */
++ public static <E> E find(Iterable<E> iterable, Predicate<? super E> predicate) {
++ if (iterable != null && predicate != null) {
++ for (Iterator<E> iter = iterable.iterator(); iter.hasNext();) {
++ E item = iter.next();
++ if (predicate.evaluate(item)) {
++ return item;
++ }
++ }
++ }
++ return null;
++ }
++
++ /**
++ * Executes the given closure on each element in the iterable.
++ * <p/>
++ * If the input iterable or closure is null, there is no change made.
++ *
++ * @param iterable the iterable to get the input from, may be null
++ * @param closure the closure to perform, may be null
++ */
++ public static <E> void forAllDo(Iterable<E> iterable, Closure<? super E> closure) {
++ if (iterable != null && closure != null) {
++ for (Iterator<E> it = iterable.iterator(); it.hasNext();) {
++ closure.execute(it.next());
++ }
++ }
++ }
++
++ /**
++ * Filter the iterable by applying a Predicate to each element. If the
++ * predicate returns false, remove the element.
++ * <p/>
++ * If the input iterable or predicate is null, there is no change made.
++ *
++ * @param iterable the iterable to get the input from, may be null
++ * @param predicate the predicate to use as a filter, may be null
++ */
++ public static <E> void filter(Iterable<E> iterable, Predicate<? super E> predicate) {
++ if (iterable != null && predicate != null) {
++ for (Iterator<E> it = iterable.iterator(); it.hasNext();) {
++ if (predicate.evaluate(it.next()) == false) {
++ it.remove();
++ }
++ }
++ }
++ }
++
++ /**
++ * Transform the collection by applying a Transformer to each element.
++ * <p/>
++ * If the input collection or transformer is null, there is no change made.
++ * <p/>
++ * This routine is best for Lists, for which set() is used to do the
++ * transformations "in place." For other Collections, clear() and addAll()
++ * are used to replace elements.
++ * <p/>
++ * If the input collection controls its input, such as a Set, and the
++ * Transformer creates duplicates (or are otherwise invalid), the
++ * collection may reduce in size due to calling this method.
++ *
++ * @param collection the collection to get the input from, may be null
++ * @param transformer the transformer to perform, may be null
++ */
++ public static <E> void transform(Collection<E> collection, Transformer<? super E, ? extends E> transformer) {
++ if (collection != null && transformer != null) {
++ if (collection instanceof List) {
++ List<E> list = (List<E>) collection;
++ for (ListIterator<E> it = list.listIterator(); it.hasNext();) {
++ it.set(transformer.transform(it.next()));
++ }
++ } else {
++ Collection<E> resultCollection = collect(collection, transformer);
++ collection.clear();
++ collection.addAll(resultCollection);
++ }
++ }
++ }
++
++ /**
++ * Counts the number of elements in the input collection that match the predicate.
++ * <p/>
++ * A <code>null</code> collection or predicate matches no elements.
++ *
++ * @param inputIterable the collection to get the input from, may be null
++ * @param predicate the predicate to use, may be null
++ * @return the number of matches for the predicate in the collection
++ */
++ public static <E> int countMatches(Iterable<E> inputIterable, Predicate<? super E> predicate) {
++ int count = 0;
++ if (inputIterable != null && predicate != null) {
++ for (Iterator<E> it = inputIterable.iterator(); it.hasNext();) {
++ if (predicate.evaluate(it.next())) {
++ count++;
++ }
++ }
++ }
++ return count;
++ }
++
++ /**
++ * Answers true if a predicate is true for at least one element of a iterable.
++ * <p/>
++ * A <code>null</code> iterable or predicate returns false.
++ *
++ * @param iterable the iterable to get the input from, may be null
++ * @param predicate the predicate to use, may be null
++ * @return true if at least one element of the iterable matches the predicate
++ */
++ public static <E> boolean exists(Iterable<E> iterable, Predicate<? super E> predicate) {
++ if (iterable != null && predicate != null) {
++ for (Iterator<E> it = iterable.iterator(); it.hasNext();) {
++ if (predicate.evaluate(it.next())) {
++ return true;
++ }
++ }
++ }
++ return false;
++ }
++
++ /**
++ * Selects all elements from input collection which match the given predicate
++ * into an output collection.
++ * <p/>
++ * A <code>null</code> predicate matches no elements.
++ *
++ * @param inputCollection the collection to get the input from, may not be null
++ * @param predicate the predicate to use, may be null
++ * @return the elements matching the predicate (new list)
++ * @throws NullPointerException if the input collection is null
++ */
++ public static <E> Collection<E> select(Collection<E> inputCollection, Predicate<? super E> predicate) {
++ return select(inputCollection, predicate, new ArrayList<E>(inputCollection.size()));
++ }
++
++ /**
++ * Selects all elements from input collection which match the given predicate
++ * and adds them to outputCollection.
++ * <p/>
++ * If the input collection or predicate is null, there is no change to the
++ * output collection.
++ *
++ * @param inputCollection the collection to get the input from, may be null
++ * @param predicate the predicate to use, may be null
++ * @param outputCollection the collection to output into, may not be null
++ */
++ public static <E, C extends Collection<? super E>> C select(Iterable<E> inputCollection, Predicate<? super E> predicate, C outputCollection) {
++ if (inputCollection != null && predicate != null) {
++ for (Iterator<E> iter = inputCollection.iterator(); iter.hasNext();) {
++ E item = iter.next();
++ if (predicate.evaluate(item)) {
++ outputCollection.add(item);
++ }
++ }
++ }
++ return outputCollection;
++ }
++
++ /**
++ * Selects all elements from inputCollection which don't match the given predicate
++ * into an output collection.
++ * <p/>
++ * If the input predicate is <code>null</code>, the result is an empty list.
++ *
++ * @param inputCollection the collection to get the input from, may not be null
++ * @param predicate the predicate to use, may be null
++ * @return the elements <b>not</b> matching the predicate (new list)
++ * @throws NullPointerException if the input collection is null
++ */
++ public static <E> Collection<E> selectRejected(Collection<E> inputCollection, Predicate<? super E> predicate) {
++ ArrayList<E> answer = new ArrayList<E>(inputCollection.size());
++ selectRejected(inputCollection, predicate, answer);
++ return answer;
++ }
++
++ /**
++ * Selects all elements from inputIterable which don't match the given predicate
++ * and adds them to outputCollection.
++ * <p/>
++ * If the input predicate is <code>null</code>, no elements are added to <code>outputCollection</code>.
++ *
++ * @param inputIterable the collection to get the input from, may be null
++ * @param predicate the predicate to use, may be null
++ * @param outputCollection the collection to output into, may not be null
++ */
++ public static <E> void selectRejected(Iterable<E> inputIterable, Predicate<? super E> predicate, Collection<? super E> outputCollection) {
++ if (inputIterable != null && predicate != null) {
++ for (Iterator<E> iter = inputIterable.iterator(); iter.hasNext();) {
++ E item = iter.next();
++ if (predicate.evaluate(item) == false) {
++ outputCollection.add(item);
++ }
++ }
++ }
++ }
++
++ /**
++ * Returns a new Collection consisting of the elements of inputCollection transformed
++ * by the given transformer.
++ * <p/>
++ * If the input transformer is null, the result is an empty list.
++ *
++ * @param inputCollection the collection to get the input from, may not be null
++ * @param transformer the transformer to use, may be null
++ * @return the transformed result (new list)
++ * @throws NullPointerException if the input collection is null
++ */
++ public static <I,O> Collection<O> collect(Collection<I> inputCollection, Transformer<? super I, ? extends O> transformer) {
++ ArrayList<O> answer = new ArrayList<O>(inputCollection.size());
++ collect(inputCollection, transformer, answer);
++ return answer;
++ }
++
++ /**
++ * Transforms all elements from the inputIterator with the given transformer
++ * and adds them to the outputCollection.
++ * <p/>
++ * If the input iterator or transformer is null, the result is an empty list.
++ *
++ * @param inputIterator the iterator to get the input from, may be null
++ * @param transformer the transformer to use, may be null
++ * @return the transformed result (new list)
++ */
++ public static <I,O> Collection<O> collect(Iterator<I> inputIterator, Transformer<? super I, ? extends O> transformer) {
++ ArrayList<O> answer = new ArrayList<O>();
++ collect(inputIterator, transformer, answer);
++ return answer;
++ }
++
++ /**
++ * Transforms all elements from inputCollection with the given transformer
++ * and adds them to the outputCollection.
++ * <p/>
++ * If the input collection or transformer is null, there is no change to the
++ * output collection.
++ *
++ * @param inputCollection the collection to get the input from, may be null
++ * @param transformer the transformer to use, may not be null
++ * @param outputCollection the collection to output into, may not be null
++ * @return the outputCollection with the transformed input added
++ * @throws NullPointerException if the output collection is null
++ */
++ public static <I,O,C extends Collection<O>> C collect(Iterable<I> inputCollection, final Transformer<? super I, ? extends O> transformer, final C outputCollection) {
++ if (inputCollection != null) {
++ return collect(inputCollection.iterator(), transformer, outputCollection);
++ }
++ return outputCollection;
++ }
++
++ /**
++ * Transforms all elements from the inputIterator with the given transformer
++ * and adds them to the outputCollection.
++ * <p/>
++ * If the input iterator or transformer is null, there is no change to the
++ * output collection.
++ *
++ * @param inputIterator the iterator to get the input from, may be null
++ * @param transformer the transformer to use, may not be null
++ * @param outputCollection the collection to output into, may not be null
++ * @return the outputCollection with the transformed input added
++ * @throws NullPointerException if the output collection is null
++ */
++ public static <I,O,C extends Collection<O>> C collect(Iterator<I> inputIterator, final Transformer<? super I, ? extends O> transformer, final C outputCollection) {
++ if (inputIterator != null && transformer != null) {
++ while (inputIterator.hasNext()) {
++ I item = inputIterator.next();
++ O value = transformer.transform(item);
++ outputCollection.add(value);
++ }
++ }
++ return outputCollection;
++ }
++
++ /**
++ * Adds all elements in the iteration to the given collection.
++ * @deprecated Replaced by {@link Collection#addAll(java.util.Collection<? extends E>)}
++ *
++ * @param collection the collection to add to
++ * @param iterator the iterator of elements to add, may not be null
++ * @throws NullPointerException if the collection or iterator is null
++ */
++ public static <E> void addAll(Collection<E> collection, Iterator<? extends E> iterator) {
++ while (iterator.hasNext()) {
++ collection.add(iterator.next());
++ }
++ }
++
++ /**
++ * Adds all elements in the enumeration to the given collection.
++ * @deprecated Replaced by {@link Collection#addAll(java.util.Collection<? extends E>)}
++ *
++ * @param collection the collection to add to
++ * @param enumeration the enumeration of elements to add, may not be null
++ * @throws NullPointerException if the collection or enumeration is null
++ */
++ public static <E> void addAll(Collection<E> collection, Enumeration<? extends E> enumeration) {
++ while (enumeration.hasMoreElements()) {
++ collection.add(enumeration.nextElement());
++ }
++ }
++
++ /**
++ * Adds all elements in the array to the given collection.
++ *
++ * @param collection the collection to add to, may not be null
++ * @param elements the array of elements to add, may not be null
++ * @throws NullPointerException if the collection or array is null
++ */
++ public static <E, T extends E> void addAll(Collection<E> collection, T... elements) {
++ for (int i = 0, size = elements.length; i < size; i++) {
++ collection.add(elements[i]);
++ }
++ }
++
++ /**
++ * Given an Object, and an index, returns the nth value in the
++ * object.
++ * <ul>
++ * <li>If obj is a Map, returns the nth value from the <b>keySet</b> iterator, unless
++ * the Map contains an Integer key with integer value = idx, in which case the
++ * corresponding map entry value is returned. If idx exceeds the number of entries in
++ * the map, an empty Iterator is returned.
++ * <li>If obj is a List or an array, returns the nth value, throwing IndexOutOfBoundsException,
++ * ArrayIndexOutOfBoundsException, resp. if the nth value does not exist.
++ * <li>If obj is an iterator, enumeration or Collection, returns the nth value from the iterator,
++ * returning an empty Iterator (resp. Enumeration) if the nth value does not exist.
++ * <li>Returns the original obj if it is null or not a Collection or Iterator.
++ * </ul>
++ *
++ * @param obj the object to get an index of, may be null
++ * @param idx the index to get
++ * @throws IndexOutOfBoundsException
++ * @throws ArrayIndexOutOfBoundsException
++ * @deprecated use {@link #get(Object, int)} instead. Will be removed in v4.0
++ */
++ public static Object index(Object obj, int idx) {
++ return index(obj, new Integer(idx));
++ }
++
++ /**
++ * Given an Object, and a key (index), returns the value associated with
++ * that key in the Object. The following checks are made:
++ * <ul>
++ * <li>If obj is a Map, use the index as a key to get a value. If no match continue.
++ * <li>Check key is an Integer. If not, return the object passed in.
++ * <li>If obj is a Map, get the nth value from the <b>keySet</b> iterator.
++ * If the Map has fewer than n entries, return an empty Iterator.
++ * <li>If obj is a List or an array, get the nth value, throwing IndexOutOfBoundsException,
++ * ArrayIndexOutOfBoundsException, resp. if the nth value does not exist.
++ * <li>If obj is an iterator, enumeration or Collection, get the nth value from the iterator,
++ * returning an empty Iterator (resp. Enumeration) if the nth value does not exist.
++ * <li>Return the original obj.
++ * </ul>
++ *
++ * @param obj the object to get an index of
++ * @param index the index to get
++ * @return the object at the specified index
++ * @throws IndexOutOfBoundsException
++ * @throws ArrayIndexOutOfBoundsException
++ * @deprecated use {@link #get(Object, int)} instead. Will be removed in v4.0
++ */
++ public static Object index(Object obj, Object index) {
++ if (obj instanceof Map) {
++ Map map = (Map) obj;
++ if (map.containsKey(index)) {
++ return map.get(index);
++ }
++ }
++ int idx = -1;
++ if (index instanceof Integer) {
++ idx = ((Integer) index).intValue();
++ }
++ if (idx < 0) {
++ return obj;
++ } else if (obj instanceof Map) {
++ Map map = (Map) obj;
++ Iterator iterator = map.keySet().iterator();
++ return index(iterator, idx);
++ } else if (obj instanceof List) {
++ return ((List) obj).get(idx);
++ } else if (obj instanceof Object[]) {
++ return ((Object[]) obj)[idx];
++ } else if (obj instanceof Enumeration) {
++ Enumeration it = (Enumeration) obj;
++ while (it.hasMoreElements()) {
++ idx--;
++ if (idx == -1) {
++ return it.nextElement();
++ } else {
++ it.nextElement();
++ }
++ }
++ } else if (obj instanceof Iterator) {
++ return index((Iterator) obj, idx);
++ } else if (obj instanceof Collection) {
++ Iterator iterator = ((Collection) obj).iterator();
++ return index(iterator, idx);
++ }
++ return obj;
++ }
++
++ private static Object index(Iterator iterator, int idx) {
++ while (iterator.hasNext()) {
++ idx--;
++ if (idx == -1) {
++ return iterator.next();
++ } else {
++ iterator.next();
++ }
++ }
++ return iterator;
++ }
++
++ /**
++ * Returns the <code>index</code>-th value in <code>object</code>, throwing
++ * <code>IndexOutOfBoundsException</code> if there is no such element or
++ * <code>IllegalArgumentException</code> if <code>object</code> is not an
++ * instance of one of the supported types.
++ * <p/>
++ * The supported types, and associated semantics are:
++ * <ul>
++ * <li> Map -- the value returned is the <code>Map.Entry</code> in position
++ * <code>index</code> in the map's <code>entrySet</code> iterator,
++ * if there is such an entry.</li>
++ * <li> List -- this method is equivalent to the list's get method.</li>
++ * <li> Array -- the <code>index</code>-th array entry is returned,
++ * if there is such an entry; otherwise an <code>IndexOutOfBoundsException</code>
++ * is thrown.</li>
++ * <li> Collection -- the value returned is the <code>index</code>-th object
++ * returned by the collection's default iterator, if there is such an element.</li>
++ * <li> Iterator or Enumeration -- the value returned is the
++ * <code>index</code>-th object in the Iterator/Enumeration, if there
++ * is such an element. The Iterator/Enumeration is advanced to
++ * <code>index</code> (or to the end, if <code>index</code> exceeds the
++ * number of entries) as a side effect of this method.</li>
++ * </ul>
++ *
++ * @param object the object to get a value from
++ * @param index the index to get
++ * @return the object at the specified index
++ * @throws IndexOutOfBoundsException if the index is invalid
++ * @throws IllegalArgumentException if the object type is invalid
++ */
++ public static Object get(Object object, int index) {
++ if (index < 0) {
++ throw new IndexOutOfBoundsException("Index cannot be negative: " + index);
++ }
++ if (object instanceof Map) {
++ Map map = (Map) object;
++ Iterator iterator = map.entrySet().iterator();
++ return get(iterator, index);
++ } else if (object instanceof List) {
++ return ((List) object).get(index);
++ } else if (object instanceof Object[]) {
++ return ((Object[]) object)[index];
++ } else if (object instanceof Iterator) {
++ Iterator it = (Iterator) object;
++ while (it.hasNext()) {
++ index--;
++ if (index == -1) {
++ return it.next();
++ } else {
++ it.next();
++ }
++ }
++ throw new IndexOutOfBoundsException("Entry does not exist: " + index);
++ } else if (object instanceof Collection) {
++ Iterator iterator = ((Collection) object).iterator();
++ return get(iterator, index);
++ } else if (object instanceof Enumeration) {
++ Enumeration it = (Enumeration) object;
++ while (it.hasMoreElements()) {
++ index--;
++ if (index == -1) {
++ return it.nextElement();
++ } else {
++ it.nextElement();
++ }
++ }
++ throw new IndexOutOfBoundsException("Entry does not exist: " + index);
++ } else if (object == null) {
++ throw new IllegalArgumentException("Unsupported object type: null");
++ } else {
++ try {
++ return Array.get(object, index);
++ } catch (IllegalArgumentException ex) {
++ throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
++ }
++ }
++ }
++
++ /**
++ * Gets the size of the collection/iterator specified.
++ * <p/>
++ * This method can handles objects as follows
++ * <ul>
++ * <li>Collection - the collection size
++ * <li>Map - the map size
++ * <li>Array - the array size
++ * <li>Iterator - the number of elements remaining in the iterator
++ * <li>Enumeration - the number of elements remaining in the enumeration
++ * </ul>
++ *
++ * @param object the object to get the size of
++ * @return the size of the specified collection
++ * @throws IllegalArgumentException thrown if object is not recognised or null
++ * @since Commons Collections 3.1
++ */
++ public static int size(Object object) {
++ int total = 0;
++ if (object instanceof Map) {
++ total = ((Map) object).size();
++ } else if (object instanceof Collection) {
++ total = ((Collection) object).size();
++ } else if (object instanceof Object[]) {
++ total = ((Object[]) object).length;
++ } else if (object instanceof Iterator) {
++ Iterator it = (Iterator) object;
++ while (it.hasNext()) {
++ total++;
++ it.next();
++ }
++ } else if (object instanceof Enumeration) {
++ Enumeration it = (Enumeration) object;
++ while (it.hasMoreElements()) {
++ total++;
++ it.nextElement();
++ }
++ } else if (object == null) {
++ throw new IllegalArgumentException("Unsupported object type: null");
++ } else {
++ try {
++ total = Array.getLength(object);
++ } catch (IllegalArgumentException ex) {
++ throw new IllegalArgumentException("Unsupported object type: " + object.getClass().getName());
++ }
++ }
++ return total;
++ }
++
++ /**
++ * Reverses the order of the given array.
++ *
++ * @param array the array to reverse
++ */
++ public static void reverseArray(Object[] array) {
++ int i = 0;
++ int j = array.length - 1;
++ Object tmp;
++
++ while (j > i) {
++ tmp = array[j];
++ array[j] = array[i];
++ array[i] = tmp;
++ j--;
++ i++;
++ }
++ }
++
++ private static final int getFreq(final Object obj, final Map freqMap) {
++ Integer count = (Integer) freqMap.get(obj);
++ if (count != null) {
++ return count.intValue();
++ }
++ return 0;
++ }
++
++ /**
++ * Returns true if no more elements can be added to the Collection.
++ * <p/>
++ * This method uses the {@link BoundedCollection} interface to determine the
++ * full status. If the collection does not implement this interface then
++ * false is returned.
++ * <p/>
++ * The collection does not have to implement this interface directly.
++ * If the collection has been decorated using the decorators subpackage
++ * then these will be removed to access the BoundedCollection.
++ *
++ * @param coll the collection to check
++ * @return true if the BoundedCollection is full
++ * @throws NullPointerException if the collection is null
++ */
++ public static boolean isFull(Collection coll) {
++ if (coll == null) {
++ throw new NullPointerException("The collection must not be null");
++ }
++ if (coll instanceof BoundedCollection) {
++ return ((BoundedCollection) coll).isFull();
++ }
++ try {
++ BoundedCollection bcoll = UnmodifiableBoundedCollection.decorateUsing(coll);
++ return bcoll.isFull();
++
++ } catch (IllegalArgumentException ex) {
++ return false;
++ }
++ }
++
++ /**
++ * Get the maximum number of elements that the Collection can contain.
++ * <p/>
++ * This method uses the {@link BoundedCollection} interface to determine the
++ * maximum size. If the collection does not implement this interface then
++ * -1 is returned.
++ * <p/>
++ * The collection does not have to implement this interface directly.
++ * If the collection has been decorated using the decorators subpackage
++ * then these will be removed to access the BoundedCollection.
++ *
++ * @param coll the collection to check
++ * @return the maximum size of the BoundedCollection, -1 if no maximum size
++ * @throws NullPointerException if the collection is null
++ */
++ public static int maxSize(Collection coll) {
++ if (coll == null) {
++ throw new NullPointerException("The collection must not be null");
++ }
++ if (coll instanceof BoundedCollection) {
++ return ((BoundedCollection) coll).maxSize();
++ }
++ try {
++ BoundedCollection bcoll = UnmodifiableBoundedCollection.decorateUsing(coll);
++ return bcoll.maxSize();
++
++ } catch (IllegalArgumentException ex) {
++ return -1;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a synchronized collection backed by the given collection.
++ * <p/>
++ * You must manually synchronize on the returned buffer's iterator to
++ * avoid non-deterministic behavior:
++ * <p/>
++ * <pre>
++ * Collection c = CollectionUtils.synchronizedCollection(myCollection);
++ * synchronized (c) {
++ * Iterator i = c.iterator();
++ * while (i.hasNext()) {
++ * process (i.next());
++ * }
++ * }
++ * </pre>
++ * <p/>
++ * This method uses the implementation in the decorators subpackage.
++ *
++ * @param collection the collection to synchronize, must not be null
++ * @return a synchronized collection backed by the given collection
++ * @throws IllegalArgumentException if the collection is null
++ */
++ public static <E> Collection<E> synchronizedCollection(Collection<E> collection) {
++ return SynchronizedCollection.decorate(collection);
++ }
++
++ /**
++ * Returns an unmodifiable collection backed by the given collection.
++ * <p/>
++ * This method uses the implementation in the decorators subpackage.
++ *
++ * @param collection the collection to make unmodifiable, must not be null
++ * @return an unmodifiable collection backed by the given collection
++ * @throws IllegalArgumentException if the collection is null
++ */
++ public static <E> Collection<E> unmodifiableCollection(Collection<E> collection) {
++ return UnmodifiableCollection.decorate(collection);
++ }
++
++ /**
++ * Returns a predicated (validating) collection backed by the given collection.
++ * <p/>
++ * Only objects that pass the test in the given predicate can be added to the collection.
++ * Trying to add an invalid object results in an IllegalArgumentException.
++ * It is important not to use the original collection after invoking this method,
++ * as it is a backdoor for adding invalid objects.
++ *
++ * @param collection the collection to predicate, must not be null
++ * @param predicate the predicate for the collection, must not be null
++ * @return a predicated collection backed by the given collection
++ * @throws IllegalArgumentException if the Collection is null
++ */
++ public static <E> Collection<E> predicatedCollection(Collection<E> collection, Predicate<? super E> predicate) {
++ return PredicatedCollection.decorate(collection, predicate);
++ }
++
++ /**
++ * Returns a typed collection backed by the given collection.
++ * <p/>
++ * Only objects of the specified type can be added to the collection.
++ *
++ * @param collection the collection to limit to a specific type, must not be null
++ * @param type the type of objects which may be added to the collection
++ * @return a typed collection backed by the specified collection
++ * @deprecated Obsoleted by Java 1.5 Generics.
++ */
++ public static <E> Collection<E> typedCollection(Collection<E> collection, Class<E> type) {
++ return TypedCollection.decorate(collection, type);
++ }
++
++ /**
++ * Returns a transformed bag backed by the given collection.
++ * <p/>
++ * Each object is passed through the transformer as it is added to the
++ * Collection. It is important not to use the original collection after invoking this
++ * method, as it is a backdoor for adding untransformed objects.
++ *
++ * @param collection the collection to predicate, must not be null
++ * @param transformer the transformer for the collection, must not be null
++ * @return a transformed collection backed by the given collection
++ * @throws IllegalArgumentException if the Collection or Transformer is null
++ */
++ public static <I,O> Collection<O> transformedCollection(Collection<I> collection, Transformer<? super I, ? extends O> transformer) {
++ return TransformedCollection.decorate(collection, transformer);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/ComparatorUtils.java
+@@ -0,0 +1,233 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.comparators.*;
++
++import java.util.Collection;
++import java.util.Comparator;
++
++/**
++ * Provides convenient static utility methods for <Code>Comparator</Code>
++ * objects.
++ * <p/>
++ * Most of the functionality in this class can also be found in the
++ * <code>comparators</code> package. This class merely provides a
++ * convenient central place if you have use for more than one class
++ * in the <code>comparators</code> subpackage.
++ *
++ * @author Paul Jack
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 2.1
++ */
++public class ComparatorUtils {
++
++ /**
++ * ComparatorUtils should not normally be instantiated.
++ */
++ public ComparatorUtils() {
++ }
++
++ /**
++ * Comparator for natural sort order.
++ *
++ * @see ComparableComparator#getInstance
++ */
++ public static final Comparator NATURAL_COMPARATOR = ComparableComparator.getInstance();
++
++ /**
++ * Gets a comparator that uses the natural order of the objects.
++ *
++ * @return a comparator which uses natural order
++ */
++ public static Comparator naturalComparator() {
++ return NATURAL_COMPARATOR;
++ }
++
++ /**
++ * Gets a comparator that compares using two {@link Comparator}s.
++ * <p/>
++ * The second comparator is used if the first comparator returns equal.
++ *
++ * @param comparator1 the first comparator to use, not null
++ * @param comparator2 the first comparator to use, not null
++ * @return a {@link ComparatorChain} formed from the two comparators
++ * @throws NullPointerException if either comparator is null
++ * @see ComparatorChain
++ */
++ public static <T> Comparator<T> chainedComparator(Comparator<T> comparator1, Comparator<T> comparator2) {
++ return chainedComparator(new Comparator[]{comparator1, comparator2});
++ }
++
++ /**
++ * Gets a comparator that compares using an array of {@link Comparator}s, applied
++ * in sequence until one returns not equal or the array is exhausted.
++ *
++ * @param comparators the comparators to use, not null or empty or containing nulls
++ * @return a {@link ComparatorChain} formed from the input comparators
++ * @throws NullPointerException if comparators array is null or contains a null
++ * @see ComparatorChain
++ */
++ public static <T> Comparator<T> chainedComparator(Comparator<T>[] comparators) {
++ ComparatorChain chain = new ComparatorChain();
++ for (int i = 0; i < comparators.length; i++) {
++ if (comparators[i] == null) {
++ throw new NullPointerException("Comparator cannot be null");
++ }
++ chain.addComparator(comparators[i]);
++ }
++ return chain;
++ }
++
++ /**
++ * Gets a comparator that compares using a collection of {@link Comparator}s,
++ * applied in (default iterator) sequence until one returns not equal or the
++ * collection is exhausted.
++ *
++ * @param comparators the comparators to use, not null or empty or containing nulls
++ * @return a {@link ComparatorChain} formed from the input comparators
++ * @throws NullPointerException if comparators collection is null or contains a null
++ * @throws ClassCastException if the comparators collection contains the wrong object type
++ * @see ComparatorChain
++ */
++ public static <T> Comparator<T> chainedComparator(Collection<T> comparators) {
++ return chainedComparator((Comparator[]) comparators.toArray(new Comparator[comparators.size()]));
++ }
++
++ /**
++ * Gets a comparator that reverses the order of the given comparator.
++ *
++ * @param comparator the comparator to reverse
++ * @return a comparator that reverses the order of the input comparator
++ * @see ReverseComparator
++ */
++ public static <T> Comparator<T> reversedComparator(Comparator<T> comparator) {
++ if (comparator == null) {
++ comparator = NATURAL_COMPARATOR;
++ }
++ return new ReverseComparator(comparator);
++ }
++
++ /**
++ * Gets a Comparator that can sort Boolean objects.
++ * <p/>
++ * The parameter specifies whether true or false is sorted first.
++ * <p/>
++ * The comparator throws NullPointerException if a null value is compared.
++ *
++ * @param trueFirst when <code>true</code>, sort
++ * <code>true</code> {@link Boolean}s before
++ * <code>false</code> {@link Boolean}s.
++ * @return a comparator that sorts booleans
++ */
++ public static Comparator<Boolean> booleanComparator(boolean trueFirst) {
++ return BooleanComparator.getBooleanComparator(trueFirst);
++ }
++
++ /**
++ * Gets a Comparator that controls the comparison of <code>null</code> values.
++ * <p/>
++ * The returned comparator will consider a null value to be less than
++ * any nonnull value, and equal to any other null value. Two nonnull
++ * values will be evaluated with the given comparator.
++ *
++ * @param comparator the comparator that wants to allow nulls
++ * @return a version of that comparator that allows nulls
++ * @see NullComparator
++ */
++ public static <T> Comparator<T> nullLowComparator(Comparator<T> comparator) {
++ if (comparator == null) {
++ comparator = NATURAL_COMPARATOR;
++ }
++ return new NullComparator(comparator, false);
++ }
++
++ /**
++ * Gets a Comparator that controls the comparison of <code>null</code> values.
++ * <p/>
++ * The returned comparator will consider a null value to be greater than
++ * any nonnull value, and equal to any other null value. Two nonnull
++ * values will be evaluated with the given comparator.
++ *
++ * @param comparator the comparator that wants to allow nulls
++ * @return a version of that comparator that allows nulls
++ * @see NullComparator
++ */
++ public static <T> Comparator<T> nullHighComparator(Comparator<T> comparator) {
++ if (comparator == null) {
++ comparator = NATURAL_COMPARATOR;
++ }
++ return new NullComparator(comparator, true);
++ }
++
++ /**
++ * Gets a Comparator that passes transformed objects to the given comparator.
++ * <p/>
++ * Objects passed to the returned comparator will first be transformed
++ * by the given transformer before they are compared by the given
++ * comparator.
++ *
++ * @param comparator the sort order to use
++ * @param transformer the transformer to use
++ * @return a comparator that transforms its input objects before comparing them
++ * @see TransformingComparator
++ */
++ public static <I,O> Comparator<O> transformedComparator(Comparator<I> comparator, Transformer<I, O> transformer) {
++ if (comparator == null) {
++ comparator = NATURAL_COMPARATOR;
++ }
++ return new TransformingComparator(transformer, comparator);
++ }
++
++ /**
++ * Returns the smaller of the given objects according to the given
++ * comparator, returning the second object if the comparator
++ * returns equal.
++ *
++ * @param o1 the first object to compare
++ * @param o2 the second object to compare
++ * @param comparator the sort order to use
++ * @return the smaller of the two objects
++ */
++ public static <T> T min(T o1, T o2, Comparator<T> comparator) {
++ if (comparator == null) {
++ comparator = NATURAL_COMPARATOR;
++ }
++ int c = comparator.compare(o1, o2);
++ return (c < 0) ? o1 : o2;
++ }
++
++ /**
++ * Returns the larger of the given objects according to the given
++ * comparator, returning the second object if the comparator
++ * returns equal.
++ *
++ * @param o1 the first object to compare
++ * @param o2 the second object to compare
++ * @param comparator the sort order to use
++ * @return the larger of the two objects
++ */
++ public static <T> T max(T o1, T o2, Comparator<T> comparator) {
++ if (comparator == null) {
++ comparator = NATURAL_COMPARATOR;
++ }
++ int c = comparator.compare(o1, o2);
++ return (c > 0) ? o1 : o2;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/EnumerationUtils.java
+@@ -0,0 +1,53 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.iterators.EnumerationIterator;
++
++import java.util.Enumeration;
++import java.util.List;
++
++/**
++ * Provides utility methods for {@link Enumeration} instances.
++ *
++ * @author Matt Hall, John Watkinson, <a href="mailto:ggregory at seagullsw.com">Gary Gregory</a>
++ * @version $Id: EnumerationUtils.java,v 1.1 2005/10/11 17:05:19 pents90 Exp $
++ * @since Commons Collections 3.0
++ */
++public class EnumerationUtils {
++
++ /**
++ * EnumerationUtils is not normally instantiated.
++ */
++ public EnumerationUtils() {
++ // no init.
++ }
++
++ /**
++ * Creates a list based on an enumeration.
++ * <p/>
++ * <p>As the enumeration is traversed, an ArrayList of its values is
++ * created. The new list is returned.</p>
++ *
++ * @param enumeration the enumeration to traverse, which should not be <code>null</code>.
++ * @throws NullPointerException if the enumeration parameter is <code>null</code>.
++ */
++ public static <E> List<E> toList(Enumeration<E> enumeration) {
++ return IteratorUtils.toList(new EnumerationIterator(enumeration));
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/ExtendedProperties.java
+@@ -0,0 +1,1613 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.io.*;
++import java.util.*;
++
++/**
++ * This class extends normal Java properties by adding the possibility
++ * to use the same key many times concatenating the value strings
++ * instead of overwriting them.
++ * <p/>
++ * <b>Please consider using the <code>PropertiesConfiguration</code> class in
++ * Commons-Configuration as soon as it is released.</b>
++ * <p/>
++ * The Extended Properties syntax is explained here:
++ * <p/>
++ * <ul>
++ * <li>
++ * Each property has the syntax <code>key = value</code>
++ * </li>
++ * <li>
++ * The <i>key</i> may use any character but the equal sign '='.
++ * </li>
++ * <li>
++ * <i>value</i> may be separated on different lines if a backslash
++ * is placed at the end of the line that continues below.
++ * </li>
++ * <li>
++ * If <i>value</i> is a list of strings, each token is separated
++ * by a comma ','.
++ * </li>
++ * <li>
++ * Commas in each token are escaped placing a backslash right before
++ * the comma.
++ * </li>
++ * <li>
++ * Backslashes are escaped by using two consecutive backslashes i.e. \\
++ * </li>
++ * <li>
++ * If a <i>key</i> is used more than once, the values are appended
++ * like if they were on the same line separated with commas.
++ * </li>
++ * <li>
++ * Blank lines and lines starting with character '#' are skipped.
++ * </li>
++ * <li>
++ * If a property is named "include" (or whatever is defined by
++ * setInclude() and getInclude() and the value of that property is
++ * the full path to a file on disk, that file will be included into
++ * the ConfigurationsRepository. You can also pull in files relative
++ * to the parent configuration file. So if you have something
++ * like the following:
++ * <p/>
++ * include = additional.properties
++ * <p/>
++ * Then "additional.properties" is expected to be in the same
++ * directory as the parent configuration file.
++ * <p/>
++ * Duplicate name values will be replaced, so be careful.
++ * <p/>
++ * </li>
++ * </ul>
++ * <p/>
++ * <p>Here is an example of a valid extended properties file:
++ * <p/>
++ * <p><pre>
++ * # lines starting with # are comments
++ * <p/>
++ * # This is the simplest property
++ * key = value
++ * <p/>
++ * # A long property may be separated on multiple lines
++ * longvalue = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \
++ * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
++ * <p/>
++ * # This is a property with many tokens
++ * tokens_on_a_line = first token, second token
++ * <p/>
++ * # This sequence generates exactly the same result
++ * tokens_on_multiple_lines = first token
++ * tokens_on_multiple_lines = second token
++ * <p/>
++ * # commas may be escaped in tokens
++ * commas.escaped = Hi\, what'up?
++ * </pre>
++ * <p/>
++ * <p><b>NOTE</b>: this class has <b>not</b> been written for
++ * performance nor low memory usage. In fact, it's way slower than it
++ * could be and generates too much memory garbage. But since
++ * performance is not an issue during intialization (and there is not
++ * much time to improve it), I wrote it this way. If you don't like
++ * it, go ahead and tune it up!
++ *
++ * @author <a href="mailto:stefano at apache.org">Stefano Mazzocchi</a>
++ * @author <a href="mailto:jon at latchkey.com">Jon S. Stevens</a>
++ * @author <a href="mailto:daveb at miceda-data">Dave Bryson</a>
++ * @author <a href="mailto:jvanzyl at periapt.com">Jason van Zyl</a>
++ * @author <a href="mailto:geirm at optonline.net">Geir Magnusson Jr.</a>
++ * @author <a href="mailto:leon at opticode.co.za">Leon Messerschmidt</a>
++ * @author <a href="mailto:kjohnson at transparent.com">Kent Johnson</a>
++ * @author <a href="mailto:dlr at finemaltcoding.com">Daniel Rall</a>
++ * @author <a href="mailto:ipriha at surfeu.fi">Ilkka Priha</a>
++ * @author Janek Bogucki
++ * @author Mohan Kishore
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 1.0
++ */
++public class ExtendedProperties extends Hashtable {
++
++ /**
++ * Default configurations repository.
++ */
++ private ExtendedProperties defaults;
++
++ /**
++ * The file connected to this repository (holding comments and
++ * such).
++ *
++ * @serial
++ */
++ protected String file;
++
++ /**
++ * Base path of the configuration file used to create
++ * this ExtendedProperties object.
++ */
++ protected String basePath;
++
++ /**
++ * File separator.
++ */
++ protected String fileSeparator = System.getProperty("file.separator");
++
++ /**
++ * Has this configuration been intialized.
++ */
++ protected boolean isInitialized = false;
++
++ /**
++ * This is the name of the property that can point to other
++ * properties file for including other properties files.
++ */
++ protected static String include = "include";
++
++ /**
++ * These are the keys in the order they listed
++ * in the configuration file. This is useful when
++ * you wish to perform operations with configuration
++ * information in a particular order.
++ */
++ protected ArrayList<String> keysAsListed = new ArrayList<String>();
++
++ protected final static String START_TOKEN = "${";
++ protected final static String END_TOKEN = "}";
++
++
++ /**
++ * Interpolate key names to handle ${key} stuff
++ *
++ * @param base string to interpolate
++ * @return returns the key name with the ${key} substituted
++ */
++ protected String interpolate(String base) {
++ // COPIED from [configuration] 2003-12-29
++ return (interpolateHelper(base, null));
++ }
++
++ /**
++ * Recursive handler for multiple levels of interpolation.
++ * <p/>
++ * When called the first time, priorVariables should be null.
++ *
++ * @param base string with the ${key} variables
++ * @param priorVariables serves two purposes: to allow checking for
++ * loops, and creating a meaningful exception message should a loop
++ * occur. It's 0'th element will be set to the value of base from
++ * the first call. All subsequent interpolated variables are added
++ * afterward.
++ * @return the string with the interpolation taken care of
++ */
++ protected String interpolateHelper(String base, List priorVariables) {
++ // COPIED from [configuration] 2003-12-29
++ if (base == null) {
++ return null;
++ }
++
++ // on the first call initialize priorVariables
++ // and add base as the first element
++ if (priorVariables == null) {
++ priorVariables = new ArrayList();
++ priorVariables.add(base);
++ }
++
++ int begin = -1;
++ int end = -1;
++ int prec = 0 - END_TOKEN.length();
++ String variable = null;
++ StringBuffer result = new StringBuffer();
++
++ // FIXME: we should probably allow the escaping of the start token
++ while (((begin = base.indexOf(START_TOKEN, prec + END_TOKEN.length())) > -1) && ((end = base.indexOf(END_TOKEN, begin)) > -1)) {
++ result.append(base.substring(prec + END_TOKEN.length(), begin));
++ variable = base.substring(begin + START_TOKEN.length(), end);
++
++ // if we've got a loop, create a useful exception message and throw
++ if (priorVariables.contains(variable)) {
++ String initialBase = priorVariables.remove(0).toString();
++ priorVariables.add(variable);
++ StringBuffer priorVariableSb = new StringBuffer();
++
++ // create a nice trace of interpolated variables like so:
++ // var1->var2->var3
++ for (Iterator it = priorVariables.iterator(); it.hasNext();) {
++ priorVariableSb.append(it.next());
++ if (it.hasNext()) {
++ priorVariableSb.append("->");
++ }
++ }
++
++ throw new IllegalStateException("infinite loop in property interpolation of " + initialBase + ": " + priorVariableSb.toString());
++ }
++ // otherwise, add this variable to the interpolation list.
++ else {
++ priorVariables.add(variable);
++ }
++
++ //QUESTION: getProperty or getPropertyDirect
++ Object value = getProperty(variable);
++ if (value != null) {
++ result.append(interpolateHelper(value.toString(), priorVariables));
++
++ // pop the interpolated variable off the stack
++ // this maintains priorVariables correctness for
++ // properties with multiple interpolations, e.g.
++ // prop.name=${some.other.prop1}/blahblah/${some.other.prop2}
++ priorVariables.remove(priorVariables.size() - 1);
++ } else if (defaults != null && defaults.getString(variable, null) != null) {
++ result.append(defaults.getString(variable));
++ } else {
++ //variable not defined - so put it back in the value
++ result.append(START_TOKEN).append(variable).append(END_TOKEN);
++ }
++ prec = end;
++ }
++ result.append(base.substring(prec + END_TOKEN.length(), base.length()));
++
++ return result.toString();
++ }
++
++ /**
++ * Inserts a backslash before every comma and backslash.
++ */
++ private static String escape(String s) {
++ StringBuffer buf = new StringBuffer(s);
++ for (int i = 0; i < buf.length(); i++) {
++ char c = buf.charAt(i);
++ if (c == ',' || c == '\\') {
++ buf.insert(i, '\\');
++ i++;
++ }
++ }
++ return buf.toString();
++ }
++
++ /**
++ * Removes a backslash from every pair of backslashes.
++ */
++ private static String unescape(String s) {
++ StringBuffer buf = new StringBuffer(s);
++ for (int i = 0; i < buf.length() - 1; i++) {
++ char c1 = buf.charAt(i);
++ char c2 = buf.charAt(i + 1);
++ if (c1 == '\\' && c2 == '\\') {
++ buf.deleteCharAt(i);
++ }
++ }
++ return buf.toString();
++ }
++
++ /**
++ * Counts the number of successive times 'ch' appears in the
++ * 'line' before the position indicated by the 'index'.
++ */
++ private static int countPreceding(String line, int index, char ch) {
++ int i;
++ for (i = index - 1; i >= 0; i--) {
++ if (line.charAt(i) != ch) {
++ break;
++ }
++ }
++ return index - 1 - i;
++ }
++
++ /**
++ * Checks if the line ends with odd number of backslashes
++ */
++ private static boolean endsWithSlash(String line) {
++ if (!line.endsWith("\\")) {
++ return false;
++ }
++ return (countPreceding(line, line.length() - 1, '\\') % 2 == 0);
++ }
++
++ /**
++ * This class is used to read properties lines. These lines do
++ * not terminate with new-line chars but rather when there is no
++ * backslash sign a the end of the line. This is used to
++ * concatenate multiple lines for readability.
++ */
++ static class PropertiesReader extends LineNumberReader {
++ /**
++ * Constructor.
++ *
++ * @param reader A Reader.
++ */
++ public PropertiesReader(Reader reader) {
++ super(reader);
++ }
++
++ /**
++ * Read a property.
++ *
++ * @return a String property
++ * @throws IOException if there is difficulty reading the source.
++ */
++ public String readProperty() throws IOException {
++ StringBuffer buffer = new StringBuffer();
++
++ try {
++ while (true) {
++ String line = readLine().trim();
++ if ((line.length() != 0) && (line.charAt(0) != '#')) {
++ if (endsWithSlash(line)) {
++ line = line.substring(0, line.length() - 1);
++ buffer.append(line);
++ } else {
++ buffer.append(line);
++ break;
++ }
++ }
++ }
++ } catch (NullPointerException ex) {
++ return null;
++ }
++
++ return buffer.toString();
++ }
++ }
++
++ /**
++ * This class divides into tokens a property value. Token
++ * separator is "," but commas into the property value are escaped
++ * using the backslash in front.
++ */
++ static class PropertiesTokenizer extends StringTokenizer {
++ /**
++ * The property delimiter used while parsing (a comma).
++ */
++ static final String DELIMITER = ",";
++
++ /**
++ * Constructor.
++ *
++ * @param string A String.
++ */
++ public PropertiesTokenizer(String string) {
++ super(string, DELIMITER);
++ }
++
++ /**
++ * Check whether the object has more tokens.
++ *
++ * @return True if the object has more tokens.
++ */
++ public boolean hasMoreTokens() {
++ return super.hasMoreTokens();
++ }
++
++ /**
++ * Get next token.
++ *
++ * @return A String.
++ */
++ public String nextToken() {
++ StringBuffer buffer = new StringBuffer();
++
++ while (hasMoreTokens()) {
++ String token = super.nextToken();
++ if (endsWithSlash(token)) {
++ buffer.append(token.substring(0, token.length() - 1));
++ buffer.append(DELIMITER);
++ } else {
++ buffer.append(token);
++ break;
++ }
++ }
++
++ return buffer.toString().trim();
++ }
++ }
++
++ /**
++ * Creates an empty extended properties object.
++ */
++ public ExtendedProperties() {
++ super();
++ }
++
++ /**
++ * Creates and loads the extended properties from the specified file.
++ *
++ * @param file the filename to load
++ * @throws IOException if a file error occurs
++ */
++ public ExtendedProperties(String file) throws IOException {
++ this(file, null);
++ }
++
++ /**
++ * Creates and loads the extended properties from the specified file.
++ *
++ * @param file the filename to load
++ * @param defaultFile a second filename to load default values from
++ * @throws IOException if a file error occurs
++ */
++ public ExtendedProperties(String file, String defaultFile) throws IOException {
++ this.file = file;
++
++ basePath = new File(file).getAbsolutePath();
++ basePath = basePath.substring(0, basePath.lastIndexOf(fileSeparator) + 1);
++
++ FileInputStream in = null;
++ try {
++ in = new FileInputStream(file);
++ this.load(in);
++ } finally {
++ try {
++ if (in != null) {
++ in.close();
++ }
++ } catch (IOException ex) {
++ }
++ }
++
++ if (defaultFile != null) {
++ defaults = new ExtendedProperties(defaultFile);
++ }
++ }
++
++ /**
++ * Indicate to client code whether property
++ * resources have been initialized or not.
++ */
++ public boolean isInitialized() {
++ return isInitialized;
++ }
++
++ /**
++ * Gets the property value for including other properties files.
++ * By default it is "include".
++ *
++ * @return A String.
++ */
++ public String getInclude() {
++ return include;
++ }
++
++ /**
++ * Sets the property value for including other properties files.
++ * By default it is "include".
++ *
++ * @param inc A String.
++ */
++ public void setInclude(String inc) {
++ include = inc;
++ }
++
++ /**
++ * Load the properties from the given input stream.
++ *
++ * @param input the InputStream to load from
++ * @throws IOException if an IO error occurs
++ */
++ public void load(InputStream input) throws IOException {
++ load(input, null);
++ }
++
++ /**
++ * Load the properties from the given input stream
++ * and using the specified encoding.
++ *
++ * @param input the InputStream to load from
++ * @param enc the encoding to use
++ * @throws IOException if an IO error occurs
++ */
++ public synchronized void load(InputStream input, String enc) throws IOException {
++ PropertiesReader reader = null;
++ if (enc != null) {
++ try {
++ reader = new PropertiesReader(new InputStreamReader(input, enc));
++
++ } catch (UnsupportedEncodingException ex) {
++ // Another try coming up....
++ }
++ }
++
++ if (reader == null) {
++ try {
++ reader = new PropertiesReader(new InputStreamReader(input, "8859_1"));
++
++ } catch (UnsupportedEncodingException ex) {
++ // ISO8859-1 support is required on java platforms but....
++ // If it's not supported, use the system default encoding
++ reader = new PropertiesReader(new InputStreamReader(input));
++ }
++ }
++
++ try {
++ while (true) {
++ String line = reader.readProperty();
++ int equalSign = line.indexOf('=');
++
++ if (equalSign > 0) {
++ String key = line.substring(0, equalSign).trim();
++ String value = line.substring(equalSign + 1).trim();
++
++ // Configure produces lines like this ... just ignore them
++ if ("".equals(value)) {
++ continue;
++ }
++
++ if (getInclude() != null && key.equalsIgnoreCase(getInclude())) {
++ // Recursively load properties files.
++ File file = null;
++
++ if (value.startsWith(fileSeparator)) {
++ // We have an absolute path so we'll use this
++ file = new File(value);
++
++ } else {
++ // We have a relative path, and we have two
++ // possible forms here. If we have the "./" form
++ // then just strip that off first before continuing.
++ if (value.startsWith("." + fileSeparator)) {
++ value = value.substring(2);
++ }
++
++ file = new File(basePath + value);
++ }
++
++ if (file != null && file.exists() && file.canRead()) {
++ load(new FileInputStream(file));
++ }
++ } else {
++ addProperty(key, value);
++ }
++ }
++ }
++ } catch (NullPointerException ex) {
++ // Should happen only when EOF is reached.
++ return;
++ } finally {
++ // Loading is initializing
++ isInitialized = true;
++ }
++ }
++
++ /**
++ * Gets a property from the configuration.
++ *
++ * @param key property to retrieve
++ * @return value as object. Will return user value if exists,
++ * if not then default value if exists, otherwise null
++ */
++ public Object getProperty(String key) {
++ // first, try to get from the 'user value' store
++ Object obj = this.get(key);
++
++ if (obj == null) {
++ // if there isn't a value there, get it from the
++ // defaults if we have them
++ if (defaults != null) {
++ obj = defaults.get(key);
++ }
++ }
++
++ return obj;
++ }
++
++ /**
++ * Add a property to the configuration. If it already
++ * exists then the value stated here will be added
++ * to the configuration entry. For example, if
++ * <p/>
++ * <code>resource.loader = file</code>
++ * <p/>
++ * is already present in the configuration and you
++ * <p/>
++ * <code>addProperty("resource.loader", "classpath")</code>
++ * <p/>
++ * Then you will end up with a Vector like the
++ * following:
++ * <p/>
++ * <code>["file", "classpath"]</code>
++ *
++ * @param key the key to add
++ * @param value the value to add
++ */
++ public void addProperty(String key, Object value) {
++ if (value instanceof String) {
++ String str = (String) value;
++ if (str.indexOf(PropertiesTokenizer.DELIMITER) > 0) {
++ // token contains commas, so must be split apart then added
++ PropertiesTokenizer tokenizer = new PropertiesTokenizer(str);
++ while (tokenizer.hasMoreTokens()) {
++ String token = tokenizer.nextToken();
++ addPropertyInternal(key, unescape(token));
++ }
++ } else {
++ // token contains no commas, so can be simply added
++ addPropertyInternal(key, unescape(str));
++ }
++ } else {
++ addPropertyInternal(key, value);
++ }
++
++ // Adding a property connotes initialization
++ isInitialized = true;
++ }
++
++ /**
++ * Adds a key/value pair to the map. This routine does
++ * no magic morphing. It ensures the keylist is maintained
++ *
++ * @param key the key to store at
++ * @param value the decoded object to store
++ */
++ private void addPropertyDirect(String key, Object value) {
++ // safety check
++ if (!containsKey(key)) {
++ keysAsListed.add(key);
++ }
++ put(key, value);
++ }
++
++ /**
++ * Adds a decoded property to the map w/o checking for commas - used
++ * internally when a property has been broken up into
++ * strings that could contain escaped commas to prevent
++ * the inadvertent vectorization.
++ * <p/>
++ * Thanks to Leon Messerschmidt for this one.
++ *
++ * @param key the key to store at
++ * @param value the decoded object to store
++ */
++ private void addPropertyInternal(String key, Object value) {
++ Object current = this.get(key);
++
++ if (current instanceof String) {
++ // one object already in map - convert it to a vector
++ Vector v = new Vector(2);
++ v.addElement(current);
++ v.addElement(value);
++ put(key, v);
++
++ } else if (current instanceof Vector) {
++ // already a vector - just add the new token
++ ((Vector) current).addElement(value);
++
++ } else {
++ // brand new key - store in keysAsListed to retain order
++ if (!containsKey(key)) {
++ keysAsListed.add(key);
++ }
++ put(key, value);
++ }
++ }
++
++ /**
++ * Set a property, this will replace any previously
++ * set values. Set values is implicitly a call
++ * to clearProperty(key), addProperty(key,value).
++ *
++ * @param key the key to set
++ * @param value the value to set
++ */
++ public void setProperty(String key, Object value) {
++ clearProperty(key);
++ addProperty(key, value);
++ }
++
++ /**
++ * Save the properties to the given output stream.
++ * <p/>
++ * The stream is not closed, but it is flushed.
++ *
++ * @param output an OutputStream, may be null
++ * @param header a textual comment to act as a file header
++ * @throws IOException if an IO error occurs
++ */
++ public synchronized void save(OutputStream output, String header) throws IOException {
++ if (output == null) {
++ return;
++ }
++ PrintWriter theWrtr = new PrintWriter(output);
++ if (header != null) {
++ theWrtr.println(header);
++ }
++
++ Enumeration theKeys = keys();
++ while (theKeys.hasMoreElements()) {
++ String key = (String) theKeys.nextElement();
++ Object value = get(key);
++ if (value != null) {
++ if (value instanceof String) {
++ StringBuffer currentOutput = new StringBuffer();
++ currentOutput.append(key);
++ currentOutput.append("=");
++ currentOutput.append(escape((String) value));
++ theWrtr.println(currentOutput.toString());
++
++ } else if (value instanceof Vector) {
++ Vector values = (Vector) value;
++ Enumeration valuesEnum = values.elements();
++ while (valuesEnum.hasMoreElements()) {
++ String currentElement = (String) valuesEnum.nextElement();
++ StringBuffer currentOutput = new StringBuffer();
++ currentOutput.append(key);
++ currentOutput.append("=");
++ currentOutput.append(escape(currentElement));
++ theWrtr.println(currentOutput.toString());
++ }
++ }
++ }
++ theWrtr.println();
++ theWrtr.flush();
++ }
++ }
++
++ /**
++ * Combines an existing Hashtable with this Hashtable.
++ * <p/>
++ * Warning: It will overwrite previous entries without warning.
++ *
++ * @param props the properties to combine
++ */
++ public void combine(ExtendedProperties props) {
++ for (Iterator it = props.getKeys(); it.hasNext();) {
++ String key = (String) it.next();
++ setProperty(key, props.get(key));
++ }
++ }
++
++ /**
++ * Clear a property in the configuration.
++ *
++ * @param key the property key to remove along with corresponding value
++ */
++ public void clearProperty(String key) {
++ if (containsKey(key)) {
++ // we also need to rebuild the keysAsListed or else
++ // things get *very* confusing
++ for (int i = 0; i < keysAsListed.size(); i++) {
++ if ((keysAsListed.get(i)).equals(key)) {
++ keysAsListed.remove(i);
++ break;
++ }
++ }
++ remove(key);
++ }
++ }
++
++ /**
++ * Get the list of the keys contained in the configuration
++ * repository.
++ *
++ * @return an Iterator over the keys
++ */
++ public Iterator getKeys() {
++ return keysAsListed.iterator();
++ }
++
++ /**
++ * Get the list of the keys contained in the configuration
++ * repository that match the specified prefix.
++ *
++ * @param prefix the prefix to match
++ * @return an Iterator of keys that match the prefix
++ */
++ public Iterator getKeys(String prefix) {
++ Iterator keys = getKeys();
++ ArrayList matchingKeys = new ArrayList();
++
++ while (keys.hasNext()) {
++ Object key = keys.next();
++
++ if (key instanceof String && ((String) key).startsWith(prefix)) {
++ matchingKeys.add(key);
++ }
++ }
++ return matchingKeys.iterator();
++ }
++
++ /**
++ * Create an ExtendedProperties object that is a subset
++ * of this one. Take into account duplicate keys
++ * by using the setProperty() in ExtendedProperties.
++ *
++ * @param prefix the prefix to get a subset for
++ * @return a new independent ExtendedProperties
++ */
++ public ExtendedProperties subset(String prefix) {
++ ExtendedProperties c = new ExtendedProperties();
++ Iterator keys = getKeys();
++ boolean validSubset = false;
++
++ while (keys.hasNext()) {
++ Object key = keys.next();
++
++ if (key instanceof String && ((String) key).startsWith(prefix)) {
++ if (!validSubset) {
++ validSubset = true;
++ }
++
++ /*
++ * Check to make sure that c.subset(prefix) doesn't
++ * blow up when there is only a single property
++ * with the key prefix. This is not a useful
++ * subset but it is a valid subset.
++ */
++ String newKey = null;
++ if (((String) key).length() == prefix.length()) {
++ newKey = prefix;
++ } else {
++ newKey = ((String) key).substring(prefix.length() + 1);
++ }
++
++ /*
++ * use addPropertyDirect() - this will plug the data as
++ * is into the Map, but will also do the right thing
++ * re key accounting
++ */
++ c.addPropertyDirect(newKey, get(key));
++ }
++ }
++
++ if (validSubset) {
++ return c;
++ } else {
++ return null;
++ }
++ }
++
++ /**
++ * Display the configuration for debugging purposes to System.out.
++ */
++ public void display() {
++ Iterator i = getKeys();
++
++ while (i.hasNext()) {
++ String key = (String) i.next();
++ Object value = get(key);
++ System.out.println(key + " => " + value);
++ }
++ }
++
++ /**
++ * Get a string associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @return The associated string.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a String.
++ */
++ public String getString(String key) {
++ return getString(key, null);
++ }
++
++ /**
++ * Get a string associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated string if key is found,
++ * default value otherwise.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a String.
++ */
++ public String getString(String key, String defaultValue) {
++ Object value = get(key);
++
++ if (value instanceof String) {
++ return interpolate((String) value);
++
++ } else if (value == null) {
++ if (defaults != null) {
++ return interpolate(defaults.getString(key, defaultValue));
++ } else {
++ return interpolate(defaultValue);
++ }
++ } else if (value instanceof Vector) {
++ return interpolate((String) ((Vector) value).get(0));
++ } else {
++ throw new ClassCastException('\'' + key + "' doesn't map to a String object");
++ }
++ }
++
++ /**
++ * Get a list of properties associated with the given
++ * configuration key.
++ *
++ * @param key The configuration key.
++ * @return The associated properties if key is found.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a String/Vector.
++ * @throws IllegalArgumentException if one of the tokens is
++ * malformed (does not contain an equals sign).
++ */
++ public Properties getProperties(String key) {
++ return getProperties(key, new Properties());
++ }
++
++ /**
++ * Get a list of properties associated with the given
++ * configuration key.
++ *
++ * @param key The configuration key.
++ * @return The associated properties if key is found.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a String/Vector.
++ * @throws IllegalArgumentException if one of the tokens is
++ * malformed (does not contain an equals sign).
++ */
++ public Properties getProperties(String key, Properties defaults) {
++ /*
++ * Grab an array of the tokens for this key.
++ */
++ String[] tokens = getStringArray(key);
++
++ // Each token is of the form 'key=value'.
++ Properties props = new Properties(defaults);
++ for (int i = 0; i < tokens.length; i++) {
++ String token = tokens[i];
++ int equalSign = token.indexOf('=');
++ if (equalSign > 0) {
++ String pkey = token.substring(0, equalSign).trim();
++ String pvalue = token.substring(equalSign + 1).trim();
++ props.put(pkey, pvalue);
++ } else {
++ throw new IllegalArgumentException('\'' + token + "' does not contain " + "an equals sign");
++ }
++ }
++ return props;
++ }
++
++ /**
++ * Get an array of strings associated with the given configuration
++ * key.
++ *
++ * @param key The configuration key.
++ * @return The associated string array if key is found.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a String/Vector.
++ */
++ public String[] getStringArray(String key) {
++ Object value = get(key);
++
++ // What's your vector, Victor?
++ Vector vector;
++ if (value instanceof String) {
++ vector = new Vector(1);
++ vector.addElement(value);
++
++ } else if (value instanceof Vector) {
++ vector = (Vector) value;
++
++ } else if (value == null) {
++ if (defaults != null) {
++ return defaults.getStringArray(key);
++ } else {
++ return new String[0];
++ }
++ } else {
++ throw new ClassCastException('\'' + key + "' doesn't map to a String/Vector object");
++ }
++
++ String[] tokens = new String[vector.size()];
++ for (int i = 0; i < tokens.length; i++) {
++ tokens[i] = (String) vector.elementAt(i);
++ }
++
++ return tokens;
++ }
++
++ /**
++ * Get a Vector of strings associated with the given configuration
++ * key.
++ *
++ * @param key The configuration key.
++ * @return The associated Vector.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Vector.
++ */
++ public Vector getVector(String key) {
++ return getVector(key, null);
++ }
++
++ /**
++ * Get a Vector of strings associated with the given configuration
++ * key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated Vector.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Vector.
++ */
++ public Vector getVector(String key, Vector defaultValue) {
++ Object value = get(key);
++
++ if (value instanceof Vector) {
++ return (Vector) value;
++
++ } else if (value instanceof String) {
++ Vector v = new Vector(1);
++ v.addElement(value);
++ put(key, v);
++ return v;
++
++ } else if (value == null) {
++ if (defaults != null) {
++ return defaults.getVector(key, defaultValue);
++ } else {
++ return ((defaultValue == null) ? new Vector() : defaultValue);
++ }
++ } else {
++ throw new ClassCastException('\'' + key + "' doesn't map to a Vector object");
++ }
++ }
++
++ /**
++ * Get a boolean associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @return The associated boolean.
++ * @throws NoSuchElementException is thrown if the key doesn't
++ * map to an existing object.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Boolean.
++ */
++ public boolean getBoolean(String key) {
++ Boolean b = getBoolean(key, null);
++ if (b != null) {
++ return b.booleanValue();
++ } else {
++ throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
++ }
++ }
++
++ /**
++ * Get a boolean associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated boolean.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Boolean.
++ */
++ public boolean getBoolean(String key, boolean defaultValue) {
++ return getBoolean(key, new Boolean(defaultValue)).booleanValue();
++ }
++
++ /**
++ * Get a boolean associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated boolean if key is found and has valid
++ * format, default value otherwise.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Boolean.
++ */
++ public Boolean getBoolean(String key, Boolean defaultValue) {
++
++ Object value = get(key);
++
++ if (value instanceof Boolean) {
++ return (Boolean) value;
++
++ } else if (value instanceof String) {
++ String s = testBoolean((String) value);
++ Boolean b = new Boolean(s);
++ put(key, b);
++ return b;
++
++ } else if (value == null) {
++ if (defaults != null) {
++ return defaults.getBoolean(key, defaultValue);
++ } else {
++ return defaultValue;
++ }
++ } else {
++ throw new ClassCastException('\'' + key + "' doesn't map to a Boolean object");
++ }
++ }
++
++ /**
++ * Test whether the string represent by value maps to a boolean
++ * value or not. We will allow <code>true</code>, <code>on</code>,
++ * and <code>yes</code> for a <code>true</code> boolean value, and
++ * <code>false</code>, <code>off</code>, and <code>no</code> for
++ * <code>false</code> boolean values. Case of value to test for
++ * boolean status is ignored.
++ *
++ * @param value the value to test for boolean state
++ * @return <code>true</code> or <code>false</code> if the supplied
++ * text maps to a boolean value, or <code>null</code> otherwise.
++ */
++ public String testBoolean(String value) {
++ String s = value.toLowerCase();
++
++ if (s.equals("true") || s.equals("on") || s.equals("yes")) {
++ return "true";
++ } else if (s.equals("false") || s.equals("off") || s.equals("no")) {
++ return "false";
++ } else {
++ return null;
++ }
++ }
++
++ /**
++ * Get a byte associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @return The associated byte.
++ * @throws NoSuchElementException is thrown if the key doesn't
++ * map to an existing object.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Byte.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public byte getByte(String key) {
++ Byte b = getByte(key, null);
++ if (b != null) {
++ return b.byteValue();
++ } else {
++ throw new NoSuchElementException('\'' + key + " doesn't map to an existing object");
++ }
++ }
++
++ /**
++ * Get a byte associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated byte.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Byte.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public byte getByte(String key, byte defaultValue) {
++ return getByte(key, new Byte(defaultValue)).byteValue();
++ }
++
++ /**
++ * Get a byte associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated byte if key is found and has valid
++ * format, default value otherwise.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Byte.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public Byte getByte(String key, Byte defaultValue) {
++ Object value = get(key);
++
++ if (value instanceof Byte) {
++ return (Byte) value;
++
++ } else if (value instanceof String) {
++ Byte b = new Byte((String) value);
++ put(key, b);
++ return b;
++
++ } else if (value == null) {
++ if (defaults != null) {
++ return defaults.getByte(key, defaultValue);
++ } else {
++ return defaultValue;
++ }
++ } else {
++ throw new ClassCastException('\'' + key + "' doesn't map to a Byte object");
++ }
++ }
++
++ /**
++ * Get a short associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @return The associated short.
++ * @throws NoSuchElementException is thrown if the key doesn't
++ * map to an existing object.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Short.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public short getShort(String key) {
++ Short s = getShort(key, null);
++ if (s != null) {
++ return s.shortValue();
++ } else {
++ throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
++ }
++ }
++
++ /**
++ * Get a short associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated short.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Short.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public short getShort(String key, short defaultValue) {
++ return getShort(key, new Short(defaultValue)).shortValue();
++ }
++
++ /**
++ * Get a short associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated short if key is found and has valid
++ * format, default value otherwise.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Short.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public Short getShort(String key, Short defaultValue) {
++ Object value = get(key);
++
++ if (value instanceof Short) {
++ return (Short) value;
++
++ } else if (value instanceof String) {
++ Short s = new Short((String) value);
++ put(key, s);
++ return s;
++
++ } else if (value == null) {
++ if (defaults != null) {
++ return defaults.getShort(key, defaultValue);
++ } else {
++ return defaultValue;
++ }
++ } else {
++ throw new ClassCastException('\'' + key + "' doesn't map to a Short object");
++ }
++ }
++
++ /**
++ * The purpose of this method is to get the configuration resource
++ * with the given name as an integer.
++ *
++ * @param name The resource name.
++ * @return The value of the resource as an integer.
++ */
++ public int getInt(String name) {
++ return getInteger(name);
++ }
++
++ /**
++ * The purpose of this method is to get the configuration resource
++ * with the given name as an integer, or a default value.
++ *
++ * @param name The resource name
++ * @param def The default value of the resource.
++ * @return The value of the resource as an integer.
++ */
++ public int getInt(String name, int def) {
++ return getInteger(name, def);
++ }
++
++ /**
++ * Get a int associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @return The associated int.
++ * @throws NoSuchElementException is thrown if the key doesn't
++ * map to an existing object.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Integer.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public int getInteger(String key) {
++ Integer i = getInteger(key, null);
++ if (i != null) {
++ return i.intValue();
++ } else {
++ throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
++ }
++ }
++
++ /**
++ * Get a int associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated int.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Integer.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public int getInteger(String key, int defaultValue) {
++ Integer i = getInteger(key, null);
++
++ if (i == null) {
++ return defaultValue;
++ }
++ return i.intValue();
++ }
++
++ /**
++ * Get a int associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated int if key is found and has valid
++ * format, default value otherwise.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Integer.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public Integer getInteger(String key, Integer defaultValue) {
++ Object value = get(key);
++
++ if (value instanceof Integer) {
++ return (Integer) value;
++
++ } else if (value instanceof String) {
++ Integer i = new Integer((String) value);
++ put(key, i);
++ return i;
++
++ } else if (value == null) {
++ if (defaults != null) {
++ return defaults.getInteger(key, defaultValue);
++ } else {
++ return defaultValue;
++ }
++ } else {
++ throw new ClassCastException('\'' + key + "' doesn't map to a Integer object");
++ }
++ }
++
++ /**
++ * Get a long associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @return The associated long.
++ * @throws NoSuchElementException is thrown if the key doesn't
++ * map to an existing object.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Long.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public long getLong(String key) {
++ Long l = getLong(key, null);
++ if (l != null) {
++ return l.longValue();
++ } else {
++ throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
++ }
++ }
++
++ /**
++ * Get a long associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated long.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Long.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public long getLong(String key, long defaultValue) {
++ return getLong(key, new Long(defaultValue)).longValue();
++ }
++
++ /**
++ * Get a long associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated long if key is found and has valid
++ * format, default value otherwise.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Long.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public Long getLong(String key, Long defaultValue) {
++ Object value = get(key);
++
++ if (value instanceof Long) {
++ return (Long) value;
++
++ } else if (value instanceof String) {
++ Long l = new Long((String) value);
++ put(key, l);
++ return l;
++
++ } else if (value == null) {
++ if (defaults != null) {
++ return defaults.getLong(key, defaultValue);
++ } else {
++ return defaultValue;
++ }
++ } else {
++ throw new ClassCastException('\'' + key + "' doesn't map to a Long object");
++ }
++ }
++
++ /**
++ * Get a float associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @return The associated float.
++ * @throws NoSuchElementException is thrown if the key doesn't
++ * map to an existing object.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Float.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public float getFloat(String key) {
++ Float f = getFloat(key, null);
++ if (f != null) {
++ return f.floatValue();
++ } else {
++ throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
++ }
++ }
++
++ /**
++ * Get a float associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated float.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Float.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public float getFloat(String key, float defaultValue) {
++ return getFloat(key, new Float(defaultValue)).floatValue();
++ }
++
++ /**
++ * Get a float associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated float if key is found and has valid
++ * format, default value otherwise.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Float.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public Float getFloat(String key, Float defaultValue) {
++ Object value = get(key);
++
++ if (value instanceof Float) {
++ return (Float) value;
++
++ } else if (value instanceof String) {
++ Float f = new Float((String) value);
++ put(key, f);
++ return f;
++
++ } else if (value == null) {
++ if (defaults != null) {
++ return defaults.getFloat(key, defaultValue);
++ } else {
++ return defaultValue;
++ }
++ } else {
++ throw new ClassCastException('\'' + key + "' doesn't map to a Float object");
++ }
++ }
++
++ /**
++ * Get a double associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @return The associated double.
++ * @throws NoSuchElementException is thrown if the key doesn't
++ * map to an existing object.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Double.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public double getDouble(String key) {
++ Double d = getDouble(key, null);
++ if (d != null) {
++ return d.doubleValue();
++ } else {
++ throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
++ }
++ }
++
++ /**
++ * Get a double associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated double.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Double.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public double getDouble(String key, double defaultValue) {
++ return getDouble(key, new Double(defaultValue)).doubleValue();
++ }
++
++ /**
++ * Get a double associated with the given configuration key.
++ *
++ * @param key The configuration key.
++ * @param defaultValue The default value.
++ * @return The associated double if key is found and has valid
++ * format, default value otherwise.
++ * @throws ClassCastException is thrown if the key maps to an
++ * object that is not a Double.
++ * @throws NumberFormatException is thrown if the value mapped
++ * by the key has not a valid number format.
++ */
++ public Double getDouble(String key, Double defaultValue) {
++ Object value = get(key);
++
++ if (value instanceof Double) {
++ return (Double) value;
++
++ } else if (value instanceof String) {
++ Double d = new Double((String) value);
++ put(key, d);
++ return d;
++
++ } else if (value == null) {
++ if (defaults != null) {
++ return defaults.getDouble(key, defaultValue);
++ } else {
++ return defaultValue;
++ }
++ } else {
++ throw new ClassCastException('\'' + key + "' doesn't map to a Double object");
++ }
++ }
++
++ /**
++ * Convert a standard properties class into a configuration class.
++ *
++ * @param props the properties object to convert
++ * @return new ExtendedProperties created from props
++ */
++ public static ExtendedProperties convertProperties(Properties props) {
++ ExtendedProperties c = new ExtendedProperties();
++
++ for (Enumeration e = props.keys(); e.hasMoreElements();) {
++ String s = (String) e.nextElement();
++ c.setProperty(s, props.getProperty(s));
++ }
++
++ return c;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/Factory.java
+@@ -0,0 +1,44 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++/**
++ * Defines a functor interface implemented by classes that create objects.
++ * <p/>
++ * A <code>Factory</code> creates an object without using an input parameter.
++ * If an input parameter is required, then {@link Transformer} is more appropriate.
++ * <p/>
++ * Standard implementations of common factories are provided by
++ * {@link FactoryUtils}. These include factories that return a constant,
++ * a copy of a prototype or a new instance.
++ *
++ * @author Arron Bates
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 2.1
++ */
++public interface Factory <T> {
++
++ /**
++ * Create a new object.
++ *
++ * @return a new object
++ * @throws FunctorException (runtime) if the factory cannot create an object
++ */
++ public T create();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/FactoryUtils.java
+@@ -0,0 +1,135 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.functors.ConstantFactory;
++import org.apache.commons.collections15.functors.ExceptionFactory;
++import org.apache.commons.collections15.functors.InstantiateFactory;
++import org.apache.commons.collections15.functors.PrototypeFactory;
++
++/**
++ * <code>FactoryUtils</code> provides reference implementations and utilities
++ * for the Factory functor interface. The supplied factories are:
++ * <ul>
++ * <li>Prototype - clones a specified object
++ * <li>Reflection - creates objects using reflection
++ * <li>Constant - always returns the same object
++ * <li>Null - always returns null
++ * <li>Exception - always throws an exception
++ * </ul>
++ * All the supplied factories are Serializable.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public class FactoryUtils {
++
++ /**
++ * This class is not normally instantiated.
++ */
++ public FactoryUtils() {
++ super();
++ }
++
++ /**
++ * Gets a Factory that always throws an exception.
++ * This could be useful during testing as a placeholder.
++ *
++ * @return the factory
++ * @see org.apache.commons.collections15.functors.ExceptionFactory
++ */
++ public static Factory exceptionFactory() {
++ return ExceptionFactory.INSTANCE;
++ }
++
++ /**
++ * Gets a Factory that will return null each time the factory is used.
++ * This could be useful during testing as a placeholder.
++ *
++ * @return the factory
++ * @see org.apache.commons.collections15.functors.ConstantFactory
++ */
++ public static Factory nullFactory() {
++ return ConstantFactory.NULL_INSTANCE;
++ }
++
++ /**
++ * Creates a Factory that will return the same object each time the factory
++ * is used. No check is made that the object is immutable. In general, only
++ * immutable objects should use the constant factory. Mutable objects should
++ * use the prototype factory.
++ *
++ * @param constantToReturn the constant object to return each time in the factory
++ * @return the <code>constant</code> factory.
++ * @see org.apache.commons.collections15.functors.ConstantFactory
++ */
++ public static <T> Factory<T> constantFactory(T constantToReturn) {
++ return ConstantFactory.getInstance(constantToReturn);
++ }
++
++ /**
++ * Creates a Factory that will return a clone of the same prototype object
++ * each time the factory is used. The prototype will be cloned using one of these
++ * techniques (in order):
++ * <ul>
++ * <li>public clone method
++ * <li>public copy constructor
++ * <li>serialization clone
++ * <ul>
++ *
++ * @param prototype the object to clone each time in the factory
++ * @return the <code>prototype</code> factory
++ * @throws IllegalArgumentException if the prototype is null
++ * @throws IllegalArgumentException if the prototype cannot be cloned
++ * @see org.apache.commons.collections15.functors.PrototypeFactory
++ */
++ public static <T> Factory<T> prototypeFactory(T prototype) {
++ return PrototypeFactory.getInstance(prototype);
++ }
++
++ /**
++ * Creates a Factory that can create objects of a specific type using
++ * a no-args constructor.
++ *
++ * @param classToInstantiate the Class to instantiate each time in the factory
++ * @return the <code>reflection</code> factory
++ * @throws IllegalArgumentException if the classToInstantiate is null
++ * @see org.apache.commons.collections15.functors.InstantiateFactory
++ */
++ public static <T> Factory<T> instantiateFactory(Class<T> classToInstantiate) {
++ return InstantiateFactory.getInstance(classToInstantiate, null, null);
++ }
++
++ /**
++ * Creates a Factory that can create objects of a specific type using
++ * the arguments specified to this method.
++ *
++ * @param classToInstantiate the Class to instantiate each time in the factory
++ * @param paramTypes parameter types for the constructor, can be null
++ * @param args the arguments to pass to the constructor, can be null
++ * @return the <code>reflection</code> factory
++ * @throws IllegalArgumentException if the classToInstantiate is null
++ * @throws IllegalArgumentException if the paramTypes and args don't match
++ * @throws IllegalArgumentException if the constructor doesn't exist
++ * @see org.apache.commons.collections15.functors.InstantiateFactory
++ */
++ public static <T> Factory<T> instantiateFactory(Class<T> classToInstantiate, Class[] paramTypes, Object[] args) {
++ return InstantiateFactory.getInstance(classToInstantiate, paramTypes, args);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/FunctorException.java
+@@ -0,0 +1,143 @@
++// GenericsNote: No conversion needed.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.io.PrintStream;
++import java.io.PrintWriter;
++
++/**
++ * Runtime exception thrown from functors.
++ * If required, a root cause error can be wrapped within this one.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public class FunctorException extends RuntimeException {
++
++ /**
++ * Does JDK support nested exceptions
++ */
++ private static final boolean JDK_SUPPORTS_NESTED;
++
++ static {
++ boolean flag = false;
++ try {
++ Throwable.class.getDeclaredMethod("getCause", new Class[0]);
++ flag = true;
++ } catch (NoSuchMethodException ex) {
++ flag = false;
++ }
++ JDK_SUPPORTS_NESTED = flag;
++ }
++
++ /**
++ * Root cause of the exception
++ */
++ private final Throwable rootCause;
++
++ /**
++ * Constructs a new <code>FunctorException</code> without specified
++ * detail message.
++ */
++ public FunctorException() {
++ super();
++ this.rootCause = null;
++ }
++
++ /**
++ * Constructs a new <code>FunctorException</code> with specified
++ * detail message.
++ *
++ * @param msg the error message.
++ */
++ public FunctorException(String msg) {
++ super(msg);
++ this.rootCause = null;
++ }
++
++ /**
++ * Constructs a new <code>FunctorException</code> with specified
++ * nested <code>Throwable</code> root cause.
++ *
++ * @param rootCause the exception or error that caused this exception
++ * to be thrown.
++ */
++ public FunctorException(Throwable rootCause) {
++ super((rootCause == null ? null : rootCause.getMessage()));
++ this.rootCause = rootCause;
++ }
++
++ /**
++ * Constructs a new <code>FunctorException</code> with specified
++ * detail message and nested <code>Throwable</code> root cause.
++ *
++ * @param msg the error message.
++ * @param rootCause the exception or error that caused this exception
++ * to be thrown.
++ */
++ public FunctorException(String msg, Throwable rootCause) {
++ super(msg);
++ this.rootCause = rootCause;
++ }
++
++ /**
++ * Gets the cause of this throwable.
++ *
++ * @return the cause of this throwable, or <code>null</code>
++ */
++ public Throwable getCause() {
++ return rootCause;
++ }
++
++ /**
++ * Prints the stack trace of this exception to the standard error stream.
++ */
++ public void printStackTrace() {
++ printStackTrace(System.err);
++ }
++
++ /**
++ * Prints the stack trace of this exception to the specified stream.
++ *
++ * @param out the <code>PrintStream</code> to use for output
++ */
++ public void printStackTrace(PrintStream out) {
++ synchronized (out) {
++ PrintWriter pw = new PrintWriter(out, false);
++ printStackTrace(pw);
++ // Flush the PrintWriter before it's GC'ed.
++ pw.flush();
++ }
++ }
++
++ /**
++ * Prints the stack trace of this exception to the specified writer.
++ *
++ * @param out the <code>PrintWriter</code> to use for output
++ */
++ public void printStackTrace(PrintWriter out) {
++ synchronized (out) {
++ super.printStackTrace(out);
++ if (rootCause != null && JDK_SUPPORTS_NESTED == false) {
++ out.print("Caused by: ");
++ rootCause.printStackTrace(out);
++ }
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/IterableMap.java
+@@ -0,0 +1,61 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.Map;
++
++/**
++ * Defines a map that can be iterated directly without needing to create an entry set.
++ * <p/>
++ * A map iterator is an efficient way of iterating over maps.
++ * There is no need to access the entry set or cast to Map Entry objects.
++ * <pre>
++ * IterableMap map = new HashedMap();
++ * MapIterator it = map.mapIterator();
++ * while (it.hasNext()) {
++ * Object key = it.next();
++ * Object value = it.getValue();
++ * it.setValue("newValue");
++ * }
++ * </pre>
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface IterableMap <K,V> extends Map<K, V> {
++
++ /**
++ * Obtains a <code>MapIterator</code> over the map.
++ * <p/>
++ * A map iterator is an efficient way of iterating over maps.
++ * There is no need to access the entry set or cast to Map Entry objects.
++ * <pre>
++ * IterableMap map = new HashedMap();
++ * MapIterator it = map.mapIterator();
++ * while (it.hasNext()) {
++ * Object key = it.next();
++ * Object value = it.getValue();
++ * it.setValue("newValue");
++ * }
++ * </pre>
++ *
++ * @return a map iterator
++ */
++ MapIterator<K, V> mapIterator();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/IteratorUtils.java
+@@ -0,0 +1,863 @@
++// GenericsNote: Converted, although getIterator(Object) is unsatisfying.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.iterators.*;
++
++import java.lang.reflect.Array;
++import java.lang.reflect.Method;
++import java.util.*;
++
++/**
++ * Provides static utility methods and decorators for {@link Iterator}
++ * instances. The implementations are provided in the iterators subpackage.
++ * <p/>
++ * WARNING: Due to human error certain binary incompatabilities were introduced
++ * between Commons Collections 2.1 and 3.0. The class remained source and test
++ * compatible, so if you can recompile all your classes and dependencies
++ * everything is OK. Those methods which are binary incompatible are marked as
++ * such, together with alternate solutions that are binary compatible
++ * against versions 2.1.1 and 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Phil Steitz
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 2.1
++ */
++public class IteratorUtils {
++ // validation is done in this class in certain cases because the
++ // public classes allow invalid states
++
++ /**
++ * An iterator over no elements.
++ * <p/>
++ * WARNING: This constant is binary incompatible with Commons Collections 2.1 and 2.1.1.
++ * Use <code>EmptyIterator.INSTANCE</code> for compatability with Commons Collections 2.1.1.
++ */
++ public static final ResettableIterator EMPTY_ITERATOR = EmptyIterator.RESETTABLE_INSTANCE;
++ /**
++ * A list iterator over no elements.
++ * <p/>
++ * WARNING: This constant is binary incompatible with Commons Collections 2.1 and 2.1.1.
++ * Use <code>EmptyListIterator.INSTANCE</code> for compatability with Commons Collections 2.1.1.
++ */
++ public static final ResettableListIterator EMPTY_LIST_ITERATOR = EmptyListIterator.RESETTABLE_INSTANCE;
++ /**
++ * An ordered iterator over no elements.
++ */
++ public static final OrderedIterator EMPTY_ORDERED_ITERATOR = EmptyOrderedIterator.INSTANCE;
++ /**
++ * A map iterator over no elements.
++ */
++ public static final MapIterator EMPTY_MAP_ITERATOR = EmptyMapIterator.INSTANCE;
++ /**
++ * An ordered map iterator over no elements.
++ */
++ public static final OrderedMapIterator EMPTY_ORDERED_MAP_ITERATOR = EmptyOrderedMapIterator.INSTANCE;
++
++ /**
++ * IteratorUtils is not normally instantiated.
++ */
++ public IteratorUtils() {
++ }
++
++ // Empty
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an empty iterator.
++ * <p/>
++ * This iterator is a valid iterator object that will iterate over
++ * nothing.
++ * <p/>
++ * WARNING: This method is binary incompatible with Commons Collections 2.1 and 2.1.1.
++ * Use <code>EmptyIterator.INSTANCE</code> for compatability with Commons Collections 2.1.1.
++ *
++ * @return an iterator over nothing
++ */
++ public static ResettableIterator emptyIterator() {
++ return EMPTY_ITERATOR;
++ }
++
++ /**
++ * Gets an empty list iterator.
++ * <p/>
++ * This iterator is a valid list iterator object that will iterate
++ * over nothing.
++ * <p/>
++ * WARNING: This method is binary incompatible with Commons Collections 2.1 and 2.1.1.
++ * Use <code>EmptyListIterator.INSTANCE</code> for compatability with Commons Collections 2.1.1.
++ *
++ * @return a list iterator over nothing
++ */
++ public static ResettableListIterator emptyListIterator() {
++ return EMPTY_LIST_ITERATOR;
++ }
++
++ /**
++ * Gets an empty ordered iterator.
++ * <p/>
++ * This iterator is a valid iterator object that will iterate
++ * over nothing.
++ *
++ * @return an ordered iterator over nothing
++ */
++ public static OrderedIterator emptyOrderedIterator() {
++ return EMPTY_ORDERED_ITERATOR;
++ }
++
++ /**
++ * Gets an empty map iterator.
++ * <p/>
++ * This iterator is a valid map iterator object that will iterate
++ * over nothing.
++ *
++ * @return a map iterator over nothing
++ */
++ public static MapIterator emptyMapIterator() {
++ return EMPTY_MAP_ITERATOR;
++ }
++
++ /**
++ * Gets an empty ordered map iterator.
++ * <p/>
++ * This iterator is a valid map iterator object that will iterate
++ * over nothing.
++ *
++ * @return a map iterator over nothing
++ */
++ public static OrderedMapIterator emptyOrderedMapIterator() {
++ return EMPTY_ORDERED_MAP_ITERATOR;
++ }
++
++ // Singleton
++ //-----------------------------------------------------------------------
++ /**
++ * Gets a singleton iterator.
++ * <p/>
++ * This iterator is a valid iterator object that will iterate over
++ * the specified object.
++ * <p/>
++ * WARNING: This method is binary incompatible with Commons Collections 2.1 and 2.1.1.
++ * Use <code>new SingletonIterator(object)</code> for compatability.
++ *
++ * @param object the single object over which to iterate
++ * @return a singleton iterator over the object
++ */
++ public static <E> ResettableIterator<E> singletonIterator(E object) {
++ return new SingletonIterator<E>(object);
++ }
++
++ /**
++ * Gets a singleton list iterator.
++ * <p/>
++ * This iterator is a valid list iterator object that will iterate over
++ * the specified object.
++ *
++ * @param object the single object over which to iterate
++ * @return a singleton list iterator over the object
++ */
++ public static <E> ListIterator<E> singletonListIterator(E object) {
++ return new SingletonListIterator<E>(object);
++ }
++
++ // Arrays
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator over an object array.
++ * <p/>
++ * WARNING: This method is binary incompatible with Commons Collections 2.1 and 2.1.1.
++ * Use <code>new ArrayIterator(array)</code> for compatability.
++ *
++ * @param array the array over which to iterate
++ * @return an iterator over the array
++ * @throws NullPointerException if array is null
++ */
++ public static <E> ResettableIterator<E> arrayIterator(E[] array) {
++ return new ObjectArrayIterator<E>(array);
++ }
++
++ /**
++ * Gets an iterator over an object or primitive array.
++ * <p/>
++ * This method will handle primitive arrays as well as object arrays.
++ * The primitives will be wrapped in the appropriate wrapper class.
++ *
++ * @param array the array over which to iterate
++ * @return an iterator over the array
++ * @throws IllegalArgumentException if the array is not an array
++ * @throws NullPointerException if array is null
++ */
++ public static <E> ResettableIterator<E> arrayIterator(Object array) {
++ return new ArrayIterator<E>(array);
++ }
++
++ /**
++ * Gets an iterator over the end part of an object array.
++ * <p/>
++ * WARNING: This method is binary incompatible with Commons Collections 2.1 and 2.1.1.
++ * Use <code>new ArrayIterator(array,start)</code> for compatability.
++ *
++ * @param array the array over which to iterate
++ * @param start the index to start iterating at
++ * @return an iterator over part of the array
++ * @throws IndexOutOfBoundsException if start is less than zero or greater
++ * than the length of the array
++ * @throws NullPointerException if array is null
++ */
++ public static <E> ResettableIterator<E> arrayIterator(E[] array, int start) {
++ return new ObjectArrayIterator<E>(array, start);
++ }
++
++ /**
++ * Gets an iterator over the end part of an object or primitive array.
++ * <p/>
++ * This method will handle primitive arrays as well as object arrays.
++ * The primitives will be wrapped in the appropriate wrapper class.
++ *
++ * @param array the array over which to iterate
++ * @param start the index to start iterating at
++ * @return an iterator over part of the array
++ * @throws IllegalArgumentException if the array is not an array
++ * @throws IndexOutOfBoundsException if start is less than zero or greater
++ * than the length of the array
++ * @throws NullPointerException if array is null
++ */
++ public static <E> ResettableIterator<E> arrayIterator(Object array, int start) {
++ return new ArrayIterator<E>(array, start);
++ }
++
++ /**
++ * Gets an iterator over part of an object array.
++ * <p/>
++ * WARNING: This method is binary incompatible with Commons Collections 2.1 and 2.1.1.
++ * Use <code>new ArrayIterator(array,start,end)</code> for compatability.
++ *
++ * @param array the array over which to iterate
++ * @param start the index to start iterating at
++ * @param end the index to finish iterating at
++ * @return an iterator over part of the array
++ * @throws IndexOutOfBoundsException if array bounds are invalid
++ * @throws IllegalArgumentException if end is before start
++ * @throws NullPointerException if array is null
++ */
++ public static <E> ResettableIterator<E> arrayIterator(E[] array, int start, int end) {
++ return new ObjectArrayIterator<E>(array, start, end);
++ }
++
++ /**
++ * Gets an iterator over part of an object or primitive array.
++ * <p/>
++ * This method will handle primitive arrays as well as object arrays.
++ * The primitives will be wrapped in the appropriate wrapper class.
++ *
++ * @param array the array over which to iterate
++ * @param start the index to start iterating at
++ * @param end the index to finish iterating at
++ * @return an iterator over part of the array
++ * @throws IllegalArgumentException if the array is not an array
++ * @throws IndexOutOfBoundsException if array bounds are invalid
++ * @throws IllegalArgumentException if end is before start
++ * @throws NullPointerException if array is null
++ */
++ public static <E> ResettableIterator<E> arrayIterator(Object array, int start, int end) {
++ return new ArrayIterator<E>(array, start, end);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets a list iterator over an object array.
++ *
++ * @param array the array over which to iterate
++ * @return a list iterator over the array
++ * @throws NullPointerException if array is null
++ */
++ public static <E> ResettableListIterator<E> arrayListIterator(E[] array) {
++ return new ObjectArrayListIterator(array);
++ }
++
++ /**
++ * Gets a list iterator over an object or primitive array.
++ * <p/>
++ * This method will handle primitive arrays as well as object arrays.
++ * The primitives will be wrapped in the appropriate wrapper class.
++ *
++ * @param array the array over which to iterate
++ * @return a list iterator over the array
++ * @throws IllegalArgumentException if the array is not an array
++ * @throws NullPointerException if array is null
++ */
++ public static <E> ResettableListIterator<E> arrayListIterator(Object array) {
++ return new ArrayListIterator<E>(array);
++ }
++
++ /**
++ * Gets a list iterator over the end part of an object array.
++ *
++ * @param array the array over which to iterate
++ * @param start the index to start iterating at
++ * @return a list iterator over part of the array
++ * @throws IndexOutOfBoundsException if start is less than zero
++ * @throws NullPointerException if array is null
++ */
++ public static <E> ResettableListIterator<E> arrayListIterator(E[] array, int start) {
++ return new ObjectArrayListIterator<E>(array, start);
++ }
++
++ /**
++ * Gets a list iterator over the end part of an object or primitive array.
++ * <p/>
++ * This method will handle primitive arrays as well as object arrays.
++ * The primitives will be wrapped in the appropriate wrapper class.
++ *
++ * @param array the array over which to iterate
++ * @param start the index to start iterating at
++ * @return a list iterator over part of the array
++ * @throws IllegalArgumentException if the array is not an array
++ * @throws IndexOutOfBoundsException if start is less than zero
++ * @throws NullPointerException if array is null
++ */
++ public static <E> ResettableListIterator<E> arrayListIterator(Object array, int start) {
++ return new ArrayListIterator<E>(array, start);
++ }
++
++ /**
++ * Gets a list iterator over part of an object array.
++ *
++ * @param array the array over which to iterate
++ * @param start the index to start iterating at
++ * @param end the index to finish iterating at
++ * @return a list iterator over part of the array
++ * @throws IndexOutOfBoundsException if array bounds are invalid
++ * @throws IllegalArgumentException if end is before start
++ * @throws NullPointerException if array is null
++ */
++ public static <E> ResettableListIterator<E> arrayListIterator(E[] array, int start, int end) {
++ return new ObjectArrayListIterator<E>(array, start, end);
++ }
++
++ /**
++ * Gets a list iterator over part of an object or primitive array.
++ * <p/>
++ * This method will handle primitive arrays as well as object arrays.
++ * The primitives will be wrapped in the appropriate wrapper class.
++ *
++ * @param array the array over which to iterate
++ * @param start the index to start iterating at
++ * @param end the index to finish iterating at
++ * @return a list iterator over part of the array
++ * @throws IllegalArgumentException if the array is not an array
++ * @throws IndexOutOfBoundsException if array bounds are invalid
++ * @throws IllegalArgumentException if end is before start
++ * @throws NullPointerException if array is null
++ */
++ public static <E> ResettableListIterator<E> arrayListIterator(Object array, int start, int end) {
++ return new ArrayListIterator<E>(array, start, end);
++ }
++
++ // Unmodifiable
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an immutable version of an {@link Iterator}. The returned object
++ * will always throw an {@link UnsupportedOperationException} for
++ * the {@link Iterator#remove} method.
++ *
++ * @param iterator the iterator to make immutable
++ * @return an immutable version of the iterator
++ */
++ public static <E> Iterator<E> unmodifiableIterator(Iterator<E> iterator) {
++ return UnmodifiableIterator.decorate(iterator);
++ }
++
++ /**
++ * Gets an immutable version of a {@link ListIterator}. The returned object
++ * will always throw an {@link UnsupportedOperationException} for
++ * the {@link Iterator#remove}, {@link ListIterator#add} and
++ * {@link ListIterator#set} methods.
++ *
++ * @param listIterator the iterator to make immutable
++ * @return an immutable version of the iterator
++ */
++ public static <E> ListIterator<E> unmodifiableListIterator(ListIterator<E> listIterator) {
++ return UnmodifiableListIterator.decorate(listIterator);
++ }
++
++ /**
++ * Gets an immutable version of a {@link MapIterator}. The returned object
++ * will always throw an {@link UnsupportedOperationException} for
++ * the {@link Iterator#remove}, {@link MapIterator#setValue(Object)} methods.
++ *
++ * @param mapIterator the iterator to make immutable
++ * @return an immutable version of the iterator
++ */
++ public static <K,V> MapIterator<K, V> unmodifiableMapIterator(MapIterator<K, V> mapIterator) {
++ return UnmodifiableMapIterator.decorate(mapIterator);
++ }
++
++ // Chained
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator that iterates through two {@link Iterator}s
++ * one after another.
++ *
++ * @param iterator1 the first iterators to use, not null
++ * @param iterator2 the first iterators to use, not null
++ * @return a combination iterator over the iterators
++ * @throws NullPointerException if either iterator is null
++ */
++ public static <E> Iterator<E> chainedIterator(Iterator<E> iterator1, Iterator<E> iterator2) {
++ return new IteratorChain<E>(iterator1, iterator2);
++ }
++
++ /**
++ * Gets an iterator that iterates through an array of {@link Iterator}s
++ * one after another.
++ *
++ * @param iterators the iterators to use, not null or empty or contain nulls
++ * @return a combination iterator over the iterators
++ * @throws NullPointerException if iterators array is null or contains a null
++ */
++ public static <E> Iterator<E> chainedIterator(Iterator<E>[] iterators) {
++ return new IteratorChain<E>(iterators);
++ }
++
++ /**
++ * Gets an iterator that iterates through a collections15 of {@link Iterator}s
++ * one after another.
++ *
++ * @param iterators the iterators to use, not null or empty or contain nulls
++ * @return a combination iterator over the iterators
++ * @throws NullPointerException if iterators collection is null or contains a null
++ * @throws ClassCastException if the iterators collection contains the wrong object type
++ */
++ public static <E> Iterator<E> chainedIterator(Collection<Iterator<? extends E>> iterators) {
++ return new IteratorChain<E>(iterators);
++ }
++
++ // Collated
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator that provides an ordered iteration over the elements
++ * contained in a collection of ordered {@link Iterator}s.
++ * <p/>
++ * Given two ordered {@link Iterator}s <code>A</code> and <code>B</code>,
++ * the {@link Iterator#next()} method will return the lesser of
++ * <code>A.next()</code> and <code>B.next()</code>.
++ * <p/>
++ * The comparator is optional. If null is specified then natural order is used.
++ *
++ * @param comparator the comparator to use, may be null for natural order
++ * @param iterator1 the first iterators to use, not null
++ * @param iterator2 the first iterators to use, not null
++ * @return a combination iterator over the iterators
++ * @throws NullPointerException if either iterator is null
++ */
++ public static <E> Iterator<E> collatedIterator(Comparator<? super E> comparator, Iterator<? extends E> iterator1, Iterator<? extends E> iterator2) {
++ return new CollatingIterator<E>(comparator, iterator1, iterator2);
++ }
++
++ /**
++ * Gets an iterator that provides an ordered iteration over the elements
++ * contained in an array of {@link Iterator}s.
++ * <p/>
++ * Given two ordered {@link Iterator}s <code>A</code> and <code>B</code>,
++ * the {@link Iterator#next()} method will return the lesser of
++ * <code>A.next()</code> and <code>B.next()</code> and so on.
++ * <p/>
++ * The comparator is optional. If null is specified then natural order is used.
++ *
++ * @param comparator the comparator to use, may be null for natural order
++ * @param iterators the iterators to use, not null or empty or contain nulls
++ * @return a combination iterator over the iterators
++ * @throws NullPointerException if iterators array is null or contains a null
++ */
++ public static <E> Iterator<E> collatedIterator(Comparator<? super E> comparator, Iterator<? extends E>[] iterators) {
++ return new CollatingIterator<E>(comparator, iterators);
++ }
++
++ /**
++ * Gets an iterator that provides an ordered iteration over the elements
++ * contained in a collection of {@link Iterator}s.
++ * <p/>
++ * Given two ordered {@link Iterator}s <code>A</code> and <code>B</code>,
++ * the {@link Iterator#next()} method will return the lesser of
++ * <code>A.next()</code> and <code>B.next()</code> and so on.
++ * <p/>
++ * The comparator is optional. If null is specified then natural order is used.
++ *
++ * @param comparator the comparator to use, may be null for natural order
++ * @param iterators the iterators to use, not null or empty or contain nulls
++ * @return a combination iterator over the iterators
++ * @throws NullPointerException if iterators collection is null or contains a null
++ * @throws ClassCastException if the iterators collection contains the wrong object type
++ */
++ public static <E> Iterator<E> collatedIterator(Comparator<? super E> comparator, Collection<Iterator<? extends E>> iterators) {
++ return new CollatingIterator<E>(comparator, iterators);
++ }
++
++ // Object Graph
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator that operates over an object graph.
++ * <p/>
++ * This iterator can extract multiple objects from a complex tree-like object graph.
++ * The iteration starts from a single root object.
++ * It uses a <code>Transformer</code> to extract the iterators and elements.
++ * Its main benefit is that no intermediate <code>List</code> is created.
++ * <p/>
++ * For example, consider an object graph:
++ * <pre>
++ * |- Branch -- Leaf
++ * | \- Leaf
++ * |- Tree | /- Leaf
++ * | |- Branch -- Leaf
++ * Forest | \- Leaf
++ * | |- Branch -- Leaf
++ * | | \- Leaf
++ * |- Tree | /- Leaf
++ * |- Branch -- Leaf
++ * |- Branch -- Leaf</pre>
++ * The following <code>Transformer</code>, used in this class, will extract all
++ * the Leaf objects without creating a combined intermediate list:
++ * <pre>
++ * public Object transform(Object input) {
++ * if (input instanceof Forest) {
++ * return ((Forest) input).treeIterator();
++ * }
++ * if (input instanceof Tree) {
++ * return ((Tree) input).branchIterator();
++ * }
++ * if (input instanceof Branch) {
++ * return ((Branch) input).leafIterator();
++ * }
++ * if (input instanceof Leaf) {
++ * return input;
++ * }
++ * throw new ClassCastException();
++ * }</pre>
++ * <p/>
++ * Internally, iteration starts from the root object. When next is called,
++ * the transformer is called to examine the object. The transformer will return
++ * either an iterator or an object. If the object is an Iterator, the next element
++ * from that iterator is obtained and the process repeats. If the element is an object
++ * it is returned.
++ * <p/>
++ * Under many circumstances, linking Iterators together in this manner is
++ * more efficient (and convenient) than using nested for loops to extract a list.
++ *
++ * @param root the root object to start iterating from, null results in an empty iterator
++ * @param transformer the transformer to use, see above, null uses no effect transformer
++ * @return a new object graph iterator
++ * @since Commons Collections 3.1
++ */
++ public static Iterator objectGraphIterator(Object root, Transformer transformer) {
++ return new ObjectGraphIterator(root, transformer);
++ }
++
++ // Transformed
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator that transforms the elements of another iterator.
++ * <p/>
++ * The transformation occurs during the next() method and the underlying
++ * iterator is unaffected by the transformation.
++ *
++ * @param iterator the iterator to use, not null
++ * @param transform the transform to use, not null
++ * @return a new transforming iterator
++ * @throws NullPointerException if either parameter is null
++ */
++ public static <I,O> Iterator<O> transformedIterator(Iterator<I> iterator, Transformer<I, O> transform) {
++ if (iterator == null) {
++ throw new NullPointerException("Iterator must not be null");
++ }
++ if (transform == null) {
++ throw new NullPointerException("Transformer must not be null");
++ }
++ return new TransformIterator<I, O>(iterator, transform);
++ }
++
++ // Filtered
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator that filters another iterator.
++ * <p/>
++ * The returned iterator will only return objects that match the specified
++ * filtering predicate.
++ *
++ * @param iterator the iterator to use, not null
++ * @param predicate the predicate to use as a filter, not null
++ * @return a new filtered iterator
++ * @throws NullPointerException if either parameter is null
++ */
++ public static <E> Iterator<E> filteredIterator(Iterator<E> iterator, Predicate<? super E> predicate) {
++ if (iterator == null) {
++ throw new NullPointerException("Iterator must not be null");
++ }
++ if (predicate == null) {
++ throw new NullPointerException("Predicate must not be null");
++ }
++ return new FilterIterator<E>(iterator, predicate);
++ }
++
++ /**
++ * Gets a list iterator that filters another list iterator.
++ * <p/>
++ * The returned iterator will only return objects that match the specified
++ * filtering predicate.
++ *
++ * @param listIterator the list iterator to use, not null
++ * @param predicate the predicate to use as a filter, not null
++ * @return a new filtered iterator
++ * @throws NullPointerException if either parameter is null
++ */
++ public static <E> ListIterator<E> filteredListIterator(ListIterator<E> listIterator, Predicate<? super E> predicate) {
++ if (listIterator == null) {
++ throw new NullPointerException("ListIterator must not be null");
++ }
++ if (predicate == null) {
++ throw new NullPointerException("Predicate must not be null");
++ }
++ return new FilterListIterator<E>(listIterator, predicate);
++ }
++
++ // Looping
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator that loops continuously over the supplied collection.
++ * <p/>
++ * The iterator will only stop looping if the remove method is called
++ * enough times to empty the collection, or if the collection is empty
++ * to start with.
++ *
++ * @param coll the collection to iterate over, not null
++ * @return a new looping iterator
++ * @throws NullPointerException if the collection is null
++ */
++ public static <E> ResettableIterator<E> loopingIterator(Collection<E> coll) {
++ if (coll == null) {
++ throw new NullPointerException("Collection must not be null");
++ }
++ return new LoopingIterator<E>(coll);
++ }
++
++ // Views
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator that provides an iterator view of the given enumeration.
++ *
++ * @param enumeration the enumeration to use
++ * @return a new iterator
++ */
++ public static <E> Iterator<E> asIterator(Enumeration<E> enumeration) {
++ if (enumeration == null) {
++ throw new NullPointerException("Enumeration must not be null");
++ }
++ return new EnumerationIterator<E>(enumeration);
++ }
++
++ /**
++ * Gets an iterator that provides an iterator view of the given enumeration
++ * that will remove elements from the specified collection.
++ *
++ * @param enumeration the enumeration to use
++ * @param removeCollection the collection to remove elements from
++ * @return a new iterator
++ */
++ public static <E> Iterator<E> asIterator(Enumeration<E> enumeration, Collection<E> removeCollection) {
++ if (enumeration == null) {
++ throw new NullPointerException("Enumeration must not be null");
++ }
++ if (removeCollection == null) {
++ throw new NullPointerException("Collection must not be null");
++ }
++ return new EnumerationIterator<E>(enumeration, removeCollection);
++ }
++
++ /**
++ * Gets an enumeration that wraps an iterator.
++ *
++ * @param iterator the iterator to use, not null
++ * @return a new enumeration
++ * @throws NullPointerException if iterator is null
++ */
++ public static <E> Enumeration<E> asEnumeration(Iterator<E> iterator) {
++ if (iterator == null) {
++ throw new NullPointerException("Iterator must not be null");
++ }
++ return new IteratorEnumeration<E>(iterator);
++ }
++
++ /**
++ * Gets a list iterator based on a simple iterator.
++ * <p/>
++ * As the wrapped Iterator is traversed, a LinkedList of its values is
++ * cached, permitting all required operations of ListIterator.
++ *
++ * @param iterator the iterator to use, not null
++ * @return a new iterator
++ * @throws NullPointerException if iterator parameter is null
++ */
++ public static <E> ListIterator<E> toListIterator(Iterator<E> iterator) {
++ if (iterator == null) {
++ throw new NullPointerException("Iterator must not be null");
++ }
++ return new ListIteratorWrapper<E>(iterator);
++ }
++
++ /**
++ * Gets an array based on an iterator.
++ * <p/>
++ * As the wrapped Iterator is traversed, an ArrayList of its values is
++ * created. At the end, this is converted to an array.
++ *
++ * @param iterator the iterator to use, not null
++ * @return an array of the iterator contents
++ * @throws NullPointerException if iterator parameter is null
++ */
++ public static <E> E[] toArray(Iterator<E> iterator) {
++ if (iterator == null) {
++ throw new NullPointerException("Iterator must not be null");
++ }
++ List<E> list = toList(iterator, 100);
++ return (E[]) list.toArray();
++ }
++
++ /**
++ * Gets an array based on an iterator.
++ * <p/>
++ * As the wrapped Iterator is traversed, an ArrayList of its values is
++ * created. At the end, this is converted to an array.
++ *
++ * @param iterator the iterator to use, not null
++ * @param arrayClass the class of array to create
++ * @return an array of the iterator contents
++ * @throws NullPointerException if iterator parameter is null
++ * @throws NullPointerException if arrayClass is null
++ * @throws ClassCastException if the arrayClass is invalid
++ */
++ public static <E> E[] toArray(Iterator<E> iterator, Class<E> arrayClass) {
++ if (iterator == null) {
++ throw new NullPointerException("Iterator must not be null");
++ }
++ if (arrayClass == null) {
++ throw new NullPointerException("Array class must not be null");
++ }
++ List<E> list = toList(iterator, 100);
++ return list.toArray((E[]) Array.newInstance(arrayClass, list.size()));
++ }
++
++ /**
++ * Gets a list based on an iterator.
++ * <p/>
++ * As the wrapped Iterator is traversed, an ArrayList of its values is
++ * created. At the end, the list is returned.
++ *
++ * @param iterator the iterator to use, not null
++ * @return a list of the iterator contents
++ * @throws NullPointerException if iterator parameter is null
++ */
++ public static <E> List<E> toList(Iterator<E> iterator) {
++ return toList(iterator, 10);
++ }
++
++ /**
++ * Gets a list based on an iterator.
++ * <p/>
++ * As the wrapped Iterator is traversed, an ArrayList of its values is
++ * created. At the end, the list is returned.
++ *
++ * @param iterator the iterator to use, not null
++ * @param estimatedSize the initial size of the ArrayList
++ * @return a list of the iterator contents
++ * @throws NullPointerException if iterator parameter is null
++ * @throws IllegalArgumentException if the size is less than 1
++ */
++ public static <E> List<E> toList(Iterator<E> iterator, int estimatedSize) {
++ if (iterator == null) {
++ throw new NullPointerException("Iterator must not be null");
++ }
++ if (estimatedSize < 1) {
++ throw new IllegalArgumentException("Estimated size must be greater than 0");
++ }
++ List<E> list = new ArrayList<E>(estimatedSize);
++ while (iterator.hasNext()) {
++ list.add(iterator.next());
++ }
++ return list;
++ }
++
++ /**
++ * Gets a suitable Iterator for the given object.
++ * <p/>
++ * This method can handles objects as follows
++ * <ul>
++ * <li>null - empty iterator
++ * <li>Iterator - returned directly
++ * <li>Enumeration - wrapped
++ * <li>Collection - iterator from collection returned
++ * <li>Map - values iterator returned
++ * <li>Dictionary - values (elements) enumeration returned as iterator
++ * <li>array - iterator over array returned
++ * <li>object with iterator() public method accessed by reflection
++ * <li>object - singleton iterator
++ * </ul>
++ *
++ * @param obj the object to convert to an iterator
++ * @return a suitable iterator, never null
++ */
++ public static Iterator getIterator(Object obj) {
++ if (obj == null) {
++ return emptyIterator();
++
++ } else if (obj instanceof Iterator) {
++ return (Iterator) obj;
++
++ } else if (obj instanceof Collection) {
++ return ((Collection) obj).iterator();
++
++ } else if (obj instanceof Object[]) {
++ return new ObjectArrayIterator((Object[]) obj);
++
++ } else if (obj instanceof Enumeration) {
++ return new EnumerationIterator((Enumeration) obj);
++
++ } else if (obj instanceof Map) {
++ return ((Map) obj).values().iterator();
++
++ } else if (obj instanceof Dictionary) {
++ return new EnumerationIterator(((Dictionary) obj).elements());
++
++ } else if (obj != null && obj.getClass().isArray()) {
++ return new ArrayIterator(obj);
++
++ } else {
++ try {
++ Method method = obj.getClass().getMethod("iterator", null);
++ if (Iterator.class.isAssignableFrom(method.getReturnType())) {
++ Iterator it = (Iterator) method.invoke(obj, null);
++ if (it != null) {
++ return it;
++ }
++ }
++ } catch (Exception ex) {
++ // ignore
++ }
++ return singletonIterator(obj);
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/KeyValue.java
+@@ -0,0 +1,46 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++/**
++ * Defines a simple key value pair.
++ * <p/>
++ * A Map Entry has considerable additional semantics over and above a simple
++ * key-value pair. This interface defines the minimum key value, with just the
++ * two get methods.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface KeyValue <K,V> {
++
++ /**
++ * Gets the key from the pair.
++ *
++ * @return the key
++ */
++ K getKey();
++
++ /**
++ * Gets the value from the pair.
++ *
++ * @return the value
++ */
++ V getValue();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/ListUtils.java
+@@ -0,0 +1,345 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.list.*;
++
++import java.util.*;
++
++/**
++ * Provides utility methods and decorators for {@link List} instances.
++ *
++ * @author Federico Barbieri
++ * @author Peter Donald
++ * @author Paul Jack
++ * @author Stephen Colebourne
++ * @author Neil O'Toole
++ * @author Matt Hall, John Watkinson, Matthew Hawthorne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 1.0
++ */
++public class ListUtils {
++
++ /**
++ * An empty unmodifiable list.
++ * This uses the {@link Collections Collections} implementation
++ * and is provided for completeness.
++ */
++ public static final List EMPTY_LIST = Collections.EMPTY_LIST;
++
++ /**
++ * <code>ListUtils</code> should not normally be instantiated.
++ */
++ public ListUtils() {
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a new list containing all elements that are contained in
++ * both given lists.
++ *
++ * @param list1 the first list
++ * @param list2 the second list
++ * @return the intersection of those two lists
++ * @throws NullPointerException if either list is null
++ */
++ public static <E> List<E> intersection(final List<? extends E> list1, final List<? extends E> list2) {
++ final ArrayList<E> result = new ArrayList<E>();
++ final Iterator<? extends E> iterator = list2.iterator();
++
++ while (iterator.hasNext()) {
++ final E o = iterator.next();
++
++ if (list1.contains(o)) {
++ result.add(o);
++ }
++ }
++
++ return result;
++ }
++
++ /**
++ * Subtracts all elements in the second list from the first list,
++ * placing the results in a new list.
++ * <p/>
++ * This differs from {@link List#removeAll(Collection)} in that
++ * cardinality is respected; if <Code>list1</Code> contains two
++ * occurrences of <Code>null</Code> and <Code>list2</Code> only
++ * contains one occurrence, then the returned list will still contain
++ * one occurrence.
++ *
++ * @param list1 the list to subtract from
++ * @param list2 the list to subtract
++ * @return a new list containing the results
++ * @throws NullPointerException if either list is null
++ */
++ public static <E> List<E> subtract(final List<? extends E> list1, final List<? extends E> list2) {
++ final ArrayList<E> result = new ArrayList<E>(list1);
++ final Iterator<? extends E> iterator = list2.iterator();
++
++ while (iterator.hasNext()) {
++ result.remove(iterator.next());
++ }
++
++ return result;
++ }
++
++ /**
++ * Returns the sum of the given lists. This is their intersection
++ * subtracted from their union.
++ *
++ * @param list1 the first list
++ * @param list2 the second list
++ * @return a new list containing the sum of those lists
++ * @throws NullPointerException if either list is null
++ */
++ public static <E> List<E> sum(final List<? extends E> list1, final List<? extends E> list2) {
++ return subtract(union(list1, list2), intersection(list1, list2));
++ }
++
++ /**
++ * Returns a new list containing the second list appended to the
++ * first list. The {@link List#addAll(Collection)} operation is
++ * used to append the two given lists into a new list.
++ *
++ * @param list1 the first list
++ * @param list2 the second list
++ * @return a new list containing the union of those lists
++ * @throws NullPointerException if either list is null
++ */
++ public static <E> List<E> union(final List<? extends E> list1, final List<? extends E> list2) {
++ final ArrayList<E> result = new ArrayList<E>(list1);
++ result.addAll(list2);
++ return result;
++ }
++
++ /**
++ * Tests two lists for value-equality as per the equality contract in
++ * {@link java.util.List#equals(java.lang.Object)}.
++ * <p/>
++ * This method is useful for implementing <code>List</code> when you cannot
++ * extend AbstractList. The method takes Collection instances to enable other
++ * collection types to use the List implementation algorithm.
++ * <p/>
++ * The relevant text (slightly paraphrased as this is a static method) is:
++ * <blockquote>
++ * Compares the two list objects for equality. Returns
++ * <tt>true</tt> if and only if both
++ * lists have the same size, and all corresponding pairs of elements in
++ * the two lists are <i>equal</i>. (Two elements <tt>e1</tt> and
++ * <tt>e2</tt> are <i>equal</i> if <tt>(e1==null ? e2==null :
++ * e1.equals(e2))</tt>.) In other words, two lists are defined to be
++ * equal if they contain the same elements in the same order. This
++ * definition ensures that the equals method works properly across
++ * different implementations of the <tt>List</tt> interface.
++ * </blockquote>
++ * <p/>
++ * <b>Note:</b> The behaviour of this method is undefined if the lists are
++ * modified during the equals comparison.
++ *
++ * @param list1 the first list, may be null
++ * @param list2 the second list, may be null
++ * @return whether the lists are equal by value comparison
++ * @see java.util.List
++ */
++ public static <E> boolean isEqualList(final Collection<? extends E> list1, final Collection<? extends E> list2) {
++ if (list1 == list2) {
++ return true;
++ }
++ if (list1 == null || list2 == null || list1.size() != list2.size()) {
++ return false;
++ }
++
++ Iterator<? extends E> it1 = list1.iterator();
++ Iterator<? extends E> it2 = list2.iterator();
++ E obj1 = null;
++ E obj2 = null;
++
++ while (it1.hasNext() && it2.hasNext()) {
++ obj1 = it1.next();
++ obj2 = it2.next();
++
++ if (!(obj1 == null ? obj2 == null : obj1.equals(obj2))) {
++ return false;
++ }
++ }
++
++ return !(it1.hasNext() || it2.hasNext());
++ }
++
++ /**
++ * Generates a hash code using the algorithm specified in
++ * {@link java.util.List#hashCode()}.
++ * <p/>
++ * This method is useful for implementing <code>List</code> when you cannot
++ * extend AbstractList. The method takes Collection instances to enable other
++ * collection types to use the List implementation algorithm.
++ *
++ * @param list the list to generate the hashCode for, may be null
++ * @return the hash code
++ * @see java.util.List#hashCode()
++ */
++ public static int hashCodeForList(final Collection list) {
++ if (list == null) {
++ return 0;
++ }
++ int hashCode = 1;
++ Iterator it = list.iterator();
++ Object obj = null;
++
++ while (it.hasNext()) {
++ obj = it.next();
++ hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
++ }
++ return hashCode;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a synchronized list backed by the given list.
++ * <p/>
++ * You must manually synchronize on the returned buffer's iterator to
++ * avoid non-deterministic behavior:
++ * <p/>
++ * <pre>
++ * List list = ListUtils.synchronizedList(myList);
++ * synchronized (list) {
++ * Iterator i = list.iterator();
++ * while (i.hasNext()) {
++ * process (i.next());
++ * }
++ * }
++ * </pre>
++ * <p/>
++ * This method uses the implementation in the decorators subpackage.
++ *
++ * @param list the list to synchronize, must not be null
++ * @return a synchronized list backed by the given list
++ * @throws IllegalArgumentException if the list is null
++ */
++ public static <E> List<E> synchronizedList(List<E> list) {
++ return SynchronizedList.decorate(list);
++ }
++
++ /**
++ * Returns an unmodifiable list backed by the given list.
++ * <p/>
++ * This method uses the implementation in the decorators subpackage.
++ *
++ * @param list the list to make unmodifiable, must not be null
++ * @return an unmodifiable list backed by the given list
++ * @throws IllegalArgumentException if the list is null
++ */
++ public static <E> List<E> unmodifiableList(List<E> list) {
++ return UnmodifiableList.decorate(list);
++ }
++
++ /**
++ * Returns a predicated (validating) list backed by the given list.
++ * <p/>
++ * Only objects that pass the test in the given predicate can be added to the list.
++ * Trying to add an invalid object results in an IllegalArgumentException.
++ * It is important not to use the original list after invoking this method,
++ * as it is a backdoor for adding invalid objects.
++ *
++ * @param list the list to predicate, must not be null
++ * @param predicate the predicate for the list, must not be null
++ * @return a predicated list backed by the given list
++ * @throws IllegalArgumentException if the List or Predicate is null
++ */
++ public static <E> List<E> predicatedList(List<E> list, Predicate<? super E> predicate) {
++ return PredicatedList.decorate(list, predicate);
++ }
++
++ /**
++ * Returns a typed list backed by the given list.
++ * <p/>
++ * Only objects of the specified type can be added to the list.
++ *
++ * @param list the list to limit to a specific type, must not be null
++ * @param type the type of objects which may be added to the list
++ * @return a typed list backed by the specified list
++ * @deprecated Java generics makes this method obsolete.
++ */
++ public static <E> List<E> typedList(List<E> list, Class<E> type) {
++ return TypedList.decorate(list, type);
++ }
++
++ /**
++ * Returns a transformed list backed by the given list.
++ * <p/>
++ * Each object is passed through the transformer as it is added to the
++ * List. It is important not to use the original list after invoking this
++ * method, as it is a backdoor for adding untransformed objects.
++ *
++ * @param list the list to predicate, must not be null
++ * @param transformer the transformer for the list, must not be null
++ * @return a transformed list backed by the given list
++ * @throws IllegalArgumentException if the List or Transformer is null
++ */
++ public static <I,O> List<O> transformedList(List<I> list, Transformer<? super I, ? extends O> transformer) {
++ return TransformedList.decorate(list, transformer);
++ }
++
++ /**
++ * Returns a "lazy" list whose elements will be created on demand.
++ * <p/>
++ * When the index passed to the returned list's {@link List#get(int) get}
++ * method is greater than the list's size, then the factory will be used
++ * to create a new object and that object will be inserted at that index.
++ * <p/>
++ * For instance:
++ * <p/>
++ * <pre>
++ * Factory factory = new Factory() {
++ * public Object create() {
++ * return new Date();
++ * }
++ * }
++ * List lazy = ListUtils.lazyList(new ArrayList(), factory);
++ * Object obj = lazy.get(3);
++ * </pre>
++ * <p/>
++ * After the above code is executed, <code>obj</code> will contain
++ * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
++ * instance is the fourth element in the list. The first, second,
++ * and third element are all set to <code>null</code>.
++ *
++ * @param list the list to make lazy, must not be null
++ * @param factory the factory for creating new objects, must not be null
++ * @return a lazy list backed by the given list
++ * @throws IllegalArgumentException if the List or Factory is null
++ */
++ public static <E> List<E> lazyList(List<E> list, Factory<? extends E> factory) {
++ return LazyList.decorate(list, factory);
++ }
++
++ /**
++ * Returns a fixed-sized list backed by the given list.
++ * Elements may not be added or removed from the returned list, but
++ * existing elements can be changed (for instance, via the
++ * {@link List#set(int,Object)} method).
++ *
++ * @param list the list whose size to fix, must not be null
++ * @return a fixed-size list backed by that list
++ * @throws IllegalArgumentException if the List is null
++ */
++ public static <E> List<E> fixedSizeList(List<E> list) {
++ return FixedSizeList.decorate(list);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/MapIterator.java
+@@ -0,0 +1,109 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.Iterator;
++
++/**
++ * Defines an iterator that operates over a <code>Map</code>.
++ * <p/>
++ * This iterator is a special version designed for maps. It can be more
++ * efficient to use this rather than an entry set iterator where the option
++ * is available, and it is certainly more convenient.
++ * <p/>
++ * A map that provides this interface may not hold the data internally using
++ * Map Entry objects, thus this interface can avoid lots of object creation.
++ * <p/>
++ * In use, this iterator iterates through the keys in the map. After each call
++ * to <code>next()</code>, the <code>getValue()</code> method provides direct
++ * access to the value. The value can also be set using <code>setValue()</code>.
++ * <pre>
++ * MapIterator it = map.mapIterator();
++ * while (it.hasNext()) {
++ * Object key = it.next();
++ * Object value = it.getValue();
++ * it.setValue(newValue);
++ * }
++ * </pre>
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface MapIterator <K,V> extends Iterator<K> {
++
++ /**
++ * Checks to see if there are more entries still to be iterated.
++ *
++ * @return <code>true</code> if the iterator has more elements
++ */
++ boolean hasNext();
++
++ /**
++ * Gets the next <em>key</em> from the <code>Map</code>.
++ *
++ * @return the next key in the iteration
++ * @throws java.util.NoSuchElementException
++ * if the iteration is finished
++ */
++ K next();
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the current key, which is the key returned by the last call
++ * to <code>next()</code>.
++ *
++ * @return the current key
++ * @throws IllegalStateException if <code>next()</code> has not yet been called
++ */
++ K getKey();
++
++ /**
++ * Gets the current value, which is the value associated with the last key
++ * returned by <code>next()</code>.
++ *
++ * @return the current value
++ * @throws IllegalStateException if <code>next()</code> has not yet been called
++ */
++ V getValue();
++
++ //-----------------------------------------------------------------------
++ /**
++ * Removes the last returned key from the underlying <code>Map</code> (optional operation).
++ * <p/>
++ * This method can be called once per call to <code>next()</code>.
++ *
++ * @throws UnsupportedOperationException if remove is not supported by the map
++ * @throws IllegalStateException if <code>next()</code> has not yet been called
++ * @throws IllegalStateException if <code>remove()</code> has already been called
++ * since the last call to <code>next()</code>
++ */
++ void remove();
++
++ /**
++ * Sets the value associated with the current key (optional operation).
++ *
++ * @param value the new value
++ * @return the previous value
++ * @throws UnsupportedOperationException if setValue is not supported by the map
++ * @throws IllegalStateException if <code>next()</code> has not yet been called
++ * @throws IllegalStateException if <code>remove()</code> has been called since the
++ * last call to <code>next()</code>
++ */
++ V setValue(V value);
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/MapUtils.java
+@@ -0,0 +1,1354 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.map.*;
++
++import java.io.PrintStream;
++import java.text.NumberFormat;
++import java.text.ParseException;
++import java.util.*;
++
++/**
++ * Provides utility methods and decorators for
++ * {@link Map} and {@link SortedMap} instances.
++ * <p/>
++ * It contains various type safe methods
++ * as well as other useful features like deep copying.
++ * <p/>
++ * It also provides the following decorators:
++ * <p/>
++ * <ul>
++ * <li>{@link #fixedSizeMap(Map)}
++ * <li>{@link #fixedSizeSortedMap(SortedMap)}
++ * <li>{@link #lazyMap(Map,Factory)}
++ * <li>{@link #lazySortedMap(SortedMap,Factory)}
++ * <li>{@link #predicatedMap(Map,Predicate,Predicate)}
++ * <li>{@link #predicatedSortedMap(SortedMap,Predicate,Predicate)}
++ * <li>{@link #transformedMap(Map, Transformer, Transformer)}
++ * <li>{@link #transformedSortedMap(SortedMap, Transformer, Transformer)}
++ * <li>{@link #typedMap(Map, Class, Class)}
++ * <li>{@link #typedSortedMap(SortedMap, Class, Class)}
++ * </ul>
++ *
++ * @author <a href="mailto:jstrachan at apache.org">James Strachan</a>
++ * @author <a href="mailto:nissim at nksystems.com">Nissim Karpenstein</a>
++ * @author <a href="mailto:knielsen at apache.org">Kasper Nielsen</a>
++ * @author Paul Jack
++ * @author Stephen Colebourne
++ * @author Matthew Hawthorne
++ * @author Arun Mammen Thomas
++ * @author Janek Bogucki
++ * @author Max Rydahl Andersen
++ * @author Matt Hall, John Watkinson, <a href="mailto:equinus100 at hotmail.com">Ashwin S</a>
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 1.0
++ */
++public class MapUtils {
++
++ /**
++ * An empty unmodifiable map.
++ * This was not provided in JDK1.2.
++ */
++ public static final Map EMPTY_MAP = UnmodifiableMap.decorate(new HashMap(1));
++ /**
++ * An empty unmodifiable sorted map.
++ * This is not provided in the JDK.
++ */
++ public static final SortedMap EMPTY_SORTED_MAP = UnmodifiableSortedMap.decorate(new TreeMap());
++ /**
++ * String used to indent the verbose and debug Map prints.
++ */
++ private static final String INDENT_STRING = " ";
++
++ /**
++ * <code>MapUtils</code> should not normally be instantiated.
++ */
++ public MapUtils() {
++ }
++
++ // Type safe getters
++ //-------------------------------------------------------------------------
++ /**
++ * Gets from a Map in a null-safe manner.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map, <code>null</code> if null map input
++ */
++ public static <K,V> V getObject(final Map<K, V> map, final K key) {
++ if (map != null) {
++ return map.get(key);
++ }
++ return null;
++ }
++
++ /**
++ * Gets a String from a Map in a null-safe manner.
++ * <p/>
++ * The String is obtained via <code>toString</code>.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a String, <code>null</code> if null map input
++ */
++ public static <K,V> String getString(final Map<K, V> map, final K key) {
++ if (map != null) {
++ V answer = map.get(key);
++ if (answer != null) {
++ return answer.toString();
++ }
++ }
++ return null;
++ }
++
++ /**
++ * Gets a Boolean from a Map in a null-safe manner.
++ * <p/>
++ * If the value is a <code>Boolean</code> it is returned directly.
++ * If the value is a <code>String</code> and it equals 'true' ignoring case
++ * then <code>true</code> is returned, otherwise <code>false</code>.
++ * If the value is a <code>Number</code> an integer zero value returns
++ * <code>false</code> and non-zero returns <code>true</code>.
++ * Otherwise, <code>null</code> is returned.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a Boolean, <code>null</code> if null map input
++ */
++ public static Boolean getBoolean(final Map map, final Object key) {
++ if (map != null) {
++ Object answer = map.get(key);
++ if (answer != null) {
++ if (answer instanceof Boolean) {
++ return (Boolean) answer;
++
++ } else if (answer instanceof String) {
++ return new Boolean((String) answer);
++
++ } else if (answer instanceof Number) {
++ Number n = (Number) answer;
++ return (n.intValue() != 0) ? Boolean.TRUE : Boolean.FALSE;
++ }
++ }
++ }
++ return null;
++ }
++
++ /**
++ * Gets a Number from a Map in a null-safe manner.
++ * <p/>
++ * If the value is a <code>Number</code> it is returned directly.
++ * If the value is a <code>String</code> it is converted using
++ * {@link NumberFormat#parse(String)} on the system default formatter
++ * returning <code>null</code> if the conversion fails.
++ * Otherwise, <code>null</code> is returned.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a Number, <code>null</code> if null map input
++ */
++ public static Number getNumber(final Map map, final Object key) {
++ if (map != null) {
++ Object answer = map.get(key);
++ if (answer != null) {
++ if (answer instanceof Number) {
++ return (Number) answer;
++
++ } else if (answer instanceof String) {
++ try {
++ String text = (String) answer;
++ return NumberFormat.getInstance().parse(text);
++
++ } catch (ParseException e) {
++ logInfo(e);
++ }
++ }
++ }
++ }
++ return null;
++ }
++
++ /**
++ * Gets a Byte from a Map in a null-safe manner.
++ * <p/>
++ * The Byte is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a Byte, <code>null</code> if null map input
++ */
++ public static Byte getByte(final Map map, final Object key) {
++ Number answer = getNumber(map, key);
++ if (answer == null) {
++ return null;
++ } else if (answer instanceof Byte) {
++ return (Byte) answer;
++ }
++ return new Byte(answer.byteValue());
++ }
++
++ /**
++ * Gets a Short from a Map in a null-safe manner.
++ * <p/>
++ * The Short is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a Short, <code>null</code> if null map input
++ */
++ public static Short getShort(final Map map, final Object key) {
++ Number answer = getNumber(map, key);
++ if (answer == null) {
++ return null;
++ } else if (answer instanceof Short) {
++ return (Short) answer;
++ }
++ return new Short(answer.shortValue());
++ }
++
++ /**
++ * Gets a Integer from a Map in a null-safe manner.
++ * <p/>
++ * The Integer is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a Integer, <code>null</code> if null map input
++ */
++ public static Integer getInteger(final Map map, final Object key) {
++ Number answer = getNumber(map, key);
++ if (answer == null) {
++ return null;
++ } else if (answer instanceof Integer) {
++ return (Integer) answer;
++ }
++ return new Integer(answer.intValue());
++ }
++
++ /**
++ * Gets a Long from a Map in a null-safe manner.
++ * <p/>
++ * The Long is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a Long, <code>null</code> if null map input
++ */
++ public static Long getLong(final Map map, final Object key) {
++ Number answer = getNumber(map, key);
++ if (answer == null) {
++ return null;
++ } else if (answer instanceof Long) {
++ return (Long) answer;
++ }
++ return new Long(answer.longValue());
++ }
++
++ /**
++ * Gets a Float from a Map in a null-safe manner.
++ * <p/>
++ * The Float is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a Float, <code>null</code> if null map input
++ */
++ public static Float getFloat(final Map map, final Object key) {
++ Number answer = getNumber(map, key);
++ if (answer == null) {
++ return null;
++ } else if (answer instanceof Float) {
++ return (Float) answer;
++ }
++ return new Float(answer.floatValue());
++ }
++
++ /**
++ * Gets a Double from a Map in a null-safe manner.
++ * <p/>
++ * The Double is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a Double, <code>null</code> if null map input
++ */
++ public static Double getDouble(final Map map, final Object key) {
++ Number answer = getNumber(map, key);
++ if (answer == null) {
++ return null;
++ } else if (answer instanceof Double) {
++ return (Double) answer;
++ }
++ return new Double(answer.doubleValue());
++ }
++
++ /**
++ * Gets a Map from a Map in a null-safe manner.
++ * <p/>
++ * If the value returned from the specified map is not a Map then
++ * <code>null</code> is returned.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a Map, <code>null</code> if null map input
++ */
++ public static <K,A,B> Map<A, B> getMap(final Map<K, Map<A, B>> map, final K key) {
++ if (map != null) {
++ Map<A, B> answer = map.get(key);
++ if (answer != null) {
++ return answer;
++ }
++ }
++ return null;
++ }
++
++ // Type safe getters with default values
++ //-------------------------------------------------------------------------
++ /**
++ * Looks up the given key in the given map, converting null into the
++ * given default value.
++ *
++ * @param map the map whose value to look up
++ * @param key the key of the value to look up in that map
++ * @param defaultValue what to return if the value is null
++ * @return the value in the map, or defaultValue if the original value
++ * is null or the map is null
++ */
++ public static <K,V> V getObject(Map<K, V> map, K key, V defaultValue) {
++ if (map != null) {
++ V answer = map.get(key);
++ if (answer != null) {
++ return answer;
++ }
++ }
++ return defaultValue;
++ }
++
++ /**
++ * Looks up the given key in the given map, converting the result into
++ * a string, using the default value if the the conversion fails.
++ *
++ * @param map the map whose value to look up
++ * @param key the key of the value to look up in that map
++ * @param defaultValue what to return if the value is null or if the
++ * conversion fails
++ * @return the value in the map as a string, or defaultValue if the
++ * original value is null, the map is null or the string conversion
++ * fails
++ */
++ public static String getString(Map map, Object key, String defaultValue) {
++ String answer = getString(map, key);
++ if (answer == null) {
++ answer = defaultValue;
++ }
++ return answer;
++ }
++
++ /**
++ * Looks up the given key in the given map, converting the result into
++ * a boolean, using the default value if the the conversion fails.
++ *
++ * @param map the map whose value to look up
++ * @param key the key of the value to look up in that map
++ * @param defaultValue what to return if the value is null or if the
++ * conversion fails
++ * @return the value in the map as a boolean, or defaultValue if the
++ * original value is null, the map is null or the boolean conversion
++ * fails
++ */
++ public static Boolean getBoolean(Map map, Object key, Boolean defaultValue) {
++ Boolean answer = getBoolean(map, key);
++ if (answer == null) {
++ answer = defaultValue;
++ }
++ return answer;
++ }
++
++ /**
++ * Looks up the given key in the given map, converting the result into
++ * a number, using the default value if the the conversion fails.
++ *
++ * @param map the map whose value to look up
++ * @param key the key of the value to look up in that map
++ * @param defaultValue what to return if the value is null or if the
++ * conversion fails
++ * @return the value in the map as a number, or defaultValue if the
++ * original value is null, the map is null or the number conversion
++ * fails
++ */
++ public static Number getNumber(Map map, Object key, Number defaultValue) {
++ Number answer = getNumber(map, key);
++ if (answer == null) {
++ answer = defaultValue;
++ }
++ return answer;
++ }
++
++ /**
++ * Looks up the given key in the given map, converting the result into
++ * a byte, using the default value if the the conversion fails.
++ *
++ * @param map the map whose value to look up
++ * @param key the key of the value to look up in that map
++ * @param defaultValue what to return if the value is null or if the
++ * conversion fails
++ * @return the value in the map as a number, or defaultValue if the
++ * original value is null, the map is null or the number conversion
++ * fails
++ */
++ public static Byte getByte(Map map, Object key, Byte defaultValue) {
++ Byte answer = getByte(map, key);
++ if (answer == null) {
++ answer = defaultValue;
++ }
++ return answer;
++ }
++
++ /**
++ * Looks up the given key in the given map, converting the result into
++ * a short, using the default value if the the conversion fails.
++ *
++ * @param map the map whose value to look up
++ * @param key the key of the value to look up in that map
++ * @param defaultValue what to return if the value is null or if the
++ * conversion fails
++ * @return the value in the map as a number, or defaultValue if the
++ * original value is null, the map is null or the number conversion
++ * fails
++ */
++ public static Short getShort(Map map, Object key, Short defaultValue) {
++ Short answer = getShort(map, key);
++ if (answer == null) {
++ answer = defaultValue;
++ }
++ return answer;
++ }
++
++ /**
++ * Looks up the given key in the given map, converting the result into
++ * an integer, using the default value if the the conversion fails.
++ *
++ * @param map the map whose value to look up
++ * @param key the key of the value to look up in that map
++ * @param defaultValue what to return if the value is null or if the
++ * conversion fails
++ * @return the value in the map as a number, or defaultValue if the
++ * original value is null, the map is null or the number conversion
++ * fails
++ */
++ public static Integer getInteger(Map map, Object key, Integer defaultValue) {
++ Integer answer = getInteger(map, key);
++ if (answer == null) {
++ answer = defaultValue;
++ }
++ return answer;
++ }
++
++ /**
++ * Looks up the given key in the given map, converting the result into
++ * a long, using the default value if the the conversion fails.
++ *
++ * @param map the map whose value to look up
++ * @param key the key of the value to look up in that map
++ * @param defaultValue what to return if the value is null or if the
++ * conversion fails
++ * @return the value in the map as a number, or defaultValue if the
++ * original value is null, the map is null or the number conversion
++ * fails
++ */
++ public static Long getLong(Map map, Object key, Long defaultValue) {
++ Long answer = getLong(map, key);
++ if (answer == null) {
++ answer = defaultValue;
++ }
++ return answer;
++ }
++
++ /**
++ * Looks up the given key in the given map, converting the result into
++ * a float, using the default value if the the conversion fails.
++ *
++ * @param map the map whose value to look up
++ * @param key the key of the value to look up in that map
++ * @param defaultValue what to return if the value is null or if the
++ * conversion fails
++ * @return the value in the map as a number, or defaultValue if the
++ * original value is null, the map is null or the number conversion
++ * fails
++ */
++ public static Float getFloat(Map map, Object key, Float defaultValue) {
++ Float answer = getFloat(map, key);
++ if (answer == null) {
++ answer = defaultValue;
++ }
++ return answer;
++ }
++
++ /**
++ * Looks up the given key in the given map, converting the result into
++ * a double, using the default value if the the conversion fails.
++ *
++ * @param map the map whose value to look up
++ * @param key the key of the value to look up in that map
++ * @param defaultValue what to return if the value is null or if the
++ * conversion fails
++ * @return the value in the map as a number, or defaultValue if the
++ * original value is null, the map is null or the number conversion
++ * fails
++ */
++ public static Double getDouble(Map map, Object key, Double defaultValue) {
++ Double answer = getDouble(map, key);
++ if (answer == null) {
++ answer = defaultValue;
++ }
++ return answer;
++ }
++
++ /**
++ * Looks up the given key in the given map, converting the result into
++ * a map, using the default value if the the conversion fails.
++ *
++ * @param map the map whose value to look up
++ * @param key the key of the value to look up in that map
++ * @param defaultValue what to return if the value is null or if the
++ * conversion fails
++ * @return the value in the map as a number, or defaultValue if the
++ * original value is null, the map is null or the map conversion
++ * fails
++ */
++ public static <K,A,B> Map<A, B> getMap(Map<K, Map<A, B>> map, K key, Map<A, B> defaultValue) {
++ Map<A, B> answer = getMap(map, key);
++ if (answer == null) {
++ answer = defaultValue;
++ }
++ return answer;
++ }
++
++
++ // Type safe primitive getters
++ //-------------------------------------------------------------------------
++ /**
++ * Gets a boolean from a Map in a null-safe manner.
++ * <p/>
++ * If the value is a <code>Boolean</code> its value is returned.
++ * If the value is a <code>String</code> and it equals 'true' ignoring case
++ * then <code>true</code> is returned, otherwise <code>false</code>.
++ * If the value is a <code>Number</code> an integer zero value returns
++ * <code>false</code> and non-zero returns <code>true</code>.
++ * Otherwise, <code>false</code> is returned.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a Boolean, <code>false</code> if null map input
++ */
++ public static boolean getBooleanValue(final Map map, final Object key) {
++ Boolean booleanObject = getBoolean(map, key);
++ if (booleanObject == null) {
++ return false;
++ }
++ return booleanObject.booleanValue();
++ }
++
++ /**
++ * Gets a byte from a Map in a null-safe manner.
++ * <p/>
++ * The byte is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a byte, <code>0</code> if null map input
++ */
++ public static byte getByteValue(final Map map, final Object key) {
++ Byte byteObject = getByte(map, key);
++ if (byteObject == null) {
++ return 0;
++ }
++ return byteObject.byteValue();
++ }
++
++ /**
++ * Gets a short from a Map in a null-safe manner.
++ * <p/>
++ * The short is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a short, <code>0</code> if null map input
++ */
++ public static short getShortValue(final Map map, final Object key) {
++ Short shortObject = getShort(map, key);
++ if (shortObject == null) {
++ return 0;
++ }
++ return shortObject.shortValue();
++ }
++
++ /**
++ * Gets an int from a Map in a null-safe manner.
++ * <p/>
++ * The int is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as an int, <code>0</code> if null map input
++ */
++ public static int getIntValue(final Map map, final Object key) {
++ Integer integerObject = getInteger(map, key);
++ if (integerObject == null) {
++ return 0;
++ }
++ return integerObject.intValue();
++ }
++
++ /**
++ * Gets a long from a Map in a null-safe manner.
++ * <p/>
++ * The long is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a long, <code>0L</code> if null map input
++ */
++ public static long getLongValue(final Map map, final Object key) {
++ Long longObject = getLong(map, key);
++ if (longObject == null) {
++ return 0L;
++ }
++ return longObject.longValue();
++ }
++
++ /**
++ * Gets a float from a Map in a null-safe manner.
++ * <p/>
++ * The float is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a float, <code>0.0F</code> if null map input
++ */
++ public static float getFloatValue(final Map map, final Object key) {
++ Float floatObject = getFloat(map, key);
++ if (floatObject == null) {
++ return 0f;
++ }
++ return floatObject.floatValue();
++ }
++
++ /**
++ * Gets a double from a Map in a null-safe manner.
++ * <p/>
++ * The double is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @return the value in the Map as a double, <code>0.0</code> if null map input
++ */
++ public static double getDoubleValue(final Map map, final Object key) {
++ Double doubleObject = getDouble(map, key);
++ if (doubleObject == null) {
++ return 0d;
++ }
++ return doubleObject.doubleValue();
++ }
++
++ // Type safe primitive getters with default values
++ //-------------------------------------------------------------------------
++ /**
++ * Gets a boolean from a Map in a null-safe manner,
++ * using the default value if the the conversion fails.
++ * <p/>
++ * If the value is a <code>Boolean</code> its value is returned.
++ * If the value is a <code>String</code> and it equals 'true' ignoring case
++ * then <code>true</code> is returned, otherwise <code>false</code>.
++ * If the value is a <code>Number</code> an integer zero value returns
++ * <code>false</code> and non-zero returns <code>true</code>.
++ * Otherwise, <code>defaultValue</code> is returned.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @param defaultValue return if the value is null or if the
++ * conversion fails
++ * @return the value in the Map as a Boolean, <code>defaultValue</code> if null map input
++ */
++ public static boolean getBooleanValue(final Map map, final Object key, boolean defaultValue) {
++ Boolean booleanObject = getBoolean(map, key);
++ if (booleanObject == null) {
++ return defaultValue;
++ }
++ return booleanObject.booleanValue();
++ }
++
++ /**
++ * Gets a byte from a Map in a null-safe manner,
++ * using the default value if the the conversion fails.
++ * <p/>
++ * The byte is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @param defaultValue return if the value is null or if the
++ * conversion fails
++ * @return the value in the Map as a byte, <code>defaultValue</code> if null map input
++ */
++ public static byte getByteValue(final Map map, final Object key, byte defaultValue) {
++ Byte byteObject = getByte(map, key);
++ if (byteObject == null) {
++ return defaultValue;
++ }
++ return byteObject.byteValue();
++ }
++
++ /**
++ * Gets a short from a Map in a null-safe manner,
++ * using the default value if the the conversion fails.
++ * <p/>
++ * The short is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @param defaultValue return if the value is null or if the
++ * conversion fails
++ * @return the value in the Map as a short, <code>defaultValue</code> if null map input
++ */
++ public static short getShortValue(final Map map, final Object key, short defaultValue) {
++ Short shortObject = getShort(map, key);
++ if (shortObject == null) {
++ return defaultValue;
++ }
++ return shortObject.shortValue();
++ }
++
++ /**
++ * Gets an int from a Map in a null-safe manner,
++ * using the default value if the the conversion fails.
++ * <p/>
++ * The int is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @param defaultValue return if the value is null or if the
++ * conversion fails
++ * @return the value in the Map as an int, <code>defaultValue</code> if null map input
++ */
++ public static int getIntValue(final Map map, final Object key, int defaultValue) {
++ Integer integerObject = getInteger(map, key);
++ if (integerObject == null) {
++ return defaultValue;
++ }
++ return integerObject.intValue();
++ }
++
++ /**
++ * Gets a long from a Map in a null-safe manner,
++ * using the default value if the the conversion fails.
++ * <p/>
++ * The long is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @param defaultValue return if the value is null or if the
++ * conversion fails
++ * @return the value in the Map as a long, <code>defaultValue</code> if null map input
++ */
++ public static long getLongValue(final Map map, final Object key, long defaultValue) {
++ Long longObject = getLong(map, key);
++ if (longObject == null) {
++ return defaultValue;
++ }
++ return longObject.longValue();
++ }
++
++ /**
++ * Gets a float from a Map in a null-safe manner,
++ * using the default value if the the conversion fails.
++ * <p/>
++ * The float is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @param defaultValue return if the value is null or if the
++ * conversion fails
++ * @return the value in the Map as a float, <code>defaultValue</code> if null map input
++ */
++ public static float getFloatValue(final Map map, final Object key, float defaultValue) {
++ Float floatObject = getFloat(map, key);
++ if (floatObject == null) {
++ return defaultValue;
++ }
++ return floatObject.floatValue();
++ }
++
++ /**
++ * Gets a double from a Map in a null-safe manner,
++ * using the default value if the the conversion fails.
++ * <p/>
++ * The double is obtained from the results of {@link #getNumber(Map,Object)}.
++ *
++ * @param map the map to use
++ * @param key the key to look up
++ * @param defaultValue return if the value is null or if the
++ * conversion fails
++ * @return the value in the Map as a double, <code>defaultValue</code> if null map input
++ */
++ public static double getDoubleValue(final Map map, final Object key, double defaultValue) {
++ Double doubleObject = getDouble(map, key);
++ if (doubleObject == null) {
++ return defaultValue;
++ }
++ return doubleObject.doubleValue();
++ }
++
++ // Conversion methods
++ //-------------------------------------------------------------------------
++ /**
++ * Gets a new Properties object initialised with the values from a Map.
++ * A null input will return an empty properties object.
++ *
++ * @param map the map to convert to a Properties object, may not be null
++ * @return the properties object
++ */
++ public static Properties toProperties(final Map map) {
++ Properties answer = new Properties();
++ if (map != null) {
++ for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
++ Map.Entry entry = (Map.Entry) iter.next();
++ Object key = entry.getKey();
++ Object value = entry.getValue();
++ answer.put(key, value);
++ }
++ }
++ return answer;
++ }
++
++ /**
++ * Creates a new HashMap using data copied from a ResourceBundle.
++ *
++ * @param resourceBundle the resource bundle to convert, may not be null
++ * @return the hashmap containing the data
++ * @throws NullPointerException if the bundle is null
++ */
++ public static Map<String, Object> toMap(final ResourceBundle resourceBundle) {
++ Enumeration<String> enumeration = resourceBundle.getKeys();
++ Map<String, Object> map = new HashMap<String, Object>();
++
++ while (enumeration.hasMoreElements()) {
++ String key = enumeration.nextElement();
++ Object value = resourceBundle.getObject(key);
++ map.put(key, value);
++ }
++
++ return map;
++ }
++
++ // Printing methods
++ //-------------------------------------------------------------------------
++ /**
++ * Prints the given map with nice line breaks.
++ * <p/>
++ * This method prints a nicely formatted String describing the Map.
++ * Each map entry will be printed with key and value.
++ * When the value is a Map, recursive behaviour occurs.
++ * <p/>
++ * This method is NOT thread-safe in any special way. You must manually
++ * synchronize on either this class or the stream as required.
++ *
++ * @param out the stream to print to, must not be null
++ * @param label The label to be used, may be <code>null</code>.
++ * If <code>null</code>, the label is not output.
++ * It typically represents the name of the property in a bean or similar.
++ * @param map The map to print, may be <code>null</code>.
++ * If <code>null</code>, the text 'null' is output.
++ * @throws NullPointerException if the stream is <code>null</code>
++ */
++ public static void verbosePrint(final PrintStream out, final Object label, final Map map) {
++
++ verbosePrintInternal(out, label, map, new ArrayStack(), false);
++ }
++
++ /**
++ * Prints the given map with nice line breaks.
++ * <p/>
++ * This method prints a nicely formatted String describing the Map.
++ * Each map entry will be printed with key, value and value classname.
++ * When the value is a Map, recursive behaviour occurs.
++ * <p/>
++ * This method is NOT thread-safe in any special way. You must manually
++ * synchronize on either this class or the stream as required.
++ *
++ * @param out the stream to print to, must not be null
++ * @param label The label to be used, may be <code>null</code>.
++ * If <code>null</code>, the label is not output.
++ * It typically represents the name of the property in a bean or similar.
++ * @param map The map to print, may be <code>null</code>.
++ * If <code>null</code>, the text 'null' is output.
++ * @throws NullPointerException if the stream is <code>null</code>
++ */
++ public static void debugPrint(final PrintStream out, final Object label, final Map map) {
++
++ verbosePrintInternal(out, label, map, new ArrayStack(), true);
++ }
++
++ // Implementation methods
++ //-------------------------------------------------------------------------
++ /**
++ * Logs the given exception to <code>System.out</code>.
++ * <p/>
++ * This method exists as Jakarta Collections does not depend on logging.
++ *
++ * @param ex the exception to log
++ */
++ protected static void logInfo(final Exception ex) {
++ System.out.println("INFO: Exception: " + ex);
++ }
++
++ /**
++ * Implementation providing functionality for {@link #debugPrint} and for
++ * {@link #verbosePrint}. This prints the given map with nice line breaks.
++ * If the debug flag is true, it additionally prints the type of the object
++ * value. If the contents of a map include the map itself, then the text
++ * <em>(this Map)</em> is printed out. If the contents include a
++ * parent container of the map, the the text <em>(ancestor[i] Map)</em> is
++ * printed, where i actually indicates the number of levels which must be
++ * traversed in the sequential list of ancestors (e.g. father, grandfather,
++ * great-grandfather, etc).
++ *
++ * @param out the stream to print to
++ * @param label the label to be used, may be <code>null</code>.
++ * If <code>null</code>, the label is not output.
++ * It typically represents the name of the property in a bean or similar.
++ * @param map the map to print, may be <code>null</code>.
++ * If <code>null</code>, the text 'null' is output
++ * @param lineage a stack consisting of any maps in which the previous
++ * argument is contained. This is checked to avoid infinite recursion when
++ * printing the output
++ * @param debug flag indicating whether type names should be output.
++ * @throws NullPointerException if the stream is <code>null</code>
++ */
++ private static void verbosePrintInternal(final PrintStream out, final Object label, final Map map, final ArrayStack lineage, final boolean debug) {
++
++ printIndent(out, lineage.size());
++
++ if (map == null) {
++ if (label != null) {
++ out.print(label);
++ out.print(" = ");
++ }
++ out.println("null");
++ return;
++ }
++ if (label != null) {
++ out.print(label);
++ out.println(" = ");
++ }
++
++ printIndent(out, lineage.size());
++ out.println("{");
++
++ lineage.push(map);
++
++ for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
++ Map.Entry entry = (Map.Entry) it.next();
++ Object childKey = entry.getKey();
++ Object childValue = entry.getValue();
++ if (childValue instanceof Map && !lineage.contains(childValue)) {
++ verbosePrintInternal(out, (childKey == null ? "null" : childKey), (Map) childValue, lineage, debug);
++ } else {
++ printIndent(out, lineage.size());
++ out.print(childKey);
++ out.print(" = ");
++
++ final int lineageIndex = lineage.indexOf(childValue);
++ if (lineageIndex == -1) {
++ out.print(childValue);
++ } else if (lineage.size() - 1 == lineageIndex) {
++ out.print("(this Map)");
++ } else {
++ out.print("(ancestor[" + (lineage.size() - 1 - lineageIndex - 1) + "] Map)");
++ }
++
++ if (debug && childValue != null) {
++ out.print(' ');
++ out.println(childValue.getClass().getName());
++ } else {
++ out.println();
++ }
++ }
++ }
++
++ lineage.pop();
++
++ printIndent(out, lineage.size());
++ out.println(debug ? "} " + map.getClass().getName() : "}");
++ }
++
++ /**
++ * Writes indentation to the given stream.
++ *
++ * @param out the stream to indent
++ */
++ private static void printIndent(final PrintStream out, final int indent) {
++ for (int i = 0; i < indent; i++) {
++ out.print(INDENT_STRING);
++ }
++ }
++
++ // Misc
++ //-----------------------------------------------------------------------
++ /**
++ * Inverts the supplied map returning a new HashMap such that the keys of
++ * the input are swapped with the values.
++ * <p/>
++ * This operation assumes that the inverse mapping is well defined.
++ * If the input map had multiple entries with the same value mapped to
++ * different keys, the returned map will map one of those keys to the
++ * value, but the exact key which will be mapped is undefined.
++ *
++ * @param map the map to invert, may not be null
++ * @return a new HashMap containing the inverted data
++ * @throws NullPointerException if the map is null
++ */
++ public static <K,V> Map<V, K> invertMap(Map<K, V> map) {
++ Map<V, K> out = new HashMap<V, K>(map.size());
++ for (Iterator<Map.Entry<K, V>> it = map.entrySet().iterator(); it.hasNext();) {
++ Map.Entry<K, V> entry = it.next();
++ out.put(entry.getValue(), entry.getKey());
++ }
++ return out;
++ }
++
++ /**
++ * Nice method for adding data to a map in such a way
++ * as to not get NPE's. The point being that if the
++ * value is null, map.put() will throw an exception.
++ * That blows in the case of this class cause you may want to
++ * essentially treat put("Not Null", null ) == put("Not Null", "")
++ * We will still throw a NPE if the key is null cause that should
++ * never happen.
++ * <p>
++ * Note: this is not a type-safe operation in Java 1.5.
++ *
++ * @param map the map to add to, may not be null
++ * @param key the key
++ * @param value the value
++ * @throws NullPointerException if the map is null
++ *
++ */
++ public static void safeAddToMap(Map map, Object key, Object value) throws NullPointerException {
++ if (value == null) {
++ map.put(key, "");
++ } else {
++ map.put(key, value);
++ }
++ }
++
++ // Map decorators
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a synchronized map backed by the given map.
++ * <p/>
++ * You must manually synchronize on the returned buffer's iterator to
++ * avoid non-deterministic behavior:
++ * <p/>
++ * <pre>
++ * Map m = MapUtils.synchronizedMap(myMap);
++ * Set s = m.keySet(); // outside synchronized block
++ * synchronized (m) { // synchronized on MAP!
++ * Iterator i = s.iterator();
++ * while (i.hasNext()) {
++ * process (i.next());
++ * }
++ * }
++ * </pre>
++ * <p/>
++ * This method uses the implementation in {@link java.util.Collections Collections}.
++ *
++ * @param map the map to synchronize, must not be null
++ * @return a synchronized map backed by the given map
++ * @throws IllegalArgumentException if the map is null
++ */
++ public static <K,V> Map<K, V> synchronizedMap(Map<K, V> map) {
++ return Collections.synchronizedMap(map);
++ }
++
++ /**
++ * Returns an unmodifiable map backed by the given map.
++ * <p/>
++ * This method uses the implementation in the decorators subpackage.
++ *
++ * @param map the map to make unmodifiable, must not be null
++ * @return an unmodifiable map backed by the given map
++ * @throws IllegalArgumentException if the map is null
++ */
++ public static <K,V> Map<K, V> unmodifiableMap(Map<K, V> map) {
++ return UnmodifiableMap.decorate(map);
++ }
++
++ /**
++ * Returns a predicated (validating) map backed by the given map.
++ * <p/>
++ * Only objects that pass the tests in the given predicates can be added to the map.
++ * Trying to add an invalid object results in an IllegalArgumentException.
++ * Keys must pass the key predicate, values must pass the value predicate.
++ * It is important not to use the original map after invoking this method,
++ * as it is a backdoor for adding invalid objects.
++ *
++ * @param map the map to predicate, must not be null
++ * @param keyPred the predicate for keys, null means no check
++ * @param valuePred the predicate for values, null means no check
++ * @return a predicated map backed by the given map
++ * @throws IllegalArgumentException if the Map is null
++ */
++ public static <K,V> Map<K, V> predicatedMap(Map<K, V> map, Predicate<? super K> keyPred, Predicate<? super V> valuePred) {
++ return PredicatedMap.decorate(map, keyPred, valuePred);
++ }
++
++ /**
++ * Returns a typed map backed by the given map.
++ * <p/>
++ * Only keys and values of the specified types can be added to the map.
++ *
++ * @param map the map to limit to a specific type, must not be null
++ * @param keyType the type of keys which may be added to the map, must not be null
++ * @param valueType the type of values which may be added to the map, must not be null
++ * @return a typed map backed by the specified map
++ * @throws IllegalArgumentException if the Map or Class is null
++ * @deprecated this is no longer needed with Java generics.
++ */
++ public static Map typedMap(Map map, Class keyType, Class valueType) {
++ return TypedMap.decorate(map, keyType, valueType);
++ }
++
++ /**
++ * Returns a transformed map backed by the given map.
++ * <p/>
++ * Each object is passed through the transformers as it is added to the
++ * Map. It is important not to use the original map after invoking this
++ * method, as it is a backdoor for adding untransformed objects.
++ *
++ * @param map the map to transform, must not be null
++ * @param keyTransformer the transformer for the map keys, null means no transformation
++ * @param valueTransformer the transformer for the map values, null means no transformation
++ * @return a transformed map backed by the given map
++ * @throws IllegalArgumentException if the Map is null
++ */
++ public static Map transformedMap(Map map, Transformer keyTransformer, Transformer valueTransformer) {
++ return TransformedMap.decorate(map, keyTransformer, valueTransformer);
++ }
++
++ /**
++ * Returns a fixed-sized map backed by the given map.
++ * Elements may not be added or removed from the returned map, but
++ * existing elements can be changed (for instance, via the
++ * {@link Map#put(Object,Object)} method).
++ *
++ * @param map the map whose size to fix, must not be null
++ * @return a fixed-size map backed by that map
++ * @throws IllegalArgumentException if the Map is null
++ */
++ public static <K,V> Map<K, V> fixedSizeMap(Map<K, V> map) {
++ return FixedSizeMap.decorate(map);
++ }
++
++ /**
++ * Returns a "lazy" map whose values will be created on demand.
++ * <p/>
++ * When the key passed to the returned map's {@link Map#get(Object)}
++ * method is not present in the map, then the factory will be used
++ * to create a new object and that object will become the value
++ * associated with that key.
++ * <p/>
++ * For instance:
++ * <pre>
++ * Factory factory = new Factory() {
++ * public Object create() {
++ * return new Date();
++ * }
++ * }
++ * Map lazyMap = MapUtils.lazyMap(new HashMap(), factory);
++ * Object obj = lazyMap.get("test");
++ * </pre>
++ * <p/>
++ * After the above code is executed, <code>obj</code> will contain
++ * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
++ * instance is the value for the <code>"test"</code> key in the map.
++ *
++ * @param map the map to make lazy, must not be null
++ * @param factory the factory for creating new objects, must not be null
++ * @return a lazy map backed by the given map
++ * @throws IllegalArgumentException if the Map or Factory is null
++ */
++ public static <K,V> Map<K, V> lazyMap(Map<K, V> map, Factory<V> factory) {
++ return LazyMap.decorate(map, factory);
++ }
++
++ /**
++ * Returns a map that maintains the order of keys that are added
++ * backed by the given map.
++ * <p/>
++ * If a key is added twice, the order is determined by the first add.
++ * The order is observed through the keySet, values and entrySet.
++ *
++ * @param map the map to order, must not be null
++ * @return an ordered map backed by the given map
++ * @throws IllegalArgumentException if the Map is null
++ */
++ public static <K,V> Map<K, V> orderedMap(Map<K, V> map) {
++ return ListOrderedMap.decorate(map);
++ }
++
++ // SortedMap decorators
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a synchronized sorted map backed by the given sorted map.
++ * <p/>
++ * You must manually synchronize on the returned buffer's iterator to
++ * avoid non-deterministic behavior:
++ * <p/>
++ * <pre>
++ * Map m = MapUtils.synchronizedSortedMap(myMap);
++ * Set s = m.keySet(); // outside synchronized block
++ * synchronized (m) { // synchronized on MAP!
++ * Iterator i = s.iterator();
++ * while (i.hasNext()) {
++ * process (i.next());
++ * }
++ * }
++ * </pre>
++ * <p/>
++ * This method uses the implementation in {@link java.util.Collections Collections}.
++ *
++ * @param map the map to synchronize, must not be null
++ * @return a synchronized map backed by the given map
++ * @throws IllegalArgumentException if the map is null
++ */
++ public static <K,V> Map<K, V> synchronizedSortedMap(SortedMap<K, V> map) {
++ return Collections.synchronizedSortedMap(map);
++ }
++
++ /**
++ * Returns an unmodifiable sorted map backed by the given sorted map.
++ * <p/>
++ * This method uses the implementation in the decorators subpackage.
++ *
++ * @param map the sorted map to make unmodifiable, must not be null
++ * @return an unmodifiable map backed by the given map
++ * @throws IllegalArgumentException if the map is null
++ */
++ public static <K,V> Map<K, V> unmodifiableSortedMap(SortedMap<K, V> map) {
++ return UnmodifiableSortedMap.decorate(map);
++ }
++
++ /**
++ * Returns a predicated (validating) sorted map backed by the given map.
++ * <p/>
++ * Only objects that pass the tests in the given predicates can be added to the map.
++ * Trying to add an invalid object results in an IllegalArgumentException.
++ * Keys must pass the key predicate, values must pass the value predicate.
++ * It is important not to use the original map after invoking this method,
++ * as it is a backdoor for adding invalid objects.
++ *
++ * @param map the map to predicate, must not be null
++ * @param keyPred the predicate for keys, null means no check
++ * @param valuePred the predicate for values, null means no check
++ * @return a predicated map backed by the given map
++ * @throws IllegalArgumentException if the SortedMap is null
++ */
++ public static <K,V> SortedMap<K, V> predicatedSortedMap(SortedMap<K, V> map, Predicate<? super K> keyPred, Predicate<? super V> valuePred) {
++ return PredicatedSortedMap.decorate(map, keyPred, valuePred);
++ }
++
++ /**
++ * Returns a typed sorted map backed by the given map.
++ * <p/>
++ * Only keys and values of the specified types can be added to the map.
++ *
++ * @param map the map to limit to a specific type, must not be null
++ * @param keyType the type of keys which may be added to the map, must not be null
++ * @param valueType the type of values which may be added to the map, must not be null
++ * @return a typed map backed by the specified map
++ * @deprecated no longer needed with Java generics.
++ */
++ public static SortedMap typedSortedMap(SortedMap map, Class keyType, Class valueType) {
++ return TypedSortedMap.decorate(map, keyType, valueType);
++ }
++
++ /**
++ * Returns a transformed sorted map backed by the given map.
++ * <p/>
++ * Each object is passed through the transformers as it is added to the
++ * Map. It is important not to use the original map after invoking this
++ * method, as it is a backdoor for adding untransformed objects.
++ *
++ * @param map the map to transform, must not be null
++ * @param keyTransformer the transformer for the map keys, null means no transformation
++ * @param valueTransformer the transformer for the map values, null means no transformation
++ * @return a transformed map backed by the given map
++ * @throws IllegalArgumentException if the SortedMap is null
++ */
++ public static SortedMap transformedSortedMap(SortedMap map, Transformer keyTransformer, Transformer valueTransformer) {
++ return TransformedSortedMap.decorate(map, keyTransformer, valueTransformer);
++ }
++
++ /**
++ * Returns a fixed-sized sorted map backed by the given sorted map.
++ * Elements may not be added or removed from the returned map, but
++ * existing elements can be changed (for instance, via the
++ * {@link Map#put(Object,Object)} method).
++ *
++ * @param map the map whose size to fix, must not be null
++ * @return a fixed-size map backed by that map
++ * @throws IllegalArgumentException if the SortedMap is null
++ */
++ public static <K,V> SortedMap<K, V> fixedSizeSortedMap(SortedMap<K, V> map) {
++ return FixedSizeSortedMap.decorate(map);
++ }
++
++ /**
++ * Returns a "lazy" sorted map whose values will be created on demand.
++ * <p/>
++ * When the key passed to the returned map's {@link Map#get(Object)}
++ * method is not present in the map, then the factory will be used
++ * to create a new object and that object will become the value
++ * associated with that key.
++ * <p/>
++ * For instance:
++ * <p/>
++ * <pre>
++ * Factory factory = new Factory() {
++ * public Object create() {
++ * return new Date();
++ * }
++ * }
++ * SortedMap lazy = MapUtils.lazySortedMap(new TreeMap(), factory);
++ * Object obj = lazy.get("test");
++ * </pre>
++ * <p/>
++ * After the above code is executed, <code>obj</code> will contain
++ * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
++ * instance is the value for the <code>"test"</code> key.
++ *
++ * @param map the map to make lazy, must not be null
++ * @param factory the factory for creating new objects, must not be null
++ * @return a lazy map backed by the given map
++ * @throws IllegalArgumentException if the SortedMap or Factory is null
++ */
++ public static <K,V> SortedMap<K, V> lazySortedMap(SortedMap<K, V> map, Factory<V> factory) {
++ return LazySortedMap.decorate(map, factory);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/MultiMap.java
+@@ -0,0 +1,337 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.*;
++
++/**
++ * Defines a map that holds a collection of values against each key.
++ * <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/>
++ * For example:
++ * <pre>
++ * Number key = new Integer(5);
++ * MultiMap<Number,String> mhm = new MultiHashMap<Number,String>();
++ * mhm.put(key, "A");
++ * mhm.put(key, "B");
++ * mhm.put(key, "C");
++ * Collection<String> coll = mhm.get(key);</pre>
++ * <p/>
++ * <code>coll</code> will be a collection containing "A", "B", "C".
++ * <p/>
++ * NOTE: Note: this new, generics-friendly version of the MultiMap interface does
++ * NOT extend java.util.Map! This is because MultiMap breaks the Map contract in
++ * too many ways to allow generics support. However, you can get a live java.util.Map
++ * for a MultiMap with the method {@link #map()}.
++ *
++ * @author Christopher Berry
++ * @author James Strachan
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 2.0
++ */
++public interface MultiMap <K,V> {
++
++ /**
++ * 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, implementations typically
++ * return <code>null</code> from a subsequant <code>get(Object)</code>, however
++ * they may choose to return an empty collection.
++ *
++ * @param key the key to remove from
++ * @param item the item to remove
++ * @return the value removed (which was passed in), null if nothing removed
++ * @throws UnsupportedOperationException if the map is unmodifiable
++ * @throws ClassCastException if the key or value is of an invalid type
++ * @throws NullPointerException if the key or value is null and null is invalid
++ */
++ public V remove(Object key, Object item);
++
++ /**
++ * Gets the number of values in this map for the given key.
++ * <p/>
++ * Implementations return the count of keys in the map, or 0 if there are no values for the given key.
++ *
++ * @return the number of values in this map for the given key.
++ */
++ int size(Object key);
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the number of keys in this map.
++ * <p/>
++ * Implementations return the count of keys in the map.
++ *
++ * @return the number of key-collection mappings in this map
++ */
++ int size();
++
++ /**
++ * Gets the collection of values associated with the specified key.
++ * <p/>
++ * The returned value will implement <code>Collection</code>. Implementations
++ * are free to declare that they return <code>Collection</code> subclasses
++ * such as <code>List</code> or <code>Set</code>.
++ * <p/>
++ * Implementations return <code>null</code> if no values have
++ * been mapped to the key.
++ * <p/>
++ * Implementations may choose to return a clone of the internal collection.
++ *
++ * @param key the key to retrieve
++ * @return the <code>Collection</code> of values, implementations should
++ * return <code>null</code> for no mapping, but may return an empty collection
++ * @throws ClassCastException if the key is of an invalid type
++ * @throws NullPointerException if the key is null and null keys are invalid
++ */
++ Collection<V> get(Object key);
++
++ /**
++ * Checks whether the map contains the value specified.
++ * <p/>
++ * Implementations check all collections15 against all keys for the value.
++ *
++ * @param value the value to search for
++ * @return true if the map contains the value
++ * @throws ClassCastException if the value is of an invalid type
++ * @throws NullPointerException if the value is null and null value are invalid
++ */
++ boolean containsValue(Object value);
++
++ /**
++ * Checks whether the map contains the value specified, at the key specified.
++ *
++ * @param value the value to search for
++ * @param key the key against which to search for the value
++ * @return true if the map contains the value
++ * @throws ClassCastException if the value is of an invalid type
++ * @throws NullPointerException if the value is null and null value are invalid
++ */
++ boolean containsValue(Object key, Object value);
++
++ /**
++ * 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.
++ * The collection may be a <code>List</code>, <code>Set</code> or other
++ * collection dependent on implementation.
++ *
++ * @param key the key to store against
++ * @param value the value to add to the collection at the key
++ * @return typically the value added if the map changed and null if the map did not change
++ * @throws UnsupportedOperationException if the map is unmodifiable
++ * @throws ClassCastException if the key or value is of an invalid type
++ * @throws NullPointerException if the key or value is null and null is invalid
++ * @throws IllegalArgumentException if the key or value is invalid
++ */
++ V put(K key, V value);
++
++ /**
++ * Removes all values associated with the specified key.
++ * <p/>
++ * Implementations typically return <code>null</code> from a subsequent
++ * <code>get(Object)</code>, however they may choose to return an empty collection.
++ *
++ * @param key the key to remove values from
++ * @return the <code>Collection</code> of values removed, implementations should
++ * return <code>null</code> for no mapping found, but may return an empty collection
++ * @throws UnsupportedOperationException if the map is unmodifiable
++ * @throws ClassCastException if the key is of an invalid type
++ * @throws NullPointerException if the key is null and null keys are invalid
++ */
++ Collection<V> remove(Object key);
++
++ /**
++ * Gets a collection containing all the values in the map.
++ * <p/>
++ * Inplementations return a collection containing the combination
++ * of values from all keys.
++ *
++ * @return a collection view of the values contained in this map
++ */
++ Collection<V> values();
++
++ /**
++ * Returns <tt>true</tt> if this map contains no key-value mappings.
++ *
++ * @return <tt>true</tt> if this map contains no key-value mappings.
++ */
++ boolean isEmpty();
++
++ /**
++ * Returns <tt>true</tt> if this map contains a mapping for the specified
++ * key. More formally, returns <tt>true</tt> if and only if
++ * this map contains a mapping for a key <tt>k</tt> such that
++ * <tt>(key==null ? k==null : key.equals(k))</tt>. (There can be
++ * at most one such mapping.)
++ *
++ * @param key key whose presence in this map is to be tested.
++ * @return <tt>true</tt> if this map contains a mapping for the specified
++ * key.
++ * @throws ClassCastException if the key is of an inappropriate type for
++ * this map (optional).
++ * @throws NullPointerException if the key is <tt>null</tt> and this map
++ * does not permit <tt>null</tt> keys (optional).
++ */
++ boolean containsKey(Object key);
++
++ // Modification Operations
++
++ // Bulk Operations
++
++ /**
++ * Copies all of the mappings from the specified map to this map
++ * (optional operation). The effect of this call is equivalent to that
++ * of calling {@link #put(Object,Object) put(k, v)} on this map once
++ * for each mapping from key <tt>k</tt> to value <tt>v</tt> in the
++ * specified map. The behavior of this operation is unspecified if the
++ * specified map is modified while the operation is in progress.
++ *
++ * @param t Mappings to be stored in this map.
++ * @throws UnsupportedOperationException if the <tt>putAll</tt> method is
++ * not supported by this map.
++ * @throws ClassCastException if the class of a key or value in the
++ * specified map prevents it from being stored in this map.
++ * @throws IllegalArgumentException some aspect of a key or value in the
++ * specified map prevents it from being stored in this map.
++ * @throws NullPointerException if the specified map is <tt>null</tt>, or if
++ * this map does not permit <tt>null</tt> keys or values, and the
++ * specified map contains <tt>null</tt> keys or values.
++ */
++ void putAll(Map<? extends K, ? extends V> t);
++
++ /**
++ * Copies all of the mappings from the specified multimap to this multimap
++ * (optional operation). The effect of this call is equivalent to that
++ * of calling {@link #put(Object,Object) put(k, v)} on this map once
++ * for each mapping from key to collections15 of values in the
++ * specified multimap. The behavior of this operation is unspecified if the
++ * specified multimap is modified while the operation is in progress.
++ *
++ * @param t Mappings to be stored in this map.
++ * @throws UnsupportedOperationException if the <tt>putAll</tt> method is
++ * not supported by this map.
++ * @throws ClassCastException if the class of a key or value in the
++ * specified map prevents it from being stored in this map.
++ * @throws IllegalArgumentException some aspect of a key or value in the
++ * specified map prevents it from being stored in this map.
++ * @throws NullPointerException if the specified map is <tt>null</tt>, or if
++ * this map does not permit <tt>null</tt> keys or values, and the
++ * specified map contains <tt>null</tt> keys or values.
++ */
++ void putAll(MultiMap<? extends K, ? extends V> t);
++
++ /**
++ * Copies all of the values in the given collection in to the multimap against the given key.
++ * @param key the key against which to store the values.
++ * @param values the collection of values to map to the key.
++ */
++ boolean putAll(K key, Collection<? extends V> values);
++
++ Iterator<V> iterator(Object key);
++
++ /**
++ * Removes all mappings from this map (optional operation).
++ *
++ * @throws UnsupportedOperationException clear is not supported by this
++ * map.
++ */
++ void clear();
++
++
++ // Views
++
++ /**
++ * Returns a set view of the keys contained in this map. The set is
++ * backed by the map, so changes to the map are reflected in the set, and
++ * vice-versa. If the map is modified while an iteration over the set is
++ * in progress (except through the iterator's own <tt>remove</tt>
++ * operation), the results of the iteration are undefined. The set
++ * supports element removal, which removes the corresponding mapping from
++ * the map, via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
++ * <tt>removeAll</tt> <tt>retainAll</tt>, and <tt>clear</tt> operations.
++ * It does not support the add or <tt>addAll</tt> operations.
++ *
++ * @return a set view of the keys contained in this map.
++ */
++ Set<K> keySet();
++
++ /**
++ * Returns a set view of the mappings contained in this map. Each element
++ * in the returned set is a {@link Map.Entry}. The set is backed by the
++ * map, so changes to the map are reflected in the set, and vice-versa.
++ * If the map is modified while an iteration over the set is in progress
++ * (except through the iterator's own <tt>remove</tt> operation, or through
++ * the <tt>setValue</tt> operation on a map entry returned by the iterator)
++ * the results of the iteration are undefined. The set supports element
++ * removal, which removes the corresponding mapping from the map, via the
++ * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>,
++ * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not support
++ * the <tt>add</tt> or <tt>addAll</tt> operations.
++ *
++ * @return a set view of the mappings contained in this map.
++ */
++ Set<Map.Entry<K, Collection<V>>> entrySet();
++
++ /**
++ * Returns a java.util.Map<K,Collection<V>> for this MultiMap.
++ *
++ * @return the underlying java.util.Map for this MultiMap.
++ */
++ Map<K,Collection<V>> map();
++
++ // Comparison and hashing
++
++ /**
++ * Compares the specified object with this map for equality. Returns
++ * <tt>true</tt> if the given object is also a map and the two Maps
++ * represent the same mappings. More formally, two maps <tt>t1</tt> and
++ * <tt>t2</tt> represent the same mappings if
++ * <tt>t1.entrySet().equals(t2.entrySet())</tt>. This ensures that the
++ * <tt>equals</tt> method works properly across different implementations
++ * of the <tt>Map</tt> interface.
++ *
++ * @param o object to be compared for equality with this map.
++ * @return <tt>true</tt> if the specified object is equal to this map.
++ */
++ boolean equals(Object o);
++
++ /**
++ * Returns the hash code value for this map. The hash code of a map
++ * is defined to be the sum of the hashCodes of each entry in the map's
++ * entrySet view. This ensures that <tt>t1.equals(t2)</tt> implies
++ * that <tt>t1.hashCode()==t2.hashCode()</tt> for any two maps
++ * <tt>t1</tt> and <tt>t2</tt>, as required by the general
++ * contract of Object.hashCode.
++ *
++ * @return the hash code value for this map.
++ * @see Map.Entry#hashCode()
++ * @see Object#hashCode()
++ * @see Object#equals(Object)
++ * @see #equals(Object)
++ */
++ int hashCode();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/OrderedBidiMap.java
+@@ -0,0 +1,63 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++/**
++ * Defines a map that allows bidirectional lookup between key and values
++ * and retains and provides access to an ordering.
++ * <p/>
++ * Implementations should allow a value to be looked up from a key and
++ * a key to be looked up from a value with equal performance.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface OrderedBidiMap <K,V> extends BidiMap<K, V>, OrderedMap<K, V> {
++
++ /**
++ * Gets a view of this map where the keys and values are reversed.
++ * <p/>
++ * Changes to one map will be visible in the other and vice versa.
++ * This enables both directions of the map to be accessed equally.
++ * <p/>
++ * Implementations should seek to avoid creating a new object every time this
++ * method is called. See <code>AbstractMap.values()</code> etc. Calling this
++ * method on the inverse map should return the original.
++ * <p/>
++ * Implementations must return an <code>OrderedBidiMap</code> instance,
++ * usually by forwarding to <code>inverseOrderedBidiMap()</code>.
++ *
++ * @return an inverted bidirectional map
++ */
++ public BidiMap<V, K> inverseBidiMap();
++
++ /**
++ * Gets a view of this map where the keys and values are reversed.
++ * <p/>
++ * Changes to one map will be visible in the other and vice versa.
++ * This enables both directions of the map to be accessed equally.
++ * <p/>
++ * Implementations should seek to avoid creating a new object every time this
++ * method is called. See <code>AbstractMap.values()</code> etc. Calling this
++ * method on the inverse map should return the original.
++ *
++ * @return an inverted bidirectional map
++ */
++ public OrderedBidiMap<V, K> inverseOrderedBidiMap();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/OrderedIterator.java
+@@ -0,0 +1,48 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.Iterator;
++
++/**
++ * Defines an iterator that operates over a ordered collections15.
++ * <p/>
++ * This iterator allows both forward and reverse iteration through the collection.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface OrderedIterator <E> extends Iterator<E> {
++
++ /**
++ * Checks to see if there is a previous entry that can be iterated to.
++ *
++ * @return <code>true</code> if the iterator has a previous element
++ */
++ boolean hasPrevious();
++
++ /**
++ * Gets the previous element from the collection.
++ *
++ * @return the previous key in the iteration
++ * @throws java.util.NoSuchElementException
++ * if the iteration is finished
++ */
++ E previous();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/OrderedMap.java
+@@ -0,0 +1,83 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++/**
++ * Defines a map that maintains order and allows both forward and backward
++ * iteration through that order.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface OrderedMap <K,V> extends IterableMap<K, V> {
++
++ /**
++ * Obtains an <code>OrderedMapIterator</code> over the map.
++ * <p/>
++ * A ordered map iterator is an efficient way of iterating over maps
++ * in both directions.
++ * <pre>
++ * BidiMap map = new TreeBidiMap();
++ * MapIterator it = map.mapIterator();
++ * while (it.hasNext()) {
++ * Object key = it.next();
++ * Object value = it.getValue();
++ * it.setValue("newValue");
++ * Object previousKey = it.previous();
++ * }
++ * </pre>
++ *
++ * @return a map iterator
++ */
++ OrderedMapIterator<K, V> orderedMapIterator();
++
++ /**
++ * Gets the first key currently in this map.
++ *
++ * @return the first key currently in this map
++ * @throws java.util.NoSuchElementException
++ * if this map is empty
++ */
++ public K firstKey();
++
++ /**
++ * Gets the last key currently in this map.
++ *
++ * @return the last key currently in this map
++ * @throws java.util.NoSuchElementException
++ * if this map is empty
++ */
++ public K lastKey();
++
++ /**
++ * Gets the next key after the one specified.
++ *
++ * @param key the key to search for next from
++ * @return the next key, null if no match or at end
++ */
++ public K nextKey(K key);
++
++ /**
++ * Gets the previous key before the one specified.
++ *
++ * @param key the key to search for previous from
++ * @return the previous key, null if no match or at start
++ */
++ public K previousKey(K key);
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/OrderedMapIterator.java
+@@ -0,0 +1,46 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++/**
++ * Defines an iterator that operates over an ordered <code>Map</code>.
++ * <p/>
++ * This iterator allows both forward and reverse iteration through the map.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface OrderedMapIterator <K,V> extends MapIterator<K, V>, OrderedIterator<K> {
++
++ /**
++ * Checks to see if there is a previous entry that can be iterated to.
++ *
++ * @return <code>true</code> if the iterator has a previous element
++ */
++ boolean hasPrevious();
++
++ /**
++ * Gets the previous <em>key</em> from the <code>Map</code>.
++ *
++ * @return the previous key in the iteration
++ * @throws java.util.NoSuchElementException
++ * if the iteration is finished
++ */
++ K previous();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/Predicate.java
+@@ -0,0 +1,49 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++/**
++ * Defines a functor interface implemented by classes that perform a predicate
++ * test on an object.
++ * <p/>
++ * A <code>Predicate</code> is the object equivalent of an <code>if</code> statement.
++ * It uses the input object to return a true or false value, and is often used in
++ * validation or filtering.
++ * <p/>
++ * Standard implementations of common predicates are provided by
++ * {@link PredicateUtils}. These include true, false, instanceof, equals, and,
++ * or, not, method invokation and null testing.
++ *
++ * @author James Strachan
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 1.0
++ */
++public interface Predicate <T> {
++
++ /**
++ * Use the specified parameter to perform a test that returns true or false.
++ *
++ * @param object the object to evaluate, should not be changed
++ * @return true or false
++ * @throws ClassCastException (runtime) if the input is the wrong class
++ * @throws IllegalArgumentException (runtime) if the input is invalid
++ * @throws FunctorException (runtime) if the predicate encounters a problem
++ */
++ public boolean evaluate(T object);
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/PredicateUtils.java
+@@ -0,0 +1,488 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.functors.*;
++
++import java.util.Collection;
++
++/**
++ * <code>PredicateUtils</code> provides reference implementations and utilities
++ * for the Predicate functor interface. The supplied predicates are:
++ * <ul>
++ * <li>Invoker - returns the result of a method call on the input object
++ * <li>InstanceOf - true if the object is an instanceof a class
++ * <li>Equal - true if the object equals() a specified object
++ * <li>Identity - true if the object == a specified object
++ * <li>Null - true if the object is null
++ * <li>NotNull - true if the object is not null
++ * <li>Unique - true if the object has not already been evaluated
++ * <li>And/All - true if all of the predicates are true
++ * <li>Or/Any - true if any of the predicates is true
++ * <li>Either/One - true if only one of the predicate is true
++ * <li>Neither/None - true if none of the predicates are true
++ * <li>Not - true if the predicate is false, and vice versa
++ * <li>Transformer - wraps a Transformer as a Predicate
++ * <li>True - always return true
++ * <li>False - always return false
++ * <li>Exception - always throws an exception
++ * <li>NullIsException/NullIsFalse/NullIsTrue - check for null input
++ * <li>Transformed - transforms the input before calling the predicate
++ * </ul>
++ * All the supplied predicates are Serializable.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Ola Berg
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public class PredicateUtils {
++
++ /**
++ * This class is not normally instantiated.
++ */
++ public PredicateUtils() {
++ super();
++ }
++
++ // Simple predicates
++ //-----------------------------------------------------------------------------
++
++ /**
++ * Gets a Predicate that always throws an exception.
++ * This could be useful during testing as a placeholder.
++ *
++ * @return the predicate
++ * @see org.apache.commons.collections15.functors.ExceptionPredicate
++ */
++ public static Predicate exceptionPredicate() {
++ return ExceptionPredicate.INSTANCE;
++ }
++
++ /**
++ * Gets a Predicate that always returns true.
++ *
++ * @return the predicate
++ * @see org.apache.commons.collections15.functors.TruePredicate
++ */
++ public static <T> Predicate<T> truePredicate() {
++ return TruePredicate.getInstance();
++ }
++
++ /**
++ * Gets a Predicate that always returns false.
++ *
++ * @return the predicate
++ * @see org.apache.commons.collections15.functors.FalsePredicate
++ */
++ public static <T> Predicate<T> falsePredicate() {
++ return FalsePredicate.getInstance();
++ }
++
++ /**
++ * Gets a Predicate that checks if the input object passed in is null.
++ *
++ * @return the predicate
++ * @see org.apache.commons.collections15.functors.NullPredicate
++ */
++ public static <T> Predicate<T> nullPredicate() {
++ return NullPredicate.getInstance();
++ }
++
++ /**
++ * Gets a Predicate that checks if the input object passed in is not null.
++ *
++ * @return the predicate
++ * @see org.apache.commons.collections15.functors.NotNullPredicate
++ */
++ public static <T> Predicate<T> notNullPredicate() {
++ return NotNullPredicate.getInstance();
++ }
++
++ /**
++ * Creates a Predicate that checks if the input object is equal to the
++ * specified object using equals().
++ *
++ * @param value the value to compare against
++ * @return the predicate
++ * @see org.apache.commons.collections15.functors.EqualPredicate
++ */
++ public static <T> Predicate<T> equalPredicate(T value) {
++ return EqualPredicate.getInstance(value);
++ }
++
++ /**
++ * Creates a Predicate that checks if the input object is equal to the
++ * specified object by identity.
++ *
++ * @param value the value to compare against
++ * @return the predicate
++ * @see org.apache.commons.collections15.functors.IdentityPredicate
++ */
++ public static <T> Predicate<T> identityPredicate(T value) {
++ return IdentityPredicate.getInstance(value);
++ }
++
++ /**
++ * Creates a Predicate that checks if the object passed in is of
++ * a particular type, using instanceof. A <code>null</code> input
++ * object will return <code>false</code>.
++ *
++ * @param type the type to check for, may not be null
++ * @return the predicate
++ * @throws IllegalArgumentException if the class is null
++ * @see org.apache.commons.collections15.functors.InstanceofPredicate
++ */
++ @SuppressWarnings("unchecked")
++ public static Predicate instanceofPredicate(Class type) {
++ return InstanceofPredicate.getInstance(type);
++ }
++
++ /**
++ * Creates a Predicate that returns true the first time an object is
++ * encountered, and false if the same object is received
++ * again. The comparison is by equals(). A <code>null</code> input object
++ * is accepted and will return true the first time, and false subsequently
++ * as well.
++ *
++ * @return the predicate
++ * @see org.apache.commons.collections15.functors.UniquePredicate
++ */
++ public static <T> Predicate<T> uniquePredicate() {
++ // must return new instance each time
++ return UniquePredicate.getInstance();
++ }
++
++ /**
++ * Creates a Predicate that invokes a method on the input object.
++ * The method must return either a boolean or a non-null Boolean,
++ * and have no parameters. If the input object is null, a
++ * PredicateException is thrown.
++ * <p/>
++ * For example, <code>PredicateUtils.invokerPredicate("isEmpty");</code>
++ * will call the <code>isEmpty</code> method on the input object to
++ * determine the predicate result.
++ *
++ * @param methodName the method name to call on the input object, may not be null
++ * @return the predicate
++ * @throws IllegalArgumentException if the methodName is null.
++ * @see org.apache.commons.collections15.functors.InvokerTransformer
++ * @see org.apache.commons.collections15.functors.TransformerPredicate
++ */
++ public static Predicate invokerPredicate(String methodName) {
++ // reuse transformer as it has caching - this is lazy really, should have inner class here
++ return asPredicate(InvokerTransformer.getInstance(methodName));
++ }
++
++ /**
++ * Creates a Predicate that invokes a method on the input object.
++ * The method must return either a boolean or a non-null Boolean,
++ * and have no parameters. If the input object is null, a
++ * PredicateException is thrown.
++ * <p/>
++ * For example, <code>PredicateUtils.invokerPredicate("isEmpty");</code>
++ * will call the <code>isEmpty</code> method on the input object to
++ * determine the predicate result.
++ *
++ * @param methodName the method name to call on the input object, may not be null
++ * @param paramTypes the parameter types
++ * @param args the arguments
++ * @return the predicate
++ * @throws IllegalArgumentException if the method name is null
++ * @throws IllegalArgumentException if the paramTypes and args don't match
++ * @see org.apache.commons.collections15.functors.InvokerTransformer
++ * @see org.apache.commons.collections15.functors.TransformerPredicate
++ */
++ public static Predicate invokerPredicate(String methodName, Class[] paramTypes, Object[] args) {
++ // reuse transformer as it has caching - this is lazy really, should have inner class here
++ return asPredicate(InvokerTransformer.getInstance(methodName, paramTypes, args));
++ }
++
++ // Boolean combinations
++ //-----------------------------------------------------------------------------
++
++ /**
++ * Create a new Predicate that returns true only if both of the specified
++ * predicates are true.
++ *
++ * @param predicate1 the first predicate, may not be null
++ * @param predicate2 the second predicate, may not be null
++ * @return the <code>and</code> predicate
++ * @throws IllegalArgumentException if either predicate is null
++ * @see org.apache.commons.collections15.functors.AndPredicate
++ */
++ public static <T> Predicate<T> andPredicate(Predicate<? super T> predicate1, Predicate<? super T> predicate2) {
++ return AndPredicate.<T>getInstance(predicate1, predicate2);
++ }
++
++ /**
++ * Create a new Predicate that returns true only if all of the specified
++ * predicates are true.
++ *
++ * @param predicates an array of predicates to check, may not be null
++ * @return the <code>all</code> predicate
++ * @throws IllegalArgumentException if the predicates array is null
++ * @throws IllegalArgumentException if the predicates array has less than 2 elements
++ * @throws IllegalArgumentException if any predicate in the array is null
++ * @see org.apache.commons.collections15.functors.AllPredicate
++ */
++ public static <T> Predicate<T> allPredicate(Predicate<? super T> ... predicates) {
++ return AllPredicate.getInstance(predicates);
++ }
++
++ /**
++ * Create a new Predicate that returns true only if all of the specified
++ * predicates are true. The predicates are checked in iterator order.
++ *
++ * @param predicates a collection of predicates to check, may not be null
++ * @return the <code>all</code> predicate
++ * @throws IllegalArgumentException if the predicates collection is null
++ * @throws IllegalArgumentException if the predicates collection has less than 2 elements
++ * @throws IllegalArgumentException if any predicate in the collection is null
++ * @see org.apache.commons.collections15.functors.AllPredicate
++ */
++ public static <T> Predicate<T> allPredicate(Collection<Predicate<? super T>> predicates) {
++ return AllPredicate.getInstance(predicates);
++ }
++
++ /**
++ * Create a new Predicate that returns true if either of the specified
++ * predicates are true.
++ *
++ * @param predicate1 the first predicate, may not be null
++ * @param predicate2 the second predicate, may not be null
++ * @return the <code>or</code> predicate
++ * @throws IllegalArgumentException if either predicate is null
++ * @see org.apache.commons.collections15.functors.OrPredicate
++ */
++ public static <T> Predicate<T> orPredicate(Predicate<? super T> predicate1, Predicate<? super T> predicate2) {
++ return OrPredicate.<T>getInstance(predicate1, predicate2);
++ }
++
++ /**
++ * Create a new Predicate that returns true if any of the specified
++ * predicates are true.
++ *
++ * @param predicates an array of predicates to check, may not be null
++ * @return the <code>any</code> predicate
++ * @throws IllegalArgumentException if the predicates array is null
++ * @throws IllegalArgumentException if the predicates array has less than 2 elements
++ * @throws IllegalArgumentException if any predicate in the array is null
++ * @see org.apache.commons.collections15.functors.AnyPredicate
++ */
++ public static <T> Predicate<T> anyPredicate(Predicate<? super T> ... predicates) {
++ return AnyPredicate.getInstance(predicates);
++ }
++
++ /**
++ * Create a new Predicate that returns true if any of the specified
++ * predicates are true. The predicates are checked in iterator order.
++ *
++ * @param predicates a collection of predicates to check, may not be null
++ * @return the <code>any</code> predicate
++ * @throws IllegalArgumentException if the predicates collection is null
++ * @throws IllegalArgumentException if the predicates collection has less than 2 elements
++ * @throws IllegalArgumentException if any predicate in the collection is null
++ * @see org.apache.commons.collections15.functors.AnyPredicate
++ */
++ public static <T> Predicate<T> anyPredicate(Collection<Predicate<? super T>> predicates) {
++ return AnyPredicate.getInstance(predicates);
++ }
++
++ /**
++ * Create a new Predicate that returns true if one, but not both, of the
++ * specified predicates are true.
++ *
++ * @param predicate1 the first predicate, may not be null
++ * @param predicate2 the second predicate, may not be null
++ * @return the <code>either</code> predicate
++ * @throws IllegalArgumentException if either predicate is null
++ * @see org.apache.commons.collections15.functors.OnePredicate
++ */
++ @SuppressWarnings("unchecked")
++ public static <T> Predicate<T> eitherPredicate(Predicate<? super T> predicate1, Predicate<? super T> predicate2) {
++ return onePredicate(new Predicate[]{predicate1, predicate2});
++ }
++
++ /**
++ * Create a new Predicate that returns true if only one of the specified
++ * predicates are true.
++ *
++ * @param predicates an array of predicates to check, may not be null
++ * @return the <code>one</code> predicate
++ * @throws IllegalArgumentException if the predicates array is null
++ * @throws IllegalArgumentException if the predicates array has less than 2 elements
++ * @throws IllegalArgumentException if any predicate in the array is null
++ * @see org.apache.commons.collections15.functors.OnePredicate
++ */
++ public static <T> Predicate<T> onePredicate(Predicate<? super T> ... predicates) {
++ return OnePredicate.getInstance(predicates);
++ }
++
++ /**
++ * Create a new Predicate that returns true if only one of the specified
++ * predicates are true. The predicates are checked in iterator order.
++ *
++ * @param predicates a collection of predicates to check, may not be null
++ * @return the <code>one</code> predicate
++ * @throws IllegalArgumentException if the predicates collection is null
++ * @throws IllegalArgumentException if the predicates collection has less than 2 elements
++ * @throws IllegalArgumentException if any predicate in the collection is null
++ * @see org.apache.commons.collections15.functors.OnePredicate
++ */
++ public static <T> Predicate<T> onePredicate(Collection<Predicate<? super T>> predicates) {
++ return OnePredicate.getInstance(predicates);
++ }
++
++ /**
++ * Create a new Predicate that returns true if neither of the specified
++ * predicates are true.
++ *
++ * @param predicate1 the first predicate, may not be null
++ * @param predicate2 the second predicate, may not be null
++ * @return the <code>neither</code> predicate
++ * @throws IllegalArgumentException if either predicate is null
++ * @see org.apache.commons.collections15.functors.NonePredicate
++ */
++ @SuppressWarnings("unchecked")
++ public static <T> Predicate<T> neitherPredicate(Predicate<? super T> predicate1, Predicate<? super T> predicate2) {
++ return nonePredicate(new Predicate[]{predicate1, predicate2});
++ }
++
++ /**
++ * Create a new Predicate that returns true if none of the specified
++ * predicates are true.
++ *
++ * @param predicates an array of predicates to check, may not be null
++ * @return the <code>none</code> predicate
++ * @throws IllegalArgumentException if the predicates array is null
++ * @throws IllegalArgumentException if the predicates array has less than 2 elements
++ * @throws IllegalArgumentException if any predicate in the array is null
++ * @see org.apache.commons.collections15.functors.NonePredicate
++ */
++ public static <T> Predicate<T> nonePredicate(Predicate<? super T> ... predicates) {
++ return NonePredicate.getInstance(predicates);
++ }
++
++ /**
++ * Create a new Predicate that returns true if none of the specified
++ * predicates are true. The predicates are checked in iterator order.
++ *
++ * @param predicates a collection of predicates to check, may not be null
++ * @return the <code>none</code> predicate
++ * @throws IllegalArgumentException if the predicates collection is null
++ * @throws IllegalArgumentException if the predicates collection has less than 2 elements
++ * @throws IllegalArgumentException if any predicate in the collection is null
++ * @see org.apache.commons.collections15.functors.NonePredicate
++ */
++ public static <T> Predicate<T> nonePredicate(Collection<Predicate<? super T>> predicates) {
++ return NonePredicate.getInstance(predicates);
++ }
++
++ /**
++ * Create a new Predicate that returns true if the specified predicate
++ * returns false and vice versa.
++ *
++ * @param predicate the predicate to not
++ * @return the <code>not</code> predicate
++ * @throws IllegalArgumentException if the predicate is null
++ * @see org.apache.commons.collections15.functors.NotPredicate
++ */
++ public static <T> Predicate<T> notPredicate(Predicate<T> predicate) {
++ return NotPredicate.getInstance(predicate);
++ }
++
++ // Adaptors
++ //-----------------------------------------------------------------------------
++
++ /**
++ * Create a new Predicate that wraps a Transformer. The Transformer must
++ * return either Boolean.TRUE or Boolean.FALSE otherwise a PredicateException
++ * will be thrown.
++ *
++ * @param transformer the transformer to wrap, may not be null
++ * @return the transformer wrapping predicate
++ * @throws IllegalArgumentException if the transformer is null
++ * @see org.apache.commons.collections15.functors.TransformerPredicate
++ */
++ public static <T> Predicate<T> asPredicate(Transformer<T, Boolean> transformer) {
++ return TransformerPredicate.getInstance(transformer);
++ }
++
++ // Null handlers
++ //-----------------------------------------------------------------------------
++
++ /**
++ * Gets a Predicate that throws an exception if the input object is null,
++ * otherwise it calls the specified Predicate. This allows null handling
++ * behaviour to be added to Predicates that don't support nulls.
++ *
++ * @param predicate the predicate to wrap, may not be null
++ * @return the predicate
++ * @throws IllegalArgumentException if the predicate is null.
++ * @see org.apache.commons.collections15.functors.NullIsExceptionPredicate
++ */
++ public static <T> Predicate<T> nullIsExceptionPredicate(Predicate<T> predicate) {
++ return NullIsExceptionPredicate.getInstance(predicate);
++ }
++
++ /**
++ * Gets a Predicate that returns false if the input object is null, otherwise
++ * it calls the specified Predicate. This allows null handling behaviour to
++ * be added to Predicates that don't support nulls.
++ *
++ * @param predicate the predicate to wrap, may not be null
++ * @return the predicate
++ * @throws IllegalArgumentException if the predicate is null.
++ * @see org.apache.commons.collections15.functors.NullIsFalsePredicate
++ */
++ public static <T> Predicate<T> nullIsFalsePredicate(Predicate<T> predicate) {
++ return NullIsFalsePredicate.getInstance(predicate);
++ }
++
++ /**
++ * Gets a Predicate that returns true if the input object is null, otherwise
++ * it calls the specified Predicate. This allows null handling behaviour to
++ * be added to Predicates that don't support nulls.
++ *
++ * @param predicate the predicate to wrap, may not be null
++ * @return the predicate
++ * @throws IllegalArgumentException if the predicate is null.
++ * @see org.apache.commons.collections15.functors.NullIsTruePredicate
++ */
++ public static <T> Predicate<T> nullIsTruePredicate(Predicate<T> predicate) {
++ return NullIsTruePredicate.getInstance(predicate);
++ }
++
++ // Transformed
++ //-----------------------------------------------------------------------
++ /**
++ * Creates a predicate that transforms the input object before passing it
++ * to the predicate.
++ *
++ * @param transformer the transformer to call first
++ * @param predicate the predicate to call with the result of the transform
++ * @return the predicate
++ * @throws IllegalArgumentException if the transformer or the predicate is null
++ * @see org.apache.commons.collections15.functors.TransformedPredicate
++ * @since Commons Collections 3.1
++ */
++ public static <I,O> Predicate<I> transformedPredicate(Transformer<I, ? extends O> transformer, Predicate<? super O> predicate) {
++ return TransformedPredicate.getInstance(transformer, predicate);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/ResettableIterator.java
+@@ -0,0 +1,38 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.Iterator;
++
++/**
++ * Defines an iterator that can be reset back to an initial state.
++ * <p/>
++ * This interface allows an iterator to be repeatedly reused.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface ResettableIterator <E> extends Iterator<E> {
++
++ /**
++ * Resets the iterator back to the position at which the iterator
++ * was created.
++ */
++ public void reset();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/ResettableListIterator.java
+@@ -0,0 +1,38 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.ListIterator;
++
++/**
++ * Defines a list iterator that can be reset back to an initial state.
++ * <p/>
++ * This interface allows an iterator to be repeatedly reused.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface ResettableListIterator <E> extends ListIterator<E>, ResettableIterator<E> {
++
++ /**
++ * Resets the iterator back to the position at which the iterator
++ * was created.
++ */
++ public void reset();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/SetUtils.java
+@@ -0,0 +1,312 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.set.*;
++
++import java.util.*;
++
++/**
++ * Provides utility methods and decorators for
++ * {@link Set} and {@link SortedSet} instances.
++ *
++ * @author Paul Jack
++ * @author Stephen Colebourne
++ * @author Neil O'Toole
++ * @author Matt Hall, John Watkinson, Matthew Hawthorne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 2.1
++ */
++public class SetUtils {
++
++ /**
++ * An empty unmodifiable set.
++ * This uses the {@link Collections} implementation
++ * and is provided for completeness.
++ */
++ public static final Set EMPTY_SET = Collections.EMPTY_SET;
++ /**
++ * An empty unmodifiable sorted set.
++ * This is not provided in the JDK.
++ */
++ public static final SortedSet EMPTY_SORTED_SET = UnmodifiableSortedSet.decorate(new TreeSet());
++
++ /**
++ * <code>SetUtils</code> should not normally be instantiated.
++ */
++ public SetUtils() {
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Tests two sets for equality as per the <code>equals()</code> contract
++ * in {@link java.util.Set#equals(java.lang.Object)}.
++ * <p/>
++ * This method is useful for implementing <code>Set</code> when you cannot
++ * extend AbstractSet. The method takes Collection instances to enable other
++ * collection types to use the Set implementation algorithm.
++ * <p/>
++ * The relevant text (slightly paraphrased as this is a static method) is:
++ * <blockquote>
++ * <p>Two sets are considered equal if they have
++ * the same size, and every member of the first set is contained in
++ * the second. This ensures that the <tt>equals</tt> method works
++ * properly across different implementations of the <tt>Set</tt>
++ * interface.</p>
++ * <p/>
++ * <p/>
++ * This implementation first checks if the two sets are the same object:
++ * if so it returns <tt>true</tt>. Then, it checks if the two sets are
++ * identical in size; if not, it returns false. If so, it returns
++ * <tt>a.containsAll((Collection) b)</tt>.</p>
++ * </blockquote>
++ *
++ * @param set1 the first set, may be null
++ * @param set2 the second set, may be null
++ * @return whether the sets are equal by value comparison
++ * @see java.util.Set
++ */
++ public static boolean isEqualSet(final Collection set1, final Collection set2) {
++ if (set1 == set2) {
++ return true;
++ }
++ if (set1 == null || set2 == null || set1.size() != set2.size()) {
++ return false;
++ }
++
++ return set1.containsAll(set2);
++ }
++
++ /**
++ * Generates a hash code using the algorithm specified in
++ * {@link java.util.Set#hashCode()}.
++ * <p/>
++ * This method is useful for implementing <code>Set</code> when you cannot
++ * extend AbstractSet. The method takes Collection instances to enable other
++ * collection types to use the Set implementation algorithm.
++ *
++ * @param set the set to calculate the hash code for, may be null
++ * @return the hash code
++ * @see java.util.Set#hashCode()
++ */
++ public static int hashCodeForSet(final Collection set) {
++ if (set == null) {
++ return 0;
++ }
++ int hashCode = 0;
++ Iterator it = set.iterator();
++ Object obj = null;
++
++ while (it.hasNext()) {
++ obj = it.next();
++ if (obj != null) {
++ hashCode += obj.hashCode();
++ }
++ }
++ return hashCode;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a synchronized set backed by the given set.
++ * <p/>
++ * You must manually synchronize on the returned buffer's iterator to
++ * avoid non-deterministic behavior:
++ * <p/>
++ * <pre>
++ * Set s = SetUtils.synchronizedSet(mySet);
++ * synchronized (s) {
++ * Iterator i = s.iterator();
++ * while (i.hasNext()) {
++ * process (i.next());
++ * }
++ * }
++ * </pre>
++ * <p/>
++ * This method uses the implementation in the decorators subpackage.
++ *
++ * @param set the set to synchronize, must not be null
++ * @return a synchronized set backed by the given set
++ * @throws IllegalArgumentException if the set is null
++ */
++ public static <E> Set<E> synchronizedSet(Set<E> set) {
++ return SynchronizedSet.decorate(set);
++ }
++
++ /**
++ * Returns an unmodifiable set backed by the given set.
++ * <p/>
++ * This method uses the implementation in the decorators subpackage.
++ *
++ * @param set the set to make unmodifiable, must not be null
++ * @return an unmodifiable set backed by the given set
++ * @throws IllegalArgumentException if the set is null
++ */
++ public static <E> Set<E> unmodifiableSet(Set<E> set) {
++ return UnmodifiableSet.decorate(set);
++ }
++
++ /**
++ * Returns a predicated (validating) set backed by the given set.
++ * <p/>
++ * Only objects that pass the test in the given predicate can be added to the set.
++ * Trying to add an invalid object results in an IllegalArgumentException.
++ * It is important not to use the original set after invoking this method,
++ * as it is a backdoor for adding invalid objects.
++ *
++ * @param set the set to predicate, must not be null
++ * @param predicate the predicate for the set, must not be null
++ * @return a predicated set backed by the given set
++ * @throws IllegalArgumentException if the Set or Predicate is null
++ */
++ public static <E> Set<E> predicatedSet(Set<E> set, Predicate<? super E> predicate) {
++ return PredicatedSet.decorate(set, predicate);
++ }
++
++ /**
++ * Returns a typed set backed by the given set.
++ * <p/>
++ * Only objects of the specified type can be added to the set.
++ *
++ * @param set the set to limit to a specific type, must not be null
++ * @param type the type of objects which may be added to the set
++ * @return a typed set backed by the specified set
++ * @deprecated Made obsolete by Java 1.5 generics.
++ */
++ public static <E> Set<E> typedSet(Set<E> set, Class<E> type) {
++ return TypedSet.decorate(set, type);
++ }
++
++ /**
++ * Returns a transformed set backed by the given set.
++ * <p/>
++ * Each object is passed through the transformer as it is added to the
++ * Set. It is important not to use the original set after invoking this
++ * method, as it is a backdoor for adding untransformed objects.
++ *
++ * @param set the set to transform, must not be null
++ * @param transformer the transformer for the set, must not be null
++ * @return a transformed set backed by the given set
++ * @throws IllegalArgumentException if the Set or Transformer is null
++ */
++ public static <I,O> Set<O> transformedSet(Set<I> set, Transformer<? super I, ? extends O> transformer) {
++ return TransformedSet.decorate(set, transformer);
++ }
++
++ /**
++ * Returns a set that maintains the order of elements that are added
++ * backed by the given set.
++ * <p/>
++ * If an element is added twice, the order is determined by the first add.
++ * The order is observed through the iterator or toArray.
++ *
++ * @param set the set to order, must not be null
++ * @return an ordered set backed by the given set
++ * @throws IllegalArgumentException if the Set is null
++ */
++ public static <E> Set<E> orderedSet(Set<E> set) {
++ return ListOrderedSet.decorate(set);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a synchronized sorted set backed by the given sorted set.
++ * <p/>
++ * You must manually synchronize on the returned buffer's iterator to
++ * avoid non-deterministic behavior:
++ * <p/>
++ * <pre>
++ * Set s = SetUtils.synchronizedSet(mySet);
++ * synchronized (s) {
++ * Iterator i = s.iterator();
++ * while (i.hasNext()) {
++ * process (i.next());
++ * }
++ * }
++ * </pre>
++ * <p/>
++ * This method uses the implementation in the decorators subpackage.
++ *
++ * @param set the sorted set to synchronize, must not be null
++ * @return a synchronized set backed by the given set
++ * @throws IllegalArgumentException if the set is null
++ */
++ public static <E> SortedSet<E> synchronizedSortedSet(SortedSet<E> set) {
++ return SynchronizedSortedSet.decorate(set);
++ }
++
++ /**
++ * Returns an unmodifiable sorted set backed by the given sorted set.
++ * <p/>
++ * This method uses the implementation in the decorators subpackage.
++ *
++ * @param set the sorted set to make unmodifiable, must not be null
++ * @return an unmodifiable set backed by the given set
++ * @throws IllegalArgumentException if the set is null
++ */
++ public static <E> SortedSet<E> unmodifiableSortedSet(SortedSet<E> set) {
++ return UnmodifiableSortedSet.decorate(set);
++ }
++
++ /**
++ * Returns a predicated (validating) sorted set backed by the given sorted set.
++ * <p/>
++ * Only objects that pass the test in the given predicate can be added to the set.
++ * Trying to add an invalid object results in an IllegalArgumentException.
++ * It is important not to use the original set after invoking this method,
++ * as it is a backdoor for adding invalid objects.
++ *
++ * @param set the sorted set to predicate, must not be null
++ * @param predicate the predicate for the sorted set, must not be null
++ * @return a predicated sorted set backed by the given sorted set
++ * @throws IllegalArgumentException if the Set or Predicate is null
++ */
++ public static <E> SortedSet<E> predicatedSortedSet(SortedSet<E> set, Predicate<? super E> predicate) {
++ return PredicatedSortedSet.decorate(set, predicate);
++ }
++
++ /**
++ * Returns a typed sorted set backed by the given set.
++ * <p/>
++ * Only objects of the specified type can be added to the set.
++ *
++ * @param set the set to limit to a specific type, must not be null
++ * @param type the type of objects which may be added to the set
++ * @return a typed set backed by the specified set
++ * @deprecated made obsolete by Java 1.5 generics.
++ */
++ public static <E> SortedSet<E> typedSortedSet(SortedSet<E> set, Class<E> type) {
++ return TypedSortedSet.decorate(set, type);
++ }
++
++ /**
++ * Returns a transformed sorted set backed by the given set.
++ * <p/>
++ * Each object is passed through the transformer as it is added to the
++ * Set. It is important not to use the original set after invoking this
++ * method, as it is a backdoor for adding untransformed objects.
++ *
++ * @param set the set to transform, must not be null
++ * @param transformer the transformer for the set, must not be null
++ * @return a transformed set backed by the given set
++ * @throws IllegalArgumentException if the Set or Transformer is null
++ */
++ public static <I,O> SortedSet<O> transformedSortedSet(SortedSet<I> set, Transformer<? super I, ? extends O> transformer) {
++ return TransformedSortedSet.decorate(set, transformer);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/SortedBag.java
+@@ -0,0 +1,53 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.Comparator;
++
++/**
++ * Defines a type of <code>Bag</code> that maintains a sorted order among
++ * its unique representative members.
++ *
++ * @author Matt Hall, John Watkinson, Chuck Burdick
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 2.0
++ */
++public interface SortedBag <E> extends Bag<E> {
++
++ /**
++ * Returns the comparator associated with this sorted set, or null
++ * if it uses its elements' natural ordering.
++ *
++ * @return the comparator in use, or null if natural ordering
++ */
++ public Comparator<? super E> comparator();
++
++ /**
++ * Returns the first (lowest) member.
++ *
++ * @return the first element in the sorted bag
++ */
++ public E first();
++
++ /**
++ * Returns the last (highest) member.
++ *
++ * @return the last element in the sorted bag
++ */
++ public E last();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/SortedBidiMap.java
+@@ -0,0 +1,68 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import java.util.SortedMap;
++
++/**
++ * Defines a map that allows bidirectional lookup between key and values
++ * and retains both keys and values in sorted order.
++ * <p/>
++ * Implementations should allow a value to be looked up from a key and
++ * a key to be looked up from a value with equal performance.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface SortedBidiMap <K,V> extends OrderedBidiMap<K, V>, SortedMap<K, V> {
++
++ /**
++ * Gets a view of this map where the keys and values are reversed.
++ * <p/>
++ * Changes to one map will be visible in the other and vice versa.
++ * This enables both directions of the map to be accessed equally.
++ * <p/>
++ * Implementations should seek to avoid creating a new object every time this
++ * method is called. See <code>AbstractMap.values()</code> etc. Calling this
++ * method on the inverse map should return the original.
++ * <p/>
++ * Implementations must return a <code>SortedBidiMap</code> instance,
++ * usually by forwarding to <code>inverseSortedBidiMap()</code>.
++ *
++ * @return an inverted bidirectional map
++ */
++ public BidiMap<V, K> inverseBidiMap();
++
++ /**
++ * Gets a view of this map where the keys and values are reversed.
++ * <p/>
++ * Changes to one map will be visible in the other and vice versa.
++ * This enables both directions of the map to be accessed as a <code>SortedMap</code>.
++ * <p/>
++ * Implementations should seek to avoid creating a new object every time this
++ * method is called. See <code>AbstractMap.values()</code> etc. Calling this
++ * method on the inverse map should return the original.
++ * <p/>
++ * The inverse map returned by <code>inverseBidiMap()</code> should be the
++ * same object as returned by this method.
++ *
++ * @return an inverted bidirectional map
++ */
++ public SortedBidiMap<V, K> inverseSortedBidiMap();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/Transformer.java
+@@ -0,0 +1,50 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++/**
++ * Defines a functor interface implemented by classes that transform one
++ * object into another.
++ * <p/>
++ * A <code>Transformer</code> converts the input object to the output object.
++ * The input object should be left unchanged.
++ * Transformers are typically used for type conversions, or extracting data
++ * from an object.
++ * <p/>
++ * Standard implementations of common transformers are provided by
++ * {@link TransformerUtils}. These include method invokation, returning a constant,
++ * cloning and returning the string value.
++ *
++ * @author James Strachan
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 1.0
++ */
++public interface Transformer <I,O> {
++
++ /**
++ * Transforms the input object (leaving it unchanged) into some output object.
++ *
++ * @param input the object to be transformed, should be left unchanged
++ * @return a transformed object
++ * @throws ClassCastException (runtime) if the input is the wrong class
++ * @throws IllegalArgumentException (runtime) if the input is invalid
++ * @throws FunctorException (runtime) if the transform cannot be completed
++ */
++ public O transform(I input);
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/TransformerUtils.java
+@@ -0,0 +1,414 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++import org.apache.commons.collections15.functors.*;
++
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.Map;
++
++/**
++ * <code>TransformerUtils</code> provides reference implementations and
++ * utilities for the Transformer functor interface. The supplied transformers are:
++ * <ul>
++ * <li>Invoker - returns the result of a method call on the input object
++ * <li>Clone - returns a clone of the input object
++ * <li>Constant - always returns the same object
++ * <li>Closure - performs a Closure and returns the input object
++ * <li>Predicate - returns the result of the predicate as a Boolean
++ * <li>Factory - returns a new object from a factory
++ * <li>Chained - chains two or more transformers together
++ * <li>Switch - calls one transformer based on one or more predicates
++ * <li>SwitchMap - calls one transformer looked up from a Map
++ * <li>Instantiate - the Class input object is instantiated
++ * <li>Map - returns an object from a supplied Map
++ * <li>Null - always returns null
++ * <li>NOP - returns the input object, which should be immutable
++ * <li>Exception - always throws an exception
++ * <li>StringValue - returns a <code>java.lang.String</code> representation of the input object
++ * </ul>
++ * All the supplied transformers are Serializable.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, James Carman
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public class TransformerUtils {
++
++ /**
++ * This class is not normally instantiated.
++ */
++ public TransformerUtils() {
++ super();
++ }
++
++ /**
++ * Gets a transformer that always throws an exception.
++ * This could be useful during testing as a placeholder.
++ *
++ * @return the transformer
++ * @see org.apache.commons.collections15.functors.ExceptionTransformer
++ */
++ public static Transformer exceptionTransformer() {
++ return ExceptionTransformer.INSTANCE;
++ }
++
++ /**
++ * Gets a transformer that always returns null.
++ *
++ * @return the transformer
++ * @see org.apache.commons.collections15.functors.ConstantTransformer
++ */
++ public static Transformer nullTransformer() {
++ return ConstantTransformer.NULL_INSTANCE;
++ }
++
++ /**
++ * Gets a transformer that returns the input object.
++ * The input object should be immutable to maintain the
++ * contract of Transformer (although this is not checked).
++ *
++ * @return the transformer
++ * @see org.apache.commons.collections15.functors.NOPTransformer
++ */
++ public static Transformer nopTransformer() {
++ return NOPTransformer.INSTANCE;
++ }
++
++ /**
++ * Gets a transformer that returns a clone of the input
++ * object. The input object will be cloned using one of these
++ * techniques (in order):
++ * <ul>
++ * <li>public clone method
++ * <li>public copy constructor
++ * <li>serialization clone
++ * <ul>
++ *
++ * @return the transformer
++ * @see org.apache.commons.collections15.functors.CloneTransformer
++ */
++ public static Transformer cloneTransformer() {
++ return CloneTransformer.INSTANCE;
++ }
++
++ /**
++ * Creates a Transformer that will return the same object each time the
++ * transformer is used.
++ *
++ * @param constantToReturn the constant object to return each time in the transformer
++ * @return the transformer.
++ * @see org.apache.commons.collections15.functors.ConstantTransformer
++ */
++ public static <T> Transformer<Object, T> constantTransformer(T constantToReturn) {
++ return ConstantTransformer.getInstance(constantToReturn);
++ }
++
++ /**
++ * Creates a Transformer that calls a Closure each time the transformer is used.
++ * The transformer returns the input object.
++ *
++ * @param closure the closure to run each time in the transformer, not null
++ * @return the transformer
++ * @throws IllegalArgumentException if the closure is null
++ * @see org.apache.commons.collections15.functors.ClosureTransformer
++ */
++ public static <T> Transformer<T, T> asTransformer(Closure<T> closure) {
++ return ClosureTransformer.getInstance(closure);
++ }
++
++ /**
++ * Creates a Transformer that calls a Predicate each time the transformer is used.
++ * The transformer will return either Boolean.TRUE or Boolean.FALSE.
++ *
++ * @param predicate the predicate to run each time in the transformer, not null
++ * @return the transformer
++ * @throws IllegalArgumentException if the predicate is null
++ * @see org.apache.commons.collections15.functors.PredicateTransformer
++ */
++ public static <T> Transformer<T, Boolean> asTransformer(Predicate<T> predicate) {
++ return PredicateTransformer.getInstance(predicate);
++ }
++
++ /**
++ * Creates a Transformer that calls a Factory each time the transformer is used.
++ * The transformer will return the value returned by the factory.
++ *
++ * @param factory the factory to run each time in the transformer, not null
++ * @return the transformer
++ * @throws IllegalArgumentException if the factory is null
++ * @see org.apache.commons.collections15.functors.FactoryTransformer
++ */
++ public static <T> Transformer<Object, T> asTransformer(Factory<T> factory) {
++ return FactoryTransformer.getInstance(factory);
++ }
++
++ /**
++ * Create a new Transformer that calls two transformers, passing the result of
++ * the first into the second.
++ *
++ * @param transformer1 the first transformer
++ * @param transformer2 the second transformer
++ * @return the transformer
++ * @throws IllegalArgumentException if either transformer is null
++ * @see org.apache.commons.collections15.functors.ChainedTransformer
++ */
++ public static <I,M,O> Transformer<I, O> chainedTransformer(Transformer<I, ? extends M> transformer1, Transformer<? super M, O> transformer2) {
++ return ChainedTransformer.getInstance(transformer1, transformer2);
++ }
++
++ /**
++ * Create a new Transformer that calls each transformer in turn, passing the
++ * result into the next transformer.
++ * <p/>
++ * Note-- no type safety provided by generics.
++ *
++ * @param transformers an array of transformers to chain
++ * @return the transformer
++ * @throws IllegalArgumentException if the transformers array is null
++ * @throws IllegalArgumentException if any transformer in the array is null
++ * @see org.apache.commons.collections15.functors.ChainedTransformer
++ */
++ public static <I,O> Transformer<I, O> chainedTransformer(Transformer[] transformers) {
++ return ChainedTransformer.getInstance(transformers);
++ }
++
++ /**
++ * Create a new Transformer that calls each transformer in turn, passing the
++ * result into the next transformer. The ordering is that of the iterator()
++ * method on the collection.
++ * <p/>
++ * Note-- no type safety provided by generics.
++ *
++ * @param transformers a collection of transformers to chain
++ * @return the transformer
++ * @throws IllegalArgumentException if the transformers collection is null
++ * @throws IllegalArgumentException if any transformer in the collection is null
++ * @see org.apache.commons.collections15.functors.ChainedTransformer
++ */
++ public static <I,O> Transformer<I, O> chainedTransformer(Collection transformers) {
++ return ChainedTransformer.getInstance(transformers);
++ }
++
++ /**
++ * Create a new Transformer that calls one of two transformers depending
++ * on the specified predicate.
++ *
++ * @param predicate the predicate to switch on
++ * @param trueTransformer the transformer called if the predicate is true
++ * @param falseTransformer the transformer called if the predicate is false
++ * @return the transformer
++ * @throws IllegalArgumentException if the predicate is null
++ * @throws IllegalArgumentException if either transformer is null
++ * @see org.apache.commons.collections15.functors.SwitchTransformer
++ */
++ public static <I,O> Transformer<I, O> switchTransformer(Predicate<I> predicate, Transformer<? super I, ? extends O> trueTransformer, Transformer<? super I, ? extends O> falseTransformer) {
++ return SwitchTransformer.getInstance(new Predicate[]{predicate}, new Transformer[]{trueTransformer}, falseTransformer);
++ }
++
++ /**
++ * Create a new Transformer that calls one of the transformers depending
++ * on the predicates. The transformer at array location 0 is called if the
++ * predicate at array location 0 returned true. Each predicate is evaluated
++ * until one returns true. If no predicates evaluate to true, null is returned.
++ *
++ * @param predicates an array of predicates to check
++ * @param transformers an array of transformers to call
++ * @return the transformer
++ * @throws IllegalArgumentException if the either array is null
++ * @throws IllegalArgumentException if the either array has 0 elements
++ * @throws IllegalArgumentException if any element in the arrays is null
++ * @throws IllegalArgumentException if the arrays are different sizes
++ * @see org.apache.commons.collections15.functors.SwitchTransformer
++ */
++ public static <I,O> Transformer<I, O> switchTransformer(Predicate<? super I>[] predicates, Transformer<? super I, ? extends O>[] transformers) {
++ return SwitchTransformer.<I, O>getInstance(predicates, transformers, null);
++ }
++
++ /**
++ * Create a new Transformer that calls one of the transformers depending
++ * on the predicates. The transformer at array location 0 is called if the
++ * predicate at array location 0 returned true. Each predicate is evaluated
++ * until one returns true. If no predicates evaluate to true, the default
++ * transformer is called. If the default transformer is null, null is returned.
++ *
++ * @param predicates an array of predicates to check
++ * @param transformers an array of transformers to call
++ * @param defaultTransformer the default to call if no predicate matches, null means return null
++ * @return the transformer
++ * @throws IllegalArgumentException if the either array is null
++ * @throws IllegalArgumentException if the either array has 0 elements
++ * @throws IllegalArgumentException if any element in the arrays is null
++ * @throws IllegalArgumentException if the arrays are different sizes
++ * @see org.apache.commons.collections15.functors.SwitchTransformer
++ */
++ public static <I,O> Transformer<I, O> switchTransformer(Predicate<? super I>[] predicates, Transformer<? super I, ? extends O>[] transformers, Transformer<? super I, ? extends O> defaultTransformer) {
++ return SwitchTransformer.<I, O>getInstance(predicates, transformers, defaultTransformer);
++ }
++
++ /**
++ * Create a new Transformer that calls one of the transformers depending
++ * on the predicates.
++ * <p/>
++ * The Map consists of Predicate keys and Transformer values. A transformer
++ * is called if its matching predicate returns true. Each predicate is evaluated
++ * until one returns true. If no predicates evaluate to true, the default
++ * transformer is called. The default transformer is set in the map with a
++ * null key. If no default transformer is set, null will be returned in a default
++ * case. The ordering is that of the iterator() method on the entryset collection
++ * of the map.
++ *
++ * @param predicatesAndTransformers a map of predicates to transformers
++ * @return the transformer
++ * @throws IllegalArgumentException if the map is null
++ * @throws IllegalArgumentException if the map is empty
++ * @throws IllegalArgumentException if any transformer in the map is null
++ * @throws ClassCastException if the map elements are of the wrong type
++ * @see org.apache.commons.collections15.functors.SwitchTransformer
++ */
++ public static <I,O> Transformer<I, O> switchTransformer(Map<Predicate<? super I>, Transformer<? super I, ? extends O>> predicatesAndTransformers) {
++ return SwitchTransformer.<I, O>getInstance(predicatesAndTransformers);
++ }
++
++ /**
++ * Create a new Transformer that uses the input object as a key to find the
++ * transformer to call.
++ * <p/>
++ * The Map consists of object keys and Transformer values. A transformer
++ * is called if the input object equals the key. If there is no match, the
++ * default transformer is called. The default transformer is set in the map
++ * using a null key. If no default is set, null will be returned in a default case.
++ *
++ * @param objectsAndTransformers a map of objects to transformers
++ * @return the transformer
++ * @throws IllegalArgumentException if the map is null
++ * @throws IllegalArgumentException if the map is empty
++ * @throws IllegalArgumentException if any transformer in the map is null
++ * @see org.apache.commons.collections15.functors.SwitchTransformer
++ */
++ public static <I,O> Transformer<I, O> switchMapTransformer(Map<I, Transformer<? super I, ? extends O>> objectsAndTransformers) {
++ Transformer[] trs = null;
++ Predicate[] preds = null;
++ if (objectsAndTransformers == null) {
++ throw new IllegalArgumentException("The object and transformer map must not be null");
++ }
++ Transformer<? super I, ? extends O> def = objectsAndTransformers.remove(null);
++ int size = objectsAndTransformers.size();
++ trs = new Transformer[size];
++ preds = new Predicate[size];
++ int i = 0;
++ for (Iterator<Map.Entry<I, Transformer<? super I, ? extends O>>> it = objectsAndTransformers.entrySet().iterator(); it.hasNext();) {
++ Map.Entry<I, Transformer<? super I, ? extends O>> entry = it.next();
++ preds[i] = EqualPredicate.getInstance(entry.getKey());
++ trs[i] = entry.getValue();
++ i++;
++ }
++ return switchTransformer(preds, trs, def);
++ }
++
++ /**
++ * Gets a Transformer that expects an input Class object that it will instantiate.
++ *
++ * @return the transformer
++ * @see org.apache.commons.collections15.functors.InstantiateTransformer
++ */
++ public static Transformer<Class, Object> instantiateTransformer() {
++ return InstantiateTransformer.NO_ARG_INSTANCE;
++ }
++
++ /**
++ * Creates a Transformer that expects an input Class object that it will
++ * instantiate. The constructor used is determined by the arguments specified
++ * to this method.
++ *
++ * @param paramTypes parameter types for the constructor, can be null
++ * @param args the arguments to pass to the constructor, can be null
++ * @return the transformer
++ * @throws IllegalArgumentException if the paramTypes and args don't match
++ * @see org.apache.commons.collections15.functors.InstantiateTransformer
++ */
++ public static Transformer<Class, Object> instantiateTransformer(Class[] paramTypes, Object[] args) {
++ return InstantiateTransformer.getInstance(paramTypes, args);
++ }
++
++ /**
++ * Creates a Transformer that uses the passed in Map to transform the input
++ * object (as a simple lookup).
++ *
++ * @param map the map to use to transform the objects
++ * @return the transformer
++ * @throws IllegalArgumentException if the map is null
++ * @see org.apache.commons.collections15.functors.MapTransformer
++ */
++ public static <I,O> Transformer<I, O> mapTransformer(Map<I, O> map) {
++ return MapTransformer.getInstance(map);
++ }
++
++ /**
++ * Gets a Transformer that invokes a method on the input object.
++ * The method must have no parameters. If the input object is null,
++ * null is returned.
++ * <p/>
++ * For example, <code>TransformerUtils.invokerTransformer("getName");</code>
++ * will call the <code>getName/code> method on the input object to
++ * determine the transformer result.
++ * <p/>
++ * Note: no type saftey provided by Java 1.5.
++ *
++ * @param methodName the method name to call on the input object, may not be null
++ * @return the transformer
++ * @throws IllegalArgumentException if the methodName is null.
++ * @see org.apache.commons.collections15.functors.InvokerTransformer
++ */
++ public static Transformer invokerTransformer(String methodName) {
++ return InvokerTransformer.getInstance(methodName, null, null);
++ }
++
++ /**
++ * Gets a Transformer that invokes a method on the input object.
++ * The method parameters are specified. If the input object is null,
++ * null is returned.
++ * <p/>
++ * Note: no type saftey provided by Java 1.5.
++ *
++ * @param methodName the name of the method
++ * @param paramTypes the parameter types
++ * @param args the arguments
++ * @return the transformer
++ * @throws IllegalArgumentException if the method name is null
++ * @throws IllegalArgumentException if the paramTypes and args don't match
++ * @see org.apache.commons.collections15.functors.InvokerTransformer
++ */
++ public static Transformer invokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
++ return InvokerTransformer.getInstance(methodName, paramTypes, args);
++ }
++
++ /**
++ * Gets a transformer that returns a <code>java.lang.String</code>
++ * representation of the input object. This is achieved via the
++ * <code>toString</code> method, <code>null</code> returns 'null'.
++ *
++ * @return the transformer
++ * @see org.apache.commons.collections15.functors.StringValueTransformer
++ */
++ public static <T> Transformer<T, String> stringValueTransformer() {
++ return StringValueTransformer.getInstance();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/Unmodifiable.java
+@@ -0,0 +1,39 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15;
++
++/**
++ * Marker interface for collections15, maps and iterators that are unmodifiable.
++ * <p/>
++ * This interface enables testing such as:
++ * <pre>
++ * if (coll instanceof Unmodifiable) {
++ * coll = new ArrayList(coll);
++ * }
++ * // now we know coll is modifiable
++ * </pre>
++ * Of course all this only works if you use the Unmodifiable classes defined
++ * in this library. If you use the JDK unmodifiable class via java util Collections
++ * then the interface won't be there.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public interface Unmodifiable {
++ // marker interface - no methods to implement
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/AbstractBagDecorator.java
+@@ -0,0 +1,80 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.Bag;
++import org.apache.commons.collections15.collection.AbstractCollectionDecorator;
++
++import java.util.Set;
++
++/**
++ * Decorates another <code>Bag</code> to provide additional behaviour.
++ * <p/>
++ * Methods are forwarded directly to the decorated bag.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractBagDecorator <E> extends AbstractCollectionDecorator<E> implements Bag<E> {
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ *
++ * @since Commons Collections 3.1
++ */
++ protected AbstractBagDecorator() {
++ super();
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param bag the bag to decorate, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ protected AbstractBagDecorator(Bag<E> bag) {
++ super(bag);
++ }
++
++ /**
++ * Gets the bag being decorated.
++ *
++ * @return the decorated bag
++ */
++ protected Bag<E> getBag() {
++ return (Bag<E>) getCollection();
++ }
++
++ //-----------------------------------------------------------------------
++ public int getCount(E object) {
++ return getBag().getCount(object);
++ }
++
++ public boolean add(E object, int count) {
++ return getBag().add(object, count);
++ }
++
++ public boolean remove(E object, int count) {
++ return getBag().remove(object, count);
++ }
++
++ public Set<E> uniqueSet() {
++ return getBag().uniqueSet();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/AbstractMapBag.java
+@@ -0,0 +1,600 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.Bag;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.lang.reflect.Array;
++import java.util.*;
++
++/**
++ * Abstract implementation of the {@link Bag} interface to simplify the creation
++ * of subclass implementations.
++ * <p/>
++ * Subclasses specify a Map implementation to use as the internal storage.
++ * 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.
++ *
++ * @author Chuck Burdick
++ * @author Michael A. Smith
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Janek Bogucki
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0 (previously DefaultMapBag v2.0)
++ */
++public abstract class AbstractMapBag <E> implements Bag<E> {
++
++ /**
++ * The map to use to store the data
++ */
++ private transient Map<E, MutableInteger> map;
++ /**
++ * The current total size of the bag
++ */
++ private int size;
++ /**
++ * The modification count for fail fast iterators
++ */
++ private transient int modCount;
++ /**
++ * The modification count for fail fast iterators
++ */
++ private transient Set<E> uniqueSet;
++
++ /**
++ * Constructor needed for subclass serialisation.
++ */
++ protected AbstractMapBag() {
++ super();
++ }
++
++ /**
++ * Constructor that assigns the specified Map as the backing store.
++ * The map must be empty and non-null.
++ *
++ * @param map the map to assign
++ */
++ protected AbstractMapBag(Map<E, MutableInteger> map) {
++ super();
++ this.map = map;
++ }
++
++ /**
++ * Utility method for implementations to access the map that backs
++ * this bag. Not intended for interactive use outside of subclasses.
++ *
++ * @return the map being used by the Bag
++ */
++ protected Map<E, MutableInteger> getMap() {
++ return map;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns the number of elements in this bag.
++ *
++ * @return current size of the bag
++ */
++ public int size() {
++ return size;
++ }
++
++ /**
++ * Returns true if the underlying map is empty.
++ *
++ * @return true if bag is empty
++ */
++ public boolean isEmpty() {
++ return map.isEmpty();
++ }
++
++ /**
++ * 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(E object) {
++ MutableInteger count = map.get(object);
++ if (count != null) {
++ return count.value;
++ }
++ return 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) {
++ if (coll instanceof Bag) {
++ return containsAll((Bag<E>) 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
++ */
++ boolean containsAll(Bag<E> other) {
++ boolean result = true;
++ Iterator<E> it = other.uniqueSet().iterator();
++ while (it.hasNext()) {
++ E current = it.next();
++ boolean contains = getCount(current) >= other.getCount(current);
++ result = result && contains;
++ }
++ return result;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator over the bag elements.
++ * Elements present in the Bag more than once will be returned repeatedly.
++ *
++ * @return the iterator
++ */
++ public Iterator<E> iterator() {
++ return new BagIterator<E>(this);
++ }
++
++ /**
++ * Inner class iterator for the Bag.
++ */
++ static class BagIterator <E> implements Iterator<E> {
++ private AbstractMapBag<E> parent;
++ private Iterator<Map.Entry<E, MutableInteger>> entryIterator;
++ private Map.Entry<E, MutableInteger> current;
++ private int itemCount;
++ private final int mods;
++ private boolean canRemove;
++
++ /**
++ * Constructor.
++ *
++ * @param parent the parent bag
++ */
++ public BagIterator(AbstractMapBag<E> parent) {
++ this.parent = parent;
++ this.entryIterator = parent.map.entrySet().iterator();
++ this.current = null;
++ this.mods = parent.modCount;
++ this.canRemove = false;
++ }
++
++ public boolean hasNext() {
++ return (itemCount > 0 || entryIterator.hasNext());
++ }
++
++ public E next() {
++ if (parent.modCount != mods) {
++ throw new ConcurrentModificationException();
++ }
++ if (itemCount == 0) {
++ current = entryIterator.next();
++ itemCount = current.getValue().value;
++ }
++ canRemove = true;
++ itemCount--;
++ return current.getKey();
++ }
++
++ public void remove() {
++ if (parent.modCount != mods) {
++ throw new ConcurrentModificationException();
++ }
++ if (canRemove == false) {
++ throw new IllegalStateException();
++ }
++ MutableInteger mut = current.getValue();
++ if (mut.value > 0) {
++ mut.value--;
++ parent.size--;
++ } else {
++ entryIterator.remove();
++ }
++ canRemove = false;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Adds a new element to the bag, 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(E object) {
++ return add(object, 1);
++ }
++
++ /**
++ * Adds a new element to the bag, 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(E object, int nCopies) {
++ modCount++;
++ if (nCopies > 0) {
++ MutableInteger mut = map.get(object);
++ size += nCopies;
++ if (mut == null) {
++ map.put(object, new MutableInteger(nCopies));
++ return true;
++ } else {
++ mut.value += nCopies;
++ return false;
++ }
++ } 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<? extends E> coll) {
++ boolean changed = false;
++ Iterator<? extends E> 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() {
++ modCount++;
++ map.clear();
++ size = 0;
++ }
++
++ /**
++ * Removes all copies of the specified object from the bag.
++ *
++ * @param object the object to remove
++ * @return true if the bag changed
++ */
++ public boolean remove(Object object) {
++ MutableInteger mut = map.get(object);
++ if (mut == null) {
++ return false;
++ }
++ modCount++;
++ map.remove(object);
++ size -= mut.value;
++ return true;
++ }
++
++ /**
++ * Removes a specified number of copies of an object from the bag.
++ *
++ * @param object the object to remove
++ * @param nCopies the number of copies to remove
++ * @return true if the bag changed
++ */
++ public boolean remove(E object, int nCopies) {
++ MutableInteger mut = map.get(object);
++ if (mut == null) {
++ return false;
++ }
++ if (nCopies <= 0) {
++ return false;
++ }
++ modCount++;
++ if (nCopies < mut.value) {
++ mut.value -= nCopies;
++ map.put(object, mut);
++ size -= nCopies;
++ } else {
++ map.remove(object);
++ size -= mut.value;
++ }
++ return true;
++ }
++
++ /**
++ * Removes objects from the bag according to their count in the specified collection.
++ *
++ * @param coll the collection to use
++ * @return true if the bag changed
++ */
++ public boolean removeAll(Collection<?> coll) {
++ boolean result = false;
++ if (coll != null) {
++ Iterator i = coll.iterator();
++ while (i.hasNext()) {
++ boolean changed = remove((E) 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) {
++ if (coll instanceof Bag) {
++ return retainAll((Bag<? extends E>) coll);
++ }
++ return retainAll(new HashBag(coll));
++ }
++
++ /**
++ * Remove any members of the bag that are not in the given
++ * bag, respecting cardinality.
++ *
++ * @param other the bag to retain
++ * @return <code>true</code> if this call changed the collection
++ * @see #retainAll(Collection)
++ */
++ boolean retainAll(Bag<E> other) {
++ boolean result = false;
++ Bag excess = new HashBag();
++ Iterator<E> i = uniqueSet().iterator();
++ while (i.hasNext()) {
++ E 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;
++ }
++
++ //-----------------------------------------------------------------------
++
++ /**
++ * Mutable integer class for storing the data.
++ */
++ protected static class MutableInteger {
++ /**
++ * The value of this mutable.
++ */
++ protected int value;
++
++ /**
++ * Constructor.
++ *
++ * @param value the initial value
++ */
++ MutableInteger(int value) {
++ this.value = value;
++ }
++
++ public boolean equals(Object obj) {
++ if (obj instanceof MutableInteger == false) {
++ return false;
++ }
++ return ((MutableInteger) obj).value == value;
++ }
++
++ public int hashCode() {
++ return value;
++ }
++ }
++
++ /**
++ * Returns an array of all of this bag's elements.
++ *
++ * @return an array of all of this bag's elements
++ */
++ public Object[] toArray() {
++ Object[] result = new Object[size()];
++ int i = 0;
++ Iterator<E> it = map.keySet().iterator();
++ while (it.hasNext()) {
++ E current = it.next();
++ for (int index = getCount(current); index > 0; index--) {
++ result[i++] = current;
++ }
++ }
++ return result;
++ }
++
++ /**
++ * 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) {
++ int size = size();
++ if (array.length < size) {
++ array = (Object[]) Array.newInstance(array.getClass().getComponentType(), size);
++ }
++
++ int i = 0;
++ Iterator<E> it = map.keySet().iterator();
++ while (it.hasNext()) {
++ E current = it.next();
++ for (int index = getCount(current); index > 0; index--) {
++ array[i++] = current;
++ }
++ }
++ if (array.length > size) {
++ array[size] = null;
++ }
++ return array;
++ }
++
++ /**
++ * Returns an unmodifiable view of the underlying map's key set.
++ *
++ * @return the set of unique elements in this bag
++ */
++ public Set<E> uniqueSet() {
++ if (uniqueSet == null) {
++ uniqueSet = UnmodifiableSet.decorate(map.keySet());
++ }
++ return uniqueSet;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ */
++ protected void doWriteObject(ObjectOutputStream out) throws IOException {
++ out.writeInt(map.size());
++ for (Iterator<Map.Entry<E, MutableInteger>> it = map.entrySet().iterator(); it.hasNext();) {
++ Map.Entry<E, MutableInteger> entry = it.next();
++ out.writeObject(entry.getKey());
++ out.writeInt(entry.getValue().value);
++ }
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ *
++ * @param map the map to use
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ */
++ protected void doReadObject(Map<E, MutableInteger> map, ObjectInputStream in) throws IOException, ClassNotFoundException {
++ this.map = map;
++ int entrySize = in.readInt();
++ for (int i = 0; i < entrySize; i++) {
++ E obj = (E) in.readObject();
++ int count = in.readInt();
++ map.put(obj, new MutableInteger(count));
++ size += count;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Compares this Bag to another.
++ * This Bag equals another Bag if it contains the same number of occurrences of
++ * the same elements.
++ *
++ * @param object the Bag to compare to
++ * @return true if equal
++ */
++ 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<E> it = map.keySet().iterator(); it.hasNext();) {
++ E element = it.next();
++ if (other.getCount(element) != getCount(element)) {
++ return false;
++ }
++ }
++ return true;
++ }
++
++ /**
++ * Gets a hash code for the Bag compatible with the definition of equals.
++ * The hash code is defined as the sum total of a hash code for each element.
++ * The per element hash code is defined as
++ * <code>(e==null ? 0 : e.hashCode()) ^ noOccurances)</code>.
++ * This hash code is compatible with the Set interface.
++ *
++ * @return the hash code of the Bag
++ */
++ public int hashCode() {
++ int total = 0;
++ for (Iterator<Map.Entry<E, MutableInteger>> it = map.entrySet().iterator(); it.hasNext();) {
++ Map.Entry<E, MutableInteger> entry = it.next();
++ Object element = entry.getKey();
++ Integer count = entry.getValue().value;
++ total += (element == null ? 0 : element.hashCode()) ^ count;
++ }
++ return total;
++ }
++
++ /**
++ * Implement a toString() method suitable for debugging.
++ *
++ * @return a debugging toString
++ */
++ public String toString() {
++ if (size() == 0) {
++ return "[]";
++ }
++ StringBuffer buf = new StringBuffer();
++ buf.append('[');
++ Iterator<E> it = uniqueSet().iterator();
++ while (it.hasNext()) {
++ E current = it.next();
++ int count = getCount(current);
++ buf.append(count);
++ buf.append(':');
++ buf.append(current);
++ if (it.hasNext()) {
++ buf.append(',');
++ }
++ }
++ buf.append(']');
++ return buf.toString();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/AbstractSortedBagDecorator.java
+@@ -0,0 +1,75 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.SortedBag;
++
++import java.util.Comparator;
++
++/**
++ * Decorates another <code>SortedBag</code> to provide additional behaviour.
++ * <p/>
++ * Methods are forwarded directly to the decorated bag.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractSortedBagDecorator <E> extends AbstractBagDecorator<E> implements SortedBag<E> {
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ *
++ * @since Commons Collections 3.1
++ */
++ protected AbstractSortedBagDecorator() {
++ super();
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param bag the bag to decorate, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ protected AbstractSortedBagDecorator(SortedBag<E> bag) {
++ super(bag);
++ }
++
++ /**
++ * Gets the bag being decorated.
++ *
++ * @return the decorated bag
++ */
++ protected SortedBag<E> getSortedBag() {
++ return (SortedBag<E>) getCollection();
++ }
++
++ //-----------------------------------------------------------------------
++ public E first() {
++ return getSortedBag().first();
++ }
++
++ public E last() {
++ return getSortedBag().last();
++ }
++
++ public Comparator<? super E> comparator() {
++ return getSortedBag().comparator();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/HashBag.java
+@@ -0,0 +1,84 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.Bag;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.HashMap;
++
++/**
++ * Implements <code>Bag</code>, using a <code>HashMap</code> to provide the
++ * data storage. This is the standard implementation of a bag.
++ * <p/>
++ * A <code>Bag</code> stores each object in the collection together with a
++ * count of occurrences. Extra methods on the interface allow multiple copies
++ * of an object to be added or removed at once. It is important to read the
++ * interface javadoc carefully as several methods violate the
++ * <code>Collection</code> interface specification.
++ *
++ * @author Chuck Burdick
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0 (previously in main package v2.0)
++ */
++public class HashBag <E> extends AbstractMapBag<E> implements Bag<E>, Serializable {
++
++ /**
++ * Serial version lock
++ */
++ static final long serialVersionUID = -6561115435802554013L;
++
++ /**
++ * Constructs an empty <code>HashBag</code>.
++ */
++ public HashBag() {
++ super(new HashMap<E, MutableInteger>());
++ }
++
++ /**
++ * Constructs a bag containing all the members of the given collection.
++ *
++ * @param coll a collection to copy into this bag
++ */
++ public HashBag(Collection<? extends E> coll) {
++ this();
++ addAll(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the bag out using a custom routine.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ super.doWriteObject(out);
++ }
++
++ /**
++ * Read the bag in using a custom routine.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ super.doReadObject(new HashMap<E, MutableInteger>(), in);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/PredicatedBag.java
+@@ -0,0 +1,109 @@
++// GenericsNotes: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.Bag;
++import org.apache.commons.collections15.Predicate;
++import org.apache.commons.collections15.collection.PredicatedCollection;
++
++import java.util.Set;
++
++/**
++ * Decorates another <code>Bag</code> to validate that additions
++ * match a specified predicate.
++ * <p/>
++ * This bag exists to provide validation for the decorated bag.
++ * It is normally created to decorate an empty bag.
++ * If an object cannot be added to the bag, an IllegalArgumentException is thrown.
++ * <p/>
++ * One usage would be to ensure that no null entries are added to the bag.
++ * <pre>Bag bag = PredicatedBag.decorate(new HashBag(), NotNullPredicate.INSTANCE);</pre>
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public class PredicatedBag <E> extends PredicatedCollection<E> implements Bag<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -2575833140344736876L;
++
++ /**
++ * Factory method to create a predicated (validating) bag.
++ * <p/>
++ * If there are any elements already in the bag being decorated, they
++ * are validated.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @return a new predicated Bag
++ * @throws IllegalArgumentException if bag or predicate is null
++ * @throws IllegalArgumentException if the bag contains invalid elements
++ */
++ public static <E> Bag<E> decorate(Bag<E> bag, Predicate<? super E> predicate) {
++ return new PredicatedBag<E>(bag, predicate);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the bag being decorated, they
++ * are validated.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @throws IllegalArgumentException if bag or predicate is null
++ * @throws IllegalArgumentException if the bag contains invalid elements
++ */
++ protected PredicatedBag(Bag<E> bag, Predicate<? super E> predicate) {
++ super(bag, predicate);
++ }
++
++ /**
++ * Gets the decorated bag.
++ *
++ * @return the decorated bag
++ */
++ protected Bag<E> getBag() {
++ return (Bag<E>) getCollection();
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean add(E object, int count) {
++ validate(object);
++ return getBag().add(object, count);
++ }
++
++ public boolean remove(E object, int count) {
++ return getBag().remove(object, count);
++ }
++
++ public Set uniqueSet() {
++ return getBag().uniqueSet();
++ }
++
++ public int getCount(E object) {
++ return getBag().getCount(object);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/PredicatedSortedBag.java
+@@ -0,0 +1,103 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.Predicate;
++import org.apache.commons.collections15.SortedBag;
++
++import java.util.Comparator;
++
++/**
++ * Decorates another <code>SortedBag</code> to validate that additions
++ * match a specified predicate.
++ * <p/>
++ * This bag exists to provide validation for the decorated bag.
++ * It is normally created to decorate an empty bag.
++ * If an object cannot be added to the bag, an IllegalArgumentException is thrown.
++ * <p/>
++ * One usage would be to ensure that no null entries are added to the bag.
++ * <pre>SortedBag bag = PredicatedSortedBag.decorate(new TreeBag(), NotNullPredicate.INSTANCE);</pre>
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public class PredicatedSortedBag <E> extends PredicatedBag<E> implements SortedBag<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 3448581314086406616L;
++
++ /**
++ * Factory method to create a predicated (validating) bag.
++ * <p/>
++ * If there are any elements already in the bag being decorated, they
++ * are validated.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @return a new predicated SortedBag
++ * @throws IllegalArgumentException if bag or predicate is null
++ * @throws IllegalArgumentException if the bag contains invalid elements
++ */
++ public static <E> SortedBag<E> decorate(SortedBag<E> bag, Predicate<? super E> predicate) {
++ return new PredicatedSortedBag(bag, predicate);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the bag being decorated, they
++ * are validated.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @throws IllegalArgumentException if bag or predicate is null
++ * @throws IllegalArgumentException if the bag contains invalid elements
++ */
++ protected PredicatedSortedBag(SortedBag<E> bag, Predicate<? super E> predicate) {
++ super(bag, predicate);
++ }
++
++ /**
++ * Gets the decorated sorted bag.
++ *
++ * @return the decorated bag
++ */
++ protected SortedBag<E> getSortedBag() {
++ return (SortedBag<E>) getCollection();
++ }
++
++ //-----------------------------------------------------------------------
++ public E first() {
++ return getSortedBag().first();
++ }
++
++ public E last() {
++ return getSortedBag().last();
++ }
++
++ public Comparator<? super E> comparator() {
++ return getSortedBag().comparator();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/SynchronizedBag.java
+@@ -0,0 +1,129 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.Bag;
++import org.apache.commons.collections15.collection.SynchronizedCollection;
++import org.apache.commons.collections15.set.SynchronizedSet;
++
++import java.util.Set;
++
++/**
++ * Decorates another <code>Bag</code> to synchronize its behaviour
++ * for a multi-threaded environment.
++ * <p/>
++ * Methods are synchronized, then forwarded to the decorated bag.
++ * Iterators must be separately synchronized around the loop.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public class SynchronizedBag <E> extends SynchronizedCollection<E> implements Bag<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 8084674570753837109L;
++
++ /**
++ * Factory method to create a synchronized bag.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @return a new synchronized Bag
++ * @throws IllegalArgumentException if bag is null
++ */
++ public static <E> Bag<E> decorate(Bag<E> bag) {
++ return new SynchronizedBag<E>(bag);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param bag the bag to decorate, must not be null
++ * @throws IllegalArgumentException if bag is null
++ */
++ protected SynchronizedBag(Bag<E> bag) {
++ super(bag);
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param bag the bag to decorate, must not be null
++ * @param lock the lock to use, must not be null
++ * @throws IllegalArgumentException if bag is null
++ */
++ protected SynchronizedBag(Bag<E> bag, Object lock) {
++ super(bag, lock);
++ }
++
++ /**
++ * Gets the bag being decorated.
++ *
++ * @return the decorated bag
++ */
++ protected Bag<E> getBag() {
++ return (Bag<E>) collection;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean add(E object, int count) {
++ synchronized (lock) {
++ return getBag().add(object, count);
++ }
++ }
++
++ public boolean remove(E object, int count) {
++ synchronized (lock) {
++ return getBag().remove(object, count);
++ }
++ }
++
++ public Set<E> uniqueSet() {
++ synchronized (lock) {
++ Set<E> set = getBag().uniqueSet();
++ return new SynchronizedBagSet(set, lock);
++ }
++ }
++
++ public int getCount(E object) {
++ synchronized (lock) {
++ return getBag().getCount(object);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Synchronized Set for the Bag class.
++ */
++ class SynchronizedBagSet extends SynchronizedSet<E> {
++ /**
++ * Constructor.
++ *
++ * @param set the set to decorate
++ * @param lock the lock to use, shared with the bag
++ */
++ SynchronizedBagSet(Set<E> set, Object lock) {
++ super(set, lock);
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/SynchronizedSortedBag.java
+@@ -0,0 +1,105 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.Bag;
++import org.apache.commons.collections15.SortedBag;
++
++import java.util.Comparator;
++
++/**
++ * Decorates another <code>SortedBag</code> to synchronize its behaviour
++ * for a multi-threaded environment.
++ * <p/>
++ * Methods are synchronized, then forwarded to the decorated bag.
++ * Iterators must be separately synchronized around the loop.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public class SynchronizedSortedBag <E> extends SynchronizedBag<E> implements SortedBag<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 722374056718497858L;
++
++ /**
++ * Factory method to create a synchronized sorted bag.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @return a new synchronized SortedBag
++ * @throws IllegalArgumentException if bag is null
++ */
++ public static <E> SortedBag<E> decorate(SortedBag<E> bag) {
++ return new SynchronizedSortedBag<E>(bag);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param bag the bag to decorate, must not be null
++ * @throws IllegalArgumentException if bag is null
++ */
++ protected SynchronizedSortedBag(SortedBag<E> bag) {
++ super(bag);
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param bag the bag to decorate, must not be null
++ * @param lock the lock to use, must not be null
++ * @throws IllegalArgumentException if bag is null
++ */
++ protected SynchronizedSortedBag(Bag<E> bag, Object lock) {
++ super(bag, lock);
++ }
++
++ /**
++ * Gets the bag being decorated.
++ *
++ * @return the decorated bag
++ */
++ protected SortedBag<E> getSortedBag() {
++ return (SortedBag<E>) collection;
++ }
++
++ //-----------------------------------------------------------------------
++ public synchronized E first() {
++ synchronized (lock) {
++ return getSortedBag().first();
++ }
++ }
++
++ public synchronized E last() {
++ synchronized (lock) {
++ return getSortedBag().last();
++ }
++ }
++
++ public synchronized Comparator<? super E> comparator() {
++ synchronized (lock) {
++ return getSortedBag().comparator();
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/TransformedBag.java
+@@ -0,0 +1,108 @@
++// TODO: Not yet converted - deprecated (by me).
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.Bag;
++import org.apache.commons.collections15.Transformer;
++import org.apache.commons.collections15.collection.TransformedCollection;
++import org.apache.commons.collections15.set.TransformedSet;
++
++import java.util.Set;
++
++/**
++ * Decorates another <code>Bag</code> to transform objects that are added.
++ * <p/>
++ * The add methods are affected by this class.
++ * Thus objects must be removed or searched for using their transformed form.
++ * For example, if the transformation converts Strings to Integers, you must
++ * use the Integer form to remove objects.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ * <p>
++ * Note: This class cannot support generics without breaking the Collection contract.
++ *
++ * @author Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public class TransformedBag extends TransformedCollection implements Bag {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 5421170911299074185L;
++
++ /**
++ * Factory method to create a transforming bag.
++ * <p/>
++ * If there are any elements already in the bag being decorated, they
++ * are NOT transformed.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @return a new transformed Bag
++ * @throws IllegalArgumentException if bag or transformer is null
++ */
++ public static <I,O> Bag<O> decorate(Bag<I> bag, Transformer<? super I, ? extends O> transformer) {
++ return new TransformedBag(bag, transformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the bag being decorated, they
++ * are NOT transformed.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @throws IllegalArgumentException if bag or transformer is null
++ */
++ protected TransformedBag(Bag bag, Transformer transformer) {
++ super(bag, transformer);
++ }
++
++ /**
++ * Gets the decorated bag.
++ *
++ * @return the decorated bag
++ */
++ protected Bag getBag() {
++ return (Bag) collection;
++ }
++
++ //-----------------------------------------------------------------------
++ public int getCount(Object object) {
++ return getBag().getCount(object);
++ }
++
++ public boolean remove(Object object, int nCopies) {
++ return getBag().remove(object, nCopies);
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean add(Object object, int nCopies) {
++ object = transform(object);
++ return getBag().add(object, nCopies);
++ }
++
++ public Set uniqueSet() {
++ Set set = getBag().uniqueSet();
++ return TransformedSet.decorate(set, transformer);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/TransformedSortedBag.java
+@@ -0,0 +1,99 @@
++// TODO: Not yet converted - deprecated (by me).
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.SortedBag;
++import org.apache.commons.collections15.Transformer;
++
++import java.util.Comparator;
++
++/**
++ * Decorates another <code>SortedBag</code> to transform objects that are added.
++ * <p/>
++ * The add methods are affected by this class.
++ * Thus objects must be removed or searched for using their transformed form.
++ * For example, if the transformation converts Strings to Integers, you must
++ * use the Integer form to remove objects.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ * <p>
++ * Note: This class cannot support generics without breaking the Collection contract.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public class TransformedSortedBag extends TransformedBag implements SortedBag {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -251737742649401930L;
++
++ /**
++ * Factory method to create a transforming sorted bag.
++ * <p/>
++ * If there are any elements already in the bag being decorated, they
++ * are NOT transformed.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @return a new transformed SortedBag
++ * @throws IllegalArgumentException if bag or transformer is null
++ */
++ public static <I,O> SortedBag<O> decorate(SortedBag<I> bag, Transformer<? super I, ? extends O> transformer) {
++ return new TransformedSortedBag(bag, transformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the bag being decorated, they
++ * are NOT transformed.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @throws IllegalArgumentException if bag or transformer is null
++ */
++ protected TransformedSortedBag(SortedBag bag, Transformer transformer) {
++ super(bag, transformer);
++ }
++
++ /**
++ * Gets the decorated bag.
++ *
++ * @return the decorated bag
++ */
++ protected SortedBag getSortedBag() {
++ return (SortedBag) collection;
++ }
++
++ //-----------------------------------------------------------------------
++ public Object first() {
++ return getSortedBag().first();
++ }
++
++ public Object last() {
++ return getSortedBag().last();
++ }
++
++ public Comparator comparator() {
++ return getSortedBag().comparator();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/TreeBag.java
+@@ -0,0 +1,115 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.SortedBag;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Comparator;
++import java.util.SortedMap;
++import java.util.TreeMap;
++
++/**
++ * Implements <code>SortedBag</code>, using a <code>TreeMap</code> to provide
++ * the data storage. This is the standard implementation of a sorted bag.
++ * <p/>
++ * Order will be maintained among the bag members and can be viewed through the
++ * iterator.
++ * <p/>
++ * A <code>Bag</code> stores each object in the collection together with a
++ * count of occurrences. Extra methods on the interface allow multiple copies
++ * of an object to be added or removed at once. It is important to read the
++ * interface javadoc carefully as several methods violate the
++ * <code>Collection</code> interface specification.
++ *
++ * @author Matt Hall, John Watkinson, Chuck Burdick
++ * @author Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0 (previously in main package v2.0)
++ */
++public class TreeBag <E> extends AbstractMapBag<E> implements SortedBag<E>, Serializable {
++
++ /**
++ * Serial version lock
++ */
++ static final long serialVersionUID = -7740146511091606676L;
++
++ /**
++ * Constructs an empty <code>TreeBag</code>.
++ */
++ public TreeBag() {
++ super(new TreeMap<E, MutableInteger>());
++ }
++
++ /**
++ * Constructs an empty bag that maintains order on its unique
++ * representative members according to the given {@link Comparator}.
++ *
++ * @param comparator the comparator to use
++ */
++ public TreeBag(Comparator<? super E> comparator) {
++ super(new TreeMap<E, MutableInteger>(comparator));
++ }
++
++ /**
++ * Constructs a <code>TreeBag</code> containing all the members of the
++ * specified collection.
++ *
++ * @param coll the collection to copy into the bag
++ */
++ public TreeBag(Collection<? extends E> coll) {
++ this();
++ addAll(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ public E first() {
++ return ((SortedMap<E, MutableInteger>) getMap()).firstKey();
++ }
++
++ public E last() {
++ return ((SortedMap<E, MutableInteger>) getMap()).lastKey();
++ }
++
++ public Comparator comparator() {
++ return ((SortedMap) getMap()).comparator();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the bag out using a custom routine.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(comparator());
++ super.doWriteObject(out);
++ }
++
++ /**
++ * Read the bag in using a custom routine.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ Comparator comp = (Comparator) in.readObject();
++ super.doReadObject(new TreeMap<E, MutableInteger>(comp), in);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/TypedBag.java
+@@ -0,0 +1,61 @@
++// GenericsNote: Deprecated and not coverted, type safety not necessary anymore.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.Bag;
++import org.apache.commons.collections15.functors.InstanceofPredicate;
++
++/**
++ * Decorates another <code>Bag</code> to validate that elements added
++ * are of a specific type.
++ * <p/>
++ * The validation of additions is performed via an instanceof test against
++ * a specified <code>Class</code>. If an object cannot be added to the
++ * collection, an IllegalArgumentException is thrown.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Matthew Hawthorne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ * @deprecated Type safety classes not required anymore under 1.5, just use a typed Bag.
++ */
++public class TypedBag {
++
++ /**
++ * Factory method to create a typed bag.
++ * <p/>
++ * If there are any elements already in the bag being decorated, they
++ * are validated.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @param type the type to allow into the bag, must not be null
++ * @return a new typed Bag
++ * @throws IllegalArgumentException if bag or type is null
++ * @throws IllegalArgumentException if the bag contains invalid elements
++ */
++ public static Bag decorate(Bag bag, Class type) {
++ return new PredicatedBag(bag, InstanceofPredicate.getInstance(type));
++ }
++
++ /**
++ * Restrictive constructor.
++ */
++ protected TypedBag() {
++ super();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/TypedSortedBag.java
+@@ -0,0 +1,60 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.SortedBag;
++import org.apache.commons.collections15.functors.InstanceofPredicate;
++
++/**
++ * Decorates another <code>SortedBag</code> to validate that elements added
++ * are of a specific type.
++ * <p/>
++ * The validation of additions is performed via an instanceof test against
++ * a specified <code>Class</code>. If an object cannot be added to the
++ * collection, an IllegalArgumentException is thrown.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Matthew Hawthorne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public class TypedSortedBag <E> {
++
++ /**
++ * Factory method to create a typed sorted bag.
++ * <p/>
++ * If there are any elements already in the bag being decorated, they
++ * are validated.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @param type the type to allow into the bag, must not be null
++ * @return a new transformed SortedBag
++ * @throws IllegalArgumentException if bag or type is null
++ * @throws IllegalArgumentException if the bag contains invalid elements
++ */
++ public static <E> SortedBag<E> decorate(SortedBag<E> bag, Class<E> type) {
++ return new PredicatedSortedBag<E>(bag, InstanceofPredicate.getInstance(type));
++ }
++
++ /**
++ * Restrictive constructor.
++ */
++ protected TypedSortedBag() {
++ super();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/UnmodifiableBag.java
+@@ -0,0 +1,142 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.Bag;
++import org.apache.commons.collections15.Unmodifiable;
++import org.apache.commons.collections15.iterators.UnmodifiableIterator;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.Set;
++
++/**
++ * Decorates another <code>Bag</code> to ensure it can't be altered.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableBag <E> extends AbstractBagDecorator<E> implements Unmodifiable, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -1873799975157099624L;
++
++ /**
++ * Factory method to create an unmodifiable bag.
++ * <p/>
++ * If the bag passed in is already unmodifiable, it is returned.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @return an unmodifiable Bag
++ * @throws IllegalArgumentException if bag is null
++ */
++ public static <E> Bag<E> decorate(Bag<E> bag) {
++ if (bag instanceof Unmodifiable) {
++ return bag;
++ }
++ return new UnmodifiableBag<E>(bag);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param bag the bag to decorate, must not be null
++ * @throws IllegalArgumentException if bag is null
++ */
++ private UnmodifiableBag(Bag<E> bag) {
++ super(bag);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the collection out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(collection);
++ }
++
++ /**
++ * Read the collection in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ collection = (Collection<E>) in.readObject();
++ }
++
++ //-----------------------------------------------------------------------
++ public Iterator<E> iterator() {
++ return UnmodifiableIterator.decorate(getCollection().iterator());
++ }
++
++ public boolean add(E object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean remove(Object object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean add(E object, int count) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean remove(E object, int count) {
++ throw new UnsupportedOperationException();
++ }
++
++ public Set<E> uniqueSet() {
++ Set<E> set = getBag().uniqueSet();
++ return UnmodifiableSet.decorate(set);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/UnmodifiableSortedBag.java
+@@ -0,0 +1,142 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bag;
++
++import org.apache.commons.collections15.SortedBag;
++import org.apache.commons.collections15.Unmodifiable;
++import org.apache.commons.collections15.iterators.UnmodifiableIterator;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.Set;
++
++/**
++ * Decorates another <code>SortedBag</code> to ensure it can't be altered.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableSortedBag <E> extends AbstractSortedBagDecorator<E> implements Unmodifiable, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -3190437252665717841L;
++
++ /**
++ * Factory method to create an unmodifiable bag.
++ * <p/>
++ * If the bag passed in is already unmodifiable, it is returned.
++ *
++ * @param bag the bag to decorate, must not be null
++ * @return an unmodifiable SortedBag
++ * @throws IllegalArgumentException if bag is null
++ */
++ public static <E> SortedBag<E> decorate(SortedBag<E> bag) {
++ if (bag instanceof Unmodifiable) {
++ return bag;
++ }
++ return new UnmodifiableSortedBag<E>(bag);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param bag the bag to decorate, must not be null
++ * @throws IllegalArgumentException if bag is null
++ */
++ private UnmodifiableSortedBag(SortedBag<E> bag) {
++ super(bag);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the collection out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(collection);
++ }
++
++ /**
++ * Read the collection in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ collection = (Collection<E>) in.readObject();
++ }
++
++ //-----------------------------------------------------------------------
++ public Iterator iterator() {
++ return UnmodifiableIterator.decorate(getCollection().iterator());
++ }
++
++ public boolean add(E object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean remove(Object object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean add(E object, int count) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean remove(E object, int count) {
++ throw new UnsupportedOperationException();
++ }
++
++ public Set<E> uniqueSet() {
++ Set<E> set = getBag().uniqueSet();
++ return UnmodifiableSet.decorate(set);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bag/package.html
+@@ -0,0 +1,39 @@
++<!-- $Id: package.html,v 1.1 2005/10/11 17:05:19 pents90 Exp $ -->
++ <!--
++ Copyright 2003-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<BODY>
++<p>
++This package contains implementations of the
++{@link org.apache.commons.collections.Bag Bag} and
++{@link org.apache.commons.collections.SortedBag SortedBag} interfaces.
++A bag stores an object and a count of the number of occurences of the object.
++<p>
++The following implementations are provided in the package:
++<ul>
++<li>HashBag - implementation that uses a HashMap to store the data
++<li>TreeBag - implementation that uses a TreeMap to store the data
++</ul>
++<p>
++The following decorators are provided in the package:
++<ul>
++<li>Synchronized - synchronizes method access for multi-threaded environments
++<li>Unmodifiable - ensures the bag cannot be altered
++<li>Predicated - ensures that only elements that are valid according to a predicate can be added
++<li>Typed - ensures that only elements that are of a specific type can be added
++<li>Transformed - transforms each element added to the bag
++</ul>
++</pre>
++</BODY>
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bidimap/AbstractBidiMapDecorator.java
+@@ -0,0 +1,82 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bidimap;
++
++import org.apache.commons.collections15.BidiMap;
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.map.AbstractMapDecorator;
++
++import java.util.Set;
++
++/**
++ * Provides a base decorator that enables additional functionality to be added
++ * to a BidiMap via decoration.
++ * <p/>
++ * Methods are forwarded directly to the decorated map.
++ * <p/>
++ * This implementation does not perform any special processing with the map views.
++ * 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.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractBidiMapDecorator <K,V> extends AbstractMapDecorator<K, V> implements BidiMap<K, V> {
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ protected AbstractBidiMapDecorator(BidiMap<K, V> map) {
++ super(map);
++ }
++
++ /**
++ * Gets the map being decorated.
++ *
++ * @return the decorated map
++ */
++ protected BidiMap<K, V> getBidiMap() {
++ return (BidiMap<K, V>) map;
++ }
++
++ //-----------------------------------------------------------------------
++ public MapIterator<K, V> mapIterator() {
++ return getBidiMap().mapIterator();
++ }
++
++ public K getKey(Object value) {
++ return getBidiMap().getKey(value);
++ }
++
++ public K removeValue(Object value) {
++ return getBidiMap().removeValue(value);
++ }
++
++ public BidiMap<V, K> inverseBidiMap() {
++ return getBidiMap().inverseBidiMap();
++ }
++
++ public Set<V> values() {
++ return getBidiMap().values();
++ }
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bidimap/AbstractDualBidiMap.java
+@@ -0,0 +1,762 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bidimap;
++
++import org.apache.commons.collections15.BidiMap;
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.ResettableIterator;
++import org.apache.commons.collections15.collection.AbstractCollectionDecorator;
++import org.apache.commons.collections15.iterators.AbstractIteratorDecorator;
++import org.apache.commons.collections15.keyvalue.AbstractMapEntryDecorator;
++
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * Abstract <code>BidiMap</code> implemented using two maps.
++ * <p/>
++ * An implementation can be written simply by implementing the
++ * <code>createMap</code> method.
++ *
++ * @author Matthew Hawthorne
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Id: AbstractDualBidiMap.java,v 1.1 2005/10/11 17:05:19 pents90 Exp $
++ * @see DualHashBidiMap
++ * @see DualTreeBidiMap
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractDualBidiMap <K,V> implements BidiMap<K, V> {
++
++ /**
++ * Delegate maps. The first map contains standard entries, and the
++ * second contains inverses.
++ */
++ protected transient Map<K, V> forwardMap;
++ protected transient Map<V, K> inverseMap;
++
++ /**
++ * Inverse view of this map.
++ */
++ protected transient BidiMap<V, K> inverseBidiMap = null;
++ /**
++ * View of the keys.
++ */
++ protected transient Set<K> keySet = null;
++ /**
++ * View of the values.
++ */
++ protected transient Set<V> values = null;
++ /**
++ * View of the entries.
++ */
++ protected transient Set<Map.Entry<K, V>> entrySet = null;
++
++ /**
++ * Creates an empty map, initialised by <code>createMap</code>.
++ * <p/>
++ * This constructor remains in place for deserialization.
++ * All other usage is deprecated in favour of
++ * {@link #AbstractDualBidiMap(Map, Map)}.
++ *
++ * @deprecated should not be used.
++ */
++ protected AbstractDualBidiMap() {
++ super();
++ forwardMap = createMap();
++ inverseMap = createMap();
++ }
++
++ /**
++ * Creates an empty map using the two maps specified as storage.
++ * <p/>
++ * The two maps must be a matching pair, normal and reverse.
++ * They will typically both be empty.
++ * <p/>
++ * Neither map is validated, so nulls may be passed in.
++ * If you choose to do this then the subclass constructor must populate
++ * the <code>maps[]</code> instance variable itself.
++ *
++ * @param normalMap the normal direction map
++ * @param reverseMap the reverse direction map
++ * @since Commons Collections 3.1
++ */
++ protected AbstractDualBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap) {
++ super();
++ forwardMap = normalMap;
++ inverseMap = reverseMap;
++ }
++
++ /**
++ * Constructs a map that decorates the specified maps,
++ * used by the subclass <code>createBidiMap</code> implementation.
++ *
++ * @param normalMap the normal direction map
++ * @param reverseMap the reverse direction map
++ * @param inverseBidiMap the inverse BidiMap
++ */
++ protected AbstractDualBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap, BidiMap<V, K> inverseBidiMap) {
++ super();
++ forwardMap = normalMap;
++ inverseMap = reverseMap;
++ this.inverseBidiMap = inverseBidiMap;
++ }
++
++ /**
++ * Creates a new instance of the map used by the subclass to store data.
++ * <p/>
++ * This design is deeply flawed and has been deprecated.
++ * It relied on subclass data being used during a superclass constructor.
++ *
++ * @return the map to be used for internal storage
++ * @deprecated For constructors, use the new two map constructor.
++ * For deserialization, populate the maps array directly in readObject.
++ */
++ protected Map createMap() {
++ return null;
++ }
++
++ /**
++ * Creates a new instance of the subclass.
++ *
++ * @param normalMap the normal direction map
++ * @param reverseMap the reverse direction map
++ * @param inverseMap this map, which is the inverse in the new map
++ * @return the inverse map
++ */
++ protected abstract <K,V> BidiMap<K, V> createBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap, BidiMap<V, K> inverseMap);
++
++ // Map delegation
++ //-----------------------------------------------------------------------
++ public V get(Object key) {
++ return forwardMap.get(key);
++ }
++
++ public int size() {
++ return forwardMap.size();
++ }
++
++ public boolean isEmpty() {
++ return forwardMap.isEmpty();
++ }
++
++ public boolean containsKey(Object key) {
++ return forwardMap.containsKey(key);
++ }
++
++ public boolean equals(Object obj) {
++ return forwardMap.equals(obj);
++ }
++
++ public int hashCode() {
++ return forwardMap.hashCode();
++ }
++
++ public String toString() {
++ return forwardMap.toString();
++ }
++
++ // BidiMap changes
++ //-----------------------------------------------------------------------
++ public V put(K key, V value) {
++ if (forwardMap.containsKey(key)) {
++ inverseMap.remove(forwardMap.get(key));
++ }
++ if (inverseMap.containsKey(value)) {
++ forwardMap.remove(inverseMap.get(value));
++ }
++ final V obj = forwardMap.put(key, value);
++ inverseMap.put(value, key);
++ return obj;
++ }
++
++ public void putAll(Map<? extends K, ? extends V> map) {
++ for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
++ Map.Entry entry = (Map.Entry) it.next();
++ put((K) entry.getKey(), (V) entry.getValue());
++ }
++ }
++
++ public V remove(Object key) {
++ V value = null;
++ if (forwardMap.containsKey(key)) {
++ value = forwardMap.remove(key);
++ inverseMap.remove(value);
++ }
++ return value;
++ }
++
++ public void clear() {
++ forwardMap.clear();
++ inverseMap.clear();
++ }
++
++ public boolean containsValue(Object value) {
++ return inverseMap.containsKey(value);
++ }
++
++ // BidiMap
++ //-----------------------------------------------------------------------
++ /**
++ * Obtains a <code>MapIterator</code> over the map.
++ * The iterator implements <code>ResetableMapIterator</code>.
++ * This implementation relies on the entrySet iterator.
++ * <p/>
++ * The setValue() methods only allow a new value to be set.
++ * If the value being set is already in the map, an IllegalArgumentException
++ * is thrown (as setValue cannot change the size of the map).
++ *
++ * @return a map iterator
++ */
++ public MapIterator<K, V> mapIterator() {
++ return new BidiMapIterator<K, V>(this);
++ }
++
++ public K getKey(Object value) {
++ return inverseMap.get(value);
++ }
++
++ public K removeValue(Object value) {
++ K key = null;
++ if (inverseMap.containsKey(value)) {
++ key = inverseMap.remove(value);
++ forwardMap.remove(key);
++ }
++ return key;
++ }
++
++ public BidiMap<V, K> inverseBidiMap() {
++ if (inverseBidiMap == null) {
++ inverseBidiMap = createBidiMap(inverseMap, forwardMap, this);
++ }
++ return inverseBidiMap;
++ }
++
++ // Map views
++ //-----------------------------------------------------------------------
++ /**
++ * Gets a keySet view of the map.
++ * Changes made on the view are reflected in the map.
++ * The set supports remove and clear but not add.
++ *
++ * @return the keySet view
++ */
++ public Set<K> keySet() {
++ if (keySet == null) {
++ keySet = new KeySet<K, V>(this);
++ }
++ return keySet;
++ }
++
++ /**
++ * Creates a key set iterator.
++ * Subclasses can override this to return iterators with different properties.
++ *
++ * @param iterator the iterator to decorate
++ * @return the keySet iterator
++ */
++ protected Iterator<K> createKeySetIterator(Iterator<K> iterator) {
++ return new KeySetIterator<K, V>(iterator, this);
++ }
++
++ /**
++ * Gets a values view of the map.
++ * Changes made on the view are reflected in the map.
++ * The set supports remove and clear but not add.
++ *
++ * @return the values view
++ */
++ public Set<V> values() {
++ if (values == null) {
++ values = new Values<K, V>(this);
++ }
++ return values;
++ }
++
++ /**
++ * Creates a values iterator.
++ * Subclasses can override this to return iterators with different properties.
++ *
++ * @param iterator the iterator to decorate
++ * @return the values iterator
++ */
++ protected Iterator<V> createValuesIterator(Iterator<V> iterator) {
++ return new ValuesIterator<K, V>(iterator, this);
++ }
++
++ /**
++ * Gets an entrySet view of the map.
++ * Changes made on the set are reflected in the map.
++ * The set supports remove and clear but not add.
++ * <p/>
++ * The Map Entry setValue() method only allow a new value to be set.
++ * If the value being set is already in the map, an IllegalArgumentException
++ * is thrown (as setValue cannot change the size of the map).
++ *
++ * @return the entrySet view
++ */
++ public Set<Map.Entry<K, V>> entrySet() {
++ if (entrySet == null) {
++ entrySet = new EntrySet<K, V>(this);
++ }
++ return entrySet;
++ }
++
++ /**
++ * Creates an entry set iterator.
++ * Subclasses can override this to return iterators with different properties.
++ *
++ * @param iterator the iterator to decorate
++ * @return the entrySet iterator
++ */
++ protected Iterator<Map.Entry<K, V>> createEntrySetIterator(Iterator<Map.Entry<K, V>> iterator) {
++ return new EntrySetIterator<K, V>(iterator, this);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Inner class View.
++ */
++ protected static abstract class View <K,V,E> extends AbstractCollectionDecorator<E> {
++
++ /**
++ * The parent map
++ */
++ protected final AbstractDualBidiMap<K, V> parent;
++
++ /**
++ * Constructs a new view of the BidiMap.
++ *
++ * @param coll the collection view being decorated
++ * @param parent the parent BidiMap
++ */
++ protected View(Collection<E> coll, AbstractDualBidiMap<K, V> parent) {
++ super(coll);
++ this.parent = parent;
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ if (parent.isEmpty() || coll.isEmpty()) {
++ return false;
++ }
++ boolean modified = false;
++ Iterator it = iterator();
++ while (it.hasNext()) {
++ if (coll.contains(it.next())) {
++ it.remove();
++ modified = true;
++ }
++ }
++ return modified;
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ if (parent.isEmpty()) {
++ return false;
++ }
++ if (coll.isEmpty()) {
++ parent.clear();
++ return true;
++ }
++ boolean modified = false;
++ Iterator it = iterator();
++ while (it.hasNext()) {
++ if (coll.contains(it.next()) == false) {
++ it.remove();
++ modified = true;
++ }
++ }
++ return modified;
++ }
++
++ public void clear() {
++ parent.clear();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Inner class KeySet.
++ */
++ protected static class KeySet <K,V> extends View<K, V, K> implements Set<K> {
++
++ /**
++ * Constructs a new view of the BidiMap.
++ *
++ * @param parent the parent BidiMap
++ */
++ protected KeySet(AbstractDualBidiMap<K, V> parent) {
++ super(parent.forwardMap.keySet(), parent);
++ }
++
++ public Iterator<K> iterator() {
++ return parent.createKeySetIterator(super.iterator());
++ }
++
++ public boolean contains(Object key) {
++ return parent.forwardMap.containsKey(key);
++ }
++
++ public boolean remove(Object key) {
++ if (parent.forwardMap.containsKey(key)) {
++ Object value = parent.forwardMap.remove(key);
++ parent.inverseMap.remove(value);
++ return true;
++ }
++ return false;
++ }
++ }
++
++ /**
++ * Inner class KeySetIterator.
++ */
++ protected static class KeySetIterator <K,V> extends AbstractIteratorDecorator<K> {
++
++ /**
++ * The parent map
++ */
++ protected final AbstractDualBidiMap<K, V> parent;
++ /**
++ * The last returned key
++ */
++ protected K lastKey = null;
++ /**
++ * Whether remove is allowed at present
++ */
++ protected boolean canRemove = false;
++
++ /**
++ * Constructor.
++ *
++ * @param iterator the iterator to decorate
++ * @param parent the parent map
++ */
++ protected KeySetIterator(Iterator<K> iterator, AbstractDualBidiMap<K, V> parent) {
++ super(iterator);
++ this.parent = parent;
++ }
++
++ public K next() {
++ lastKey = super.next();
++ canRemove = true;
++ return lastKey;
++ }
++
++ public void remove() {
++ if (canRemove == false) {
++ throw new IllegalStateException("Iterator remove() can only be called once after next()");
++ }
++ Object value = parent.forwardMap.get(lastKey);
++ super.remove();
++ parent.inverseMap.remove(value);
++ lastKey = null;
++ canRemove = false;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Inner class Values.
++ */
++ protected static class Values <K,V> extends View<K, V, V> implements Set<V> {
++
++ /**
++ * Constructs a new view of the BidiMap.
++ *
++ * @param parent the parent BidiMap
++ */
++ protected Values(AbstractDualBidiMap<K, V> parent) {
++ super(parent.forwardMap.values(), parent);
++ }
++
++ public Iterator<V> iterator() {
++ return parent.createValuesIterator(super.iterator());
++ }
++
++ public boolean contains(Object value) {
++ return parent.inverseMap.containsKey(value);
++ }
++
++ public boolean remove(Object value) {
++ if (parent.inverseMap.containsKey(value)) {
++ Object key = parent.inverseMap.remove(value);
++ parent.forwardMap.remove(key);
++ return true;
++ }
++ return false;
++ }
++ }
++
++ /**
++ * Inner class ValuesIterator.
++ */
++ protected static class ValuesIterator <K,V> extends AbstractIteratorDecorator<V> {
++
++ /**
++ * The parent map
++ */
++ protected final AbstractDualBidiMap<K, V> parent;
++ /**
++ * The last returned value
++ */
++ protected V lastValue = null;
++ /**
++ * Whether remove is allowed at present
++ */
++ protected boolean canRemove = false;
++
++ /**
++ * Constructor.
++ *
++ * @param iterator the iterator to decorate
++ * @param parent the parent map
++ */
++ protected ValuesIterator(Iterator<V> iterator, AbstractDualBidiMap<K, V> parent) {
++ super(iterator);
++ this.parent = parent;
++ }
++
++ public V next() {
++ lastValue = super.next();
++ canRemove = true;
++ return lastValue;
++ }
++
++ public void remove() {
++ if (canRemove == false) {
++ throw new IllegalStateException("Iterator remove() can only be called once after next()");
++ }
++ super.remove(); // removes from forwardMap
++ parent.inverseMap.remove(lastValue);
++ lastValue = null;
++ canRemove = false;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Inner class EntrySet.
++ */
++ protected static class EntrySet <K,V> extends View<K, V, Map.Entry<K, V>> implements Set<Map.Entry<K, V>> {
++
++ /**
++ * Constructs a new view of the BidiMap.
++ *
++ * @param parent the parent BidiMap
++ */
++ protected EntrySet(AbstractDualBidiMap<K, V> parent) {
++ super(parent.forwardMap.entrySet(), parent);
++ }
++
++ public Iterator<Map.Entry<K, V>> iterator() {
++ return parent.createEntrySetIterator(super.iterator());
++ }
++
++ public boolean remove(Object obj) {
++ if (obj instanceof Map.Entry == false) {
++ return false;
++ }
++ Map.Entry entry = (Map.Entry) obj;
++ Object key = entry.getKey();
++ if (parent.containsKey(key)) {
++ Object value = parent.forwardMap.get(key);
++ if (value == null ? entry.getValue() == null : value.equals(entry.getValue())) {
++ parent.forwardMap.remove(key);
++ parent.inverseMap.remove(value);
++ return true;
++ }
++ }
++ return false;
++ }
++ }
++
++ /**
++ * Inner class EntrySetIterator.
++ */
++ protected static class EntrySetIterator <K,V> extends AbstractIteratorDecorator<Map.Entry<K, V>> {
++
++ /**
++ * The parent map
++ */
++ protected final AbstractDualBidiMap<K, V> parent;
++ /**
++ * The last returned entry
++ */
++ protected Map.Entry<K, V> last = null;
++ /**
++ * Whether remove is allowed at present
++ */
++ protected boolean canRemove = false;
++
++ /**
++ * Constructor.
++ *
++ * @param iterator the iterator to decorate
++ * @param parent the parent map
++ */
++ protected EntrySetIterator(Iterator<Map.Entry<K, V>> iterator, AbstractDualBidiMap<K, V> parent) {
++ super(iterator);
++ this.parent = parent;
++ }
++
++ public Map.Entry<K, V> next() {
++ last = new MapEntry<K, V>(super.next(), parent);
++ canRemove = true;
++ return last;
++ }
++
++ public void remove() {
++ if (canRemove == false) {
++ throw new IllegalStateException("Iterator remove() can only be called once after next()");
++ }
++ // store value as remove may change the entry in the decorator (eg.TreeMap)
++ Object value = last.getValue();
++ super.remove();
++ parent.inverseMap.remove(value);
++ last = null;
++ canRemove = false;
++ }
++ }
++
++ /**
++ * Inner class MapEntry.
++ */
++ protected static class MapEntry <K,V> extends AbstractMapEntryDecorator<K, V> {
++
++ /**
++ * The parent map
++ */
++ protected final AbstractDualBidiMap<K, V> parent;
++
++ /**
++ * Constructor.
++ *
++ * @param entry the entry to decorate
++ * @param parent the parent map
++ */
++ protected MapEntry(Map.Entry<K, V> entry, AbstractDualBidiMap<K, V> parent) {
++ super(entry);
++ this.parent = parent;
++ }
++
++ public V setValue(V value) {
++ K key = MapEntry.this.getKey();
++ if (parent.inverseMap.containsKey(value) && parent.inverseMap.get(value) != key) {
++ throw new IllegalArgumentException("Cannot use setValue() when the object being set is already in the map");
++ }
++ parent.put(key, value);
++ final V oldValue = super.setValue(value);
++ return oldValue;
++ }
++ }
++
++ /**
++ * Inner class MapIterator.
++ */
++ protected static class BidiMapIterator <K,V> implements MapIterator<K, V>, ResettableIterator<K> {
++
++ /**
++ * The parent map
++ */
++ protected final AbstractDualBidiMap<K, V> parent;
++ /**
++ * The iterator being wrapped
++ */
++ protected Iterator<Map.Entry<K, V>> iterator;
++ /**
++ * The last returned entry
++ */
++ protected Map.Entry<K, V> last = null;
++ /**
++ * Whether remove is allowed at present
++ */
++ protected boolean canRemove = false;
++
++ /**
++ * Constructor.
++ *
++ * @param parent the parent map
++ */
++ protected BidiMapIterator(AbstractDualBidiMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ this.iterator = parent.forwardMap.entrySet().iterator();
++ }
++
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ public K next() {
++ last = iterator.next();
++ canRemove = true;
++ return last.getKey();
++ }
++
++ public void remove() {
++ if (canRemove == false) {
++ throw new IllegalStateException("Iterator remove() can only be called once after next()");
++ }
++ // store value as remove may change the entry in the decorator (eg.TreeMap)
++ V value = last.getValue();
++ iterator.remove();
++ parent.inverseMap.remove(value);
++ last = null;
++ canRemove = false;
++ }
++
++ public K getKey() {
++ if (last == null) {
++ throw new IllegalStateException("Iterator getKey() can only be called after next() and before remove()");
++ }
++ return last.getKey();
++ }
++
++ public V getValue() {
++ if (last == null) {
++ throw new IllegalStateException("Iterator getValue() can only be called after next() and before remove()");
++ }
++ return last.getValue();
++ }
++
++ public V setValue(V value) {
++ if (last == null) {
++ throw new IllegalStateException("Iterator setValue() can only be called after next() and before remove()");
++ }
++ if (parent.inverseMap.containsKey(value) && parent.inverseMap.get(value) != last.getKey()) {
++ throw new IllegalArgumentException("Cannot use setValue() when the object being set is already in the map");
++ }
++ return parent.put(last.getKey(), value);
++ }
++
++ public void reset() {
++ iterator = parent.forwardMap.entrySet().iterator();
++ last = null;
++ canRemove = false;
++ }
++
++ public String toString() {
++ if (last != null) {
++ return "MapIterator[" + getKey() + "=" + getValue() + "]";
++ } else {
++ return "MapIterator[]";
++ }
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bidimap/AbstractOrderedBidiMapDecorator.java
+@@ -0,0 +1,84 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bidimap;
++
++import org.apache.commons.collections15.OrderedBidiMap;
++import org.apache.commons.collections15.OrderedMapIterator;
++
++/**
++ * Provides a base decorator that enables additional functionality to be added
++ * to an OrderedBidiMap via decoration.
++ * <p/>
++ * Methods are forwarded directly to the decorated map.
++ * <p/>
++ * This implementation does not perform any special processing with the map views.
++ * Instead it simply returns the inverse 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.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractOrderedBidiMapDecorator <K,V> extends AbstractBidiMapDecorator<K, V> implements OrderedBidiMap<K, V> {
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ protected AbstractOrderedBidiMapDecorator(OrderedBidiMap<K, V> map) {
++ super(map);
++ }
++
++ /**
++ * Gets the map being decorated.
++ *
++ * @return the decorated map
++ */
++ protected OrderedBidiMap<K, V> getOrderedBidiMap() {
++ return (OrderedBidiMap<K, V>) map;
++ }
++
++ //-----------------------------------------------------------------------
++ public OrderedMapIterator<K, V> orderedMapIterator() {
++ return getOrderedBidiMap().orderedMapIterator();
++ }
++
++ public K firstKey() {
++ return getOrderedBidiMap().firstKey();
++ }
++
++ public K lastKey() {
++ return getOrderedBidiMap().lastKey();
++ }
++
++ public K nextKey(K key) {
++ return getOrderedBidiMap().nextKey(key);
++ }
++
++ public K previousKey(K key) {
++ return getOrderedBidiMap().previousKey(key);
++ }
++
++ public OrderedBidiMap<V, K> inverseOrderedBidiMap() {
++ return getOrderedBidiMap().inverseOrderedBidiMap();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bidimap/AbstractSortedBidiMapDecorator.java
+@@ -0,0 +1,82 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bidimap;
++
++import org.apache.commons.collections15.SortedBidiMap;
++
++import java.util.Comparator;
++import java.util.SortedMap;
++
++/**
++ * Provides a base decorator that enables additional functionality to be added
++ * to a SortedBidiMap via decoration.
++ * <p/>
++ * Methods are forwarded directly to the decorated map.
++ * <p/>
++ * This implementation does not perform any special processing with the map views.
++ * Instead it simply returns the inverse 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.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractSortedBidiMapDecorator <K,V> extends AbstractOrderedBidiMapDecorator<K, V> implements SortedBidiMap<K, V> {
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ public AbstractSortedBidiMapDecorator(SortedBidiMap<K, V> map) {
++ super(map);
++ }
++
++ /**
++ * Gets the map being decorated.
++ *
++ * @return the decorated map
++ */
++ protected SortedBidiMap<K, V> getSortedBidiMap() {
++ return (SortedBidiMap<K, V>) map;
++ }
++
++ //-----------------------------------------------------------------------
++ public SortedBidiMap<V, K> inverseSortedBidiMap() {
++ return getSortedBidiMap().inverseSortedBidiMap();
++ }
++
++ public Comparator<? super K> comparator() {
++ return getSortedBidiMap().comparator();
++ }
++
++ public SortedMap<K, V> subMap(K fromKey, K toKey) {
++ return getSortedBidiMap().subMap(fromKey, toKey);
++ }
++
++ public SortedMap<K, V> headMap(K toKey) {
++ return getSortedBidiMap().headMap(toKey);
++ }
++
++ public SortedMap<K, V> tailMap(K fromKey) {
++ return getSortedBidiMap().tailMap(fromKey);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bidimap/DualHashBidiMap.java
+@@ -0,0 +1,107 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bidimap;
++
++import org.apache.commons.collections15.BidiMap;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.HashMap;
++import java.util.Map;
++
++/**
++ * Implementation of <code>BidiMap</code> that uses two <code>HashMap</code> instances.
++ * <p/>
++ * Two <code>HashMap</code> instances are used in this class.
++ * This provides fast lookups at the expense of storing two sets of map entries.
++ * Commons Collections would welcome the addition of a direct hash-based
++ * implementation of the <code>BidiMap</code> interface.
++ * <p/>
++ * NOTE: From Commons Collections 3.1, all subclasses will use <code>HashMap</code>
++ * and the flawed <code>createMap</code> method is ignored.
++ *
++ * @author Matthew Hawthorne
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Id: DualHashBidiMap.java,v 1.1 2005/10/11 17:05:19 pents90 Exp $
++ * @since Commons Collections 3.0
++ */
++public class DualHashBidiMap <K,V> extends AbstractDualBidiMap<K, V> implements Serializable {
++
++ /**
++ * Ensure serialization compatibility
++ */
++ private static final long serialVersionUID = 721969328361808L;
++
++ /**
++ * Creates an empty <code>HashBidiMap</code>.
++ */
++ public DualHashBidiMap() {
++ super(new HashMap<K, V>(), new HashMap<V, K>());
++ }
++
++ /**
++ * Constructs a <code>HashBidiMap</code> and copies the mappings from
++ * specified <code>Map</code>.
++ *
++ * @param map the map whose mappings are to be placed in this map
++ */
++ public DualHashBidiMap(Map<? extends K, ? extends V> map) {
++ super(new HashMap<K, V>(), new HashMap<V, K>());
++ putAll(map);
++ }
++
++ /**
++ * Constructs a <code>HashBidiMap</code> that decorates the specified maps.
++ *
++ * @param normalMap the normal direction map
++ * @param reverseMap the reverse direction map
++ * @param inverseBidiMap the inverse BidiMap
++ */
++ protected DualHashBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap, BidiMap<V, K> inverseBidiMap) {
++ super(normalMap, reverseMap, inverseBidiMap);
++ }
++
++ /**
++ * Creates a new instance of this object.
++ *
++ * @param normalMap the normal direction map
++ * @param reverseMap the reverse direction map
++ * @param inverseBidiMap the inverse BidiMap
++ * @return new bidi map
++ */
++ protected <K,V> BidiMap<K, V> createBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap, BidiMap<V, K> inverseBidiMap) {
++ return new DualHashBidiMap<K, V>(normalMap, reverseMap, inverseBidiMap);
++ }
++
++ // Serialization
++ //-----------------------------------------------------------------------
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(forwardMap);
++ }
++
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ forwardMap = new HashMap<K, V>();
++ inverseMap = new HashMap<V, K>();
++ Map<K, V> map = (Map<K, V>) in.readObject();
++ putAll(map);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bidimap/DualTreeBidiMap.java
+@@ -0,0 +1,353 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bidimap;
++
++import org.apache.commons.collections15.*;
++import org.apache.commons.collections15.map.AbstractSortedMapDecorator;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.*;
++
++/**
++ * Implementation of <code>BidiMap</code> that uses two <code>TreeMap</code> instances.
++ * <p/>
++ * The setValue() method on iterators will succeed only if the new value being set is
++ * not already in the bidimap.
++ * <p/>
++ * When considering whether to use this class, the {@link TreeBidiMap} class should
++ * also be considered. It implements the interface using a dedicated design, and does
++ * not store each object twice, which can save on memory use.
++ * <p/>
++ * NOTE: From Commons Collections 3.1, all subclasses will use <code>TreeMap</code>
++ * and the flawed <code>createMap</code> method is ignored.
++ *
++ * @author Matthew Hawthorne
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Id: DualTreeBidiMap.java,v 1.1 2005/10/11 17:05:19 pents90 Exp $
++ * @since Commons Collections 3.0
++ */
++public class DualTreeBidiMap <K,V> extends AbstractDualBidiMap<K, V> implements SortedBidiMap<K, V>, Serializable {
++
++ /**
++ * Ensure serialization compatibility
++ */
++ private static final long serialVersionUID = 721969328361809L;
++ /**
++ * The comparator to use
++ */
++ protected final Comparator<? super K> comparator;
++
++ /**
++ * Creates an empty <code>DualTreeBidiMap</code>
++ */
++ public DualTreeBidiMap() {
++ super(new TreeMap<K, V>(), new TreeMap<V, K>());
++ this.comparator = null;
++ }
++
++ public static <E> DualTreeBidiMap<E, E> createTwoWayBidiMap(Comparator<? super E> comparator) {
++ return new DualTreeBidiMap<E, E>(comparator, comparator);
++ }
++
++ /**
++ * Constructs a <code>DualTreeBidiMap</code> and copies the mappings from
++ * specified <code>Map</code>.
++ *
++ * @param map the map whose mappings are to be placed in this map
++ */
++ public DualTreeBidiMap(Map<? extends K, ? extends V> map) {
++ super(new TreeMap<K, V>(), new TreeMap<V, K>());
++ putAll(map);
++ this.comparator = null;
++ }
++
++ /**
++ * Constructs a <code>DualTreeBidiMap</code> using the specified Comparators.
++ *
++ * @param comparator the Comparator
++ */
++ public DualTreeBidiMap(Comparator<? super K> comparator, Comparator<? super V> inverseComparator) {
++ super(new TreeMap<K, V>(comparator), new TreeMap<V, K>(inverseComparator));
++ this.comparator = comparator;
++ }
++
++ /**
++ * Constructs a <code>DualTreeBidiMap</code> that decorates the specified maps.
++ *
++ * @param normalMap the normal direction map
++ * @param reverseMap the reverse direction map
++ * @param inverseBidiMap the inverse BidiMap
++ */
++ protected DualTreeBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap, BidiMap<V, K> inverseBidiMap) {
++ super(normalMap, reverseMap, inverseBidiMap);
++ this.comparator = ((SortedMap<K, V>) normalMap).comparator();
++ }
++
++ /**
++ * Creates a new instance of this object.
++ *
++ * @param normalMap the normal direction map
++ * @param reverseMap the reverse direction map
++ * @param inverseMap the inverse BidiMap
++ * @return new bidi map
++ */
++ protected <K,V> BidiMap<K, V> createBidiMap(Map<K, V> normalMap, Map<V, K> reverseMap, BidiMap<V, K> inverseMap) {
++ return new DualTreeBidiMap<K, V>(normalMap, reverseMap, inverseMap);
++ }
++
++ //-----------------------------------------------------------------------
++ public Comparator<? super K> comparator() {
++ return ((SortedMap<K, V>) forwardMap).comparator();
++ }
++
++ public K firstKey() {
++ return ((SortedMap<K, V>) forwardMap).firstKey();
++ }
++
++ public K lastKey() {
++ return ((SortedMap<K, V>) forwardMap).lastKey();
++ }
++
++ public K nextKey(K key) {
++ if (isEmpty()) {
++ return null;
++ }
++ if (forwardMap instanceof OrderedMap) {
++ return ((OrderedMap<K, V>) forwardMap).nextKey(key);
++ }
++ SortedMap sm = (SortedMap) forwardMap;
++ Iterator<K> it = sm.tailMap(key).keySet().iterator();
++ it.next();
++ if (it.hasNext()) {
++ return it.next();
++ }
++ return null;
++ }
++
++ public K previousKey(K key) {
++ if (isEmpty()) {
++ return null;
++ }
++ if (forwardMap instanceof OrderedMap) {
++ return ((OrderedMap<K, V>) forwardMap).previousKey(key);
++ }
++ SortedMap<K, V> sm = (SortedMap<K, V>) forwardMap;
++ SortedMap<K, V> hm = sm.headMap(key);
++ if (hm.isEmpty()) {
++ return null;
++ }
++ return hm.lastKey();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Obtains an ordered map iterator.
++ * <p/>
++ * This implementation copies the elements to an ArrayList in order to
++ * provide the forward/backward behaviour.
++ *
++ * @return a new ordered map iterator
++ */
++ public OrderedMapIterator<K, V> orderedMapIterator() {
++ return new BidiOrderedMapIterator<K, V>(this);
++ }
++
++ public SortedBidiMap<V, K> inverseSortedBidiMap() {
++ return (SortedBidiMap<V, K>) inverseBidiMap();
++ }
++
++ public OrderedBidiMap<V, K> inverseOrderedBidiMap() {
++ return (OrderedBidiMap<V, K>) inverseBidiMap();
++ }
++
++ //-----------------------------------------------------------------------
++ public SortedMap<K, V> headMap(K toKey) {
++ SortedMap<K, V> sub = ((SortedMap<K, V>) forwardMap).headMap(toKey);
++ return new ViewMap(this, sub);
++ }
++
++ public SortedMap<K, V> tailMap(K fromKey) {
++ SortedMap<K, V> sub = ((SortedMap<K, V>) forwardMap).tailMap(fromKey);
++ return new ViewMap<K, V>(this, sub);
++ }
++
++ public SortedMap<K, V> subMap(K fromKey, K toKey) {
++ SortedMap<K, V> sub = ((SortedMap<K, V>) forwardMap).subMap(fromKey, toKey);
++ return new ViewMap<K, V>(this, sub);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Internal sorted map view.
++ */
++ protected static class ViewMap <K,V> extends AbstractSortedMapDecorator<K, V> {
++ /**
++ * The parent bidi map.
++ */
++ final DualTreeBidiMap<K, V> bidi;
++
++ /**
++ * Constructor.
++ *
++ * @param bidi the parent bidi map
++ * @param sm the subMap sorted map
++ */
++ protected ViewMap(DualTreeBidiMap<K, V> bidi, SortedMap<K, V> sm) {
++ // the implementation is not great here...
++ // use the forwardMap as the filtered map, but inverseMap as the full map
++ // this forces containsValue and clear to be overridden
++ super((SortedMap) bidi.createBidiMap(sm, bidi.inverseMap, bidi.inverseBidiMap));
++ this.bidi = (DualTreeBidiMap) map;
++ }
++
++ public boolean containsValue(Object value) {
++ // override as default implementation jumps to [1]
++ return bidi.forwardMap.containsValue(value);
++ }
++
++ public void clear() {
++ // override as default implementation jumps to [1]
++ for (Iterator it = keySet().iterator(); it.hasNext();) {
++ it.next();
++ it.remove();
++ }
++ }
++
++ public SortedMap<K, V> headMap(K toKey) {
++ return new ViewMap<K, V>(bidi, super.headMap(toKey));
++ }
++
++ public SortedMap<K, V> tailMap(K fromKey) {
++ return new ViewMap<K, V>(bidi, super.tailMap(fromKey));
++ }
++
++ public SortedMap<K, V> subMap(K fromKey, K toKey) {
++ return new ViewMap<K, V>(bidi, super.subMap(fromKey, toKey));
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Inner class MapIterator.
++ */
++ protected static class BidiOrderedMapIterator <K,V> implements OrderedMapIterator<K, V>, ResettableIterator<K> {
++
++ /**
++ * The parent map
++ */
++ protected final AbstractDualBidiMap<K, V> parent;
++ /**
++ * The iterator being decorated
++ */
++ protected ListIterator<Map.Entry<K, V>> iterator;
++ /**
++ * The last returned entry
++ */
++ private Map.Entry<K, V> last = null;
++
++ /**
++ * Constructor.
++ *
++ * @param parent the parent map
++ */
++ protected BidiOrderedMapIterator(AbstractDualBidiMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ iterator = new ArrayList<Map.Entry<K, V>>(parent.entrySet()).listIterator();
++ }
++
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ public K next() {
++ last = iterator.next();
++ return last.getKey();
++ }
++
++ public boolean hasPrevious() {
++ return iterator.hasPrevious();
++ }
++
++ public K previous() {
++ last = iterator.previous();
++ return last.getKey();
++ }
++
++ public void remove() {
++ iterator.remove();
++ parent.remove(last.getKey());
++ last = null;
++ }
++
++ public K getKey() {
++ if (last == null) {
++ throw new IllegalStateException("Iterator getKey() can only be called after next() and before remove()");
++ }
++ return last.getKey();
++ }
++
++ public V getValue() {
++ if (last == null) {
++ throw new IllegalStateException("Iterator getValue() can only be called after next() and before remove()");
++ }
++ return last.getValue();
++ }
++
++ public V setValue(V value) {
++ if (last == null) {
++ throw new IllegalStateException("Iterator setValue() can only be called after next() and before remove()");
++ }
++ if (parent.inverseMap.containsKey(value) && parent.inverseMap.get(value) != last.getKey()) {
++ throw new IllegalArgumentException("Cannot use setValue() when the object being set is already in the map");
++ }
++ return parent.put(last.getKey(), value);
++ }
++
++ public void reset() {
++ iterator = new ArrayList<Map.Entry<K, V>>(parent.entrySet()).listIterator();
++ last = null;
++ }
++
++ public String toString() {
++ if (last != null) {
++ return "MapIterator[" + getKey() + "=" + getValue() + "]";
++ } else {
++ return "MapIterator[]";
++ }
++ }
++ }
++
++ // Serialization
++ //-----------------------------------------------------------------------
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(forwardMap);
++ }
++
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ forwardMap = new TreeMap<K, V>(comparator);
++ inverseMap = new TreeMap<V, K>();
++ Map<K, V> map = (Map<K, V>) in.readObject();
++ putAll(map);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bidimap/TreeBidiMap.java
+@@ -0,0 +1,2144 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bidimap;
++
++import org.apache.commons.collections15.*;
++import org.apache.commons.collections15.iterators.EmptyOrderedMapIterator;
++import org.apache.commons.collections15.keyvalue.UnmodifiableMapEntry;
++
++import java.util.*;
++
++/**
++ * Red-Black tree-based implementation of BidiMap where all objects added
++ * implement the <code>Comparable</code> interface.
++ * <p/>
++ * This class guarantees that the map will be in both ascending key order
++ * and ascending value order, sorted according to the natural order for
++ * the key's and value's classes.
++ * <p/>
++ * This Map is intended for applications that need to be able to look
++ * up a key-value pairing by either key or value, and need to do so
++ * with equal efficiency.
++ * <p/>
++ * While that goal could be accomplished by taking a pair of TreeMaps
++ * and redirecting requests to the appropriate TreeMap (e.g.,
++ * containsKey would be directed to the TreeMap that maps values to
++ * keys, containsValue would be directed to the TreeMap that maps keys
++ * to values), there are problems with that implementation.
++ * If the data contained in the TreeMaps is large, the cost of redundant
++ * storage becomes significant. The {@link DualTreeBidiMap} and
++ * {@link DualHashBidiMap} implementations use this approach.
++ * <p/>
++ * This solution keeps minimizes the data storage by holding data only once.
++ * The red-black algorithm is based on java util TreeMap, but has been modified
++ * to simultaneously map a tree node by key and by value. This doubles the
++ * cost of put operations (but so does using two TreeMaps), and nearly doubles
++ * the cost of remove operations (there is a savings in that the lookup of the
++ * node to be removed only has to be performed once). And since only one node
++ * contains the key and value, storage is significantly less than that
++ * required by two TreeMaps.
++ * <p/>
++ * The Map.Entry instances returned by the appropriate methods will
++ * not allow setValue() and will throw an
++ * UnsupportedOperationException on attempts to call that method.
++ *
++ * @author Marc Johnson
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0 (previously DoubleOrderedMap v2.0)
++ */
++public class TreeBidiMap <K extends Comparable,V extends Comparable> implements OrderedBidiMap<K, V> {
++
++ private static final int KEY = 0;
++ private static final int VALUE = 1;
++ private static final int MAPENTRY = 2;
++ private static final int INVERSEMAPENTRY = 3;
++ private static final int SUM_OF_INDICES = KEY + VALUE;
++ private static final int FIRST_INDEX = 0;
++ private static final int NUMBER_OF_INDICES = 2;
++ private static final String[] dataName = new String[]{"key", "value"};
++
++ private Node<K, V>[] rootNode = new Node[2];
++ private int nodeCount = 0;
++ private int modifications = 0;
++ private Set<K> keySet;
++ private Set<V> valuesSet;
++ private Set entrySet;
++ private TreeBidiMap.Inverse<K, V> inverse = null;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructs a new empty TreeBidiMap.
++ */
++ public TreeBidiMap() {
++ super();
++ }
++
++ /**
++ * Constructs a new TreeBidiMap by copying an existing Map.
++ *
++ * @param map the map to copy
++ * @throws ClassCastException if the keys/values in the map are
++ * not Comparable or are not mutually comparable
++ * @throws NullPointerException if any key or value in the map is null
++ */
++ public TreeBidiMap(final Map map) {
++ super();
++ putAll(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns the number of key-value mappings in this map.
++ *
++ * @return the number of key-value mappings in this map
++ */
++ public int size() {
++ return nodeCount;
++ }
++
++ /**
++ * Checks whether the map is empty or not.
++ *
++ * @return true if the map is empty
++ */
++ public boolean isEmpty() {
++ return (nodeCount == 0);
++ }
++
++ /**
++ * Checks whether this map contains the a mapping for the specified key.
++ * <p/>
++ * The key must implement <code>Comparable</code>.
++ *
++ * @param key key whose presence in this map is to be tested
++ * @return true if this map contains a mapping for the specified key
++ * @throws ClassCastException if the key is of an inappropriate type
++ * @throws NullPointerException if the key is null
++ */
++ public boolean containsKey(final Object key) {
++ checkKey(key);
++ return (lookup((Comparable) key, KEY) != null);
++ }
++
++ /**
++ * Checks whether this map contains the a mapping for the specified value.
++ * <p/>
++ * The value must implement <code>Comparable</code>.
++ *
++ * @param value value whose presence in this map is to be tested
++ * @return true if this map contains a mapping for the specified value
++ * @throws ClassCastException if the value is of an inappropriate type
++ * @throws NullPointerException if the value is null
++ */
++ public boolean containsValue(final Object value) {
++ checkValue(value);
++ return (lookup((Comparable) value, VALUE) != null);
++ }
++
++ /**
++ * Gets the value to which this map maps the specified key.
++ * Returns null if the map contains no mapping for this key.
++ * <p/>
++ * The key must implement <code>Comparable</code>.
++ *
++ * @param key key whose associated value is to be returned
++ * @return the value to which this map maps the specified key,
++ * or null if the map contains no mapping for this key
++ * @throws ClassCastException if the key is of an inappropriate type
++ * @throws NullPointerException if the key is null
++ */
++ public V get(final Object key) {
++ return doGetValue(key);
++ }
++
++ /**
++ * Puts the key-value pair into the map, replacing any previous pair.
++ * <p/>
++ * When adding a key-value pair, the value may already exist in the map
++ * against a different key. That mapping is removed, to ensure that the
++ * value only occurs once in the inverse map.
++ * <pre>
++ * BidiMap map1 = new TreeBidiMap();
++ * map.put("A","B"); // contains A mapped to B, as per Map
++ * map.put("A","C"); // contains A mapped to C, as per Map
++ * <p/>
++ * BidiMap map2 = new TreeBidiMap();
++ * map.put("A","B"); // contains A mapped to B, as per Map
++ * map.put("C","B"); // contains C mapped to B, key A is removed
++ * </pre>
++ * <p/>
++ * Both key and value must implement <code>Comparable</code>.
++ *
++ * @param key key with which the specified value is to be associated
++ * @param value value to be associated with the specified key
++ * @return the previous value for the key
++ * @throws ClassCastException if the key is of an inappropriate type
++ * @throws NullPointerException if the key is null
++ */
++ public V put(final K key, final V value) {
++ return doPutByKey(key, value);
++ }
++
++ /**
++ * Puts all the mappings from the specified map into this map.
++ * <p/>
++ * All keys and values must implement <code>Comparable</code>.
++ *
++ * @param map the map to copy from
++ */
++ public void putAll(Map<? extends K, ? extends V> map) {
++ Iterator it = map.entrySet().iterator();
++ while (it.hasNext()) {
++ Map.Entry entry = (Map.Entry) it.next();
++ put((K) entry.getKey(), (V) entry.getValue());
++ }
++ }
++
++ /**
++ * Removes the mapping for this key from this map if present.
++ * <p/>
++ * The key must implement <code>Comparable</code>.
++ *
++ * @param key key whose mapping is to be removed from the map.
++ * @return previous value associated with specified key,
++ * or null if there was no mapping for key.
++ * @throws ClassCastException if the key is of an inappropriate type
++ * @throws NullPointerException if the key is null
++ */
++ public V remove(final Object key) {
++ return doRemoveByKey((K) key);
++ }
++
++ /**
++ * Removes all mappings from this map.
++ */
++ public void clear() {
++ modify();
++
++ nodeCount = 0;
++ rootNode[KEY] = null;
++ rootNode[VALUE] = null;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns the key to which this map maps the specified value.
++ * Returns null if the map contains no mapping for this value.
++ * <p/>
++ * The value must implement <code>Comparable</code>.
++ *
++ * @param value value whose associated key is to be returned.
++ * @return the key to which this map maps the specified value,
++ * or null if the map contains no mapping for this value.
++ * @throws ClassCastException if the value is of an inappropriate type
++ * @throws NullPointerException if the value is null
++ */
++ public K getKey(final Object value) {
++ return doGetKey((Comparable) value);
++ }
++
++ /**
++ * Removes the mapping for this value from this map if present.
++ * <p/>
++ * The value must implement <code>Comparable</code>.
++ *
++ * @param value value whose mapping is to be removed from the map
++ * @return previous key associated with specified value,
++ * or null if there was no mapping for value.
++ * @throws ClassCastException if the value is of an inappropriate type
++ * @throws NullPointerException if the value is null
++ */
++ public K removeValue(final Object value) {
++ return doRemoveByValue((Comparable) value);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the first (lowest) key currently in this map.
++ *
++ * @return the first (lowest) key currently in this sorted map
++ * @throws NoSuchElementException if this map is empty
++ */
++ public K firstKey() {
++ if (nodeCount == 0) {
++ throw new NoSuchElementException("Map is empty");
++ }
++ return leastNode(rootNode[KEY], KEY).getKey();
++ }
++
++ /**
++ * Gets the last (highest) key currently in this map.
++ *
++ * @return the last (highest) key currently in this sorted map
++ * @throws NoSuchElementException if this map is empty
++ */
++ public K lastKey() {
++ if (nodeCount == 0) {
++ throw new NoSuchElementException("Map is empty");
++ }
++ return greatestNode(rootNode[KEY], KEY).getKey();
++ }
++
++ /**
++ * Gets the next key after the one specified.
++ * <p/>
++ * The key must implement <code>Comparable</code>.
++ *
++ * @param key the key to search for next from
++ * @return the next key, null if no match or at end
++ */
++ public K nextKey(K key) {
++ checkKey(key);
++ Node<K, V> node = nextGreater(lookup(key, KEY), KEY);
++ return (node == null ? null : node.getKey());
++ }
++
++ /**
++ * Gets the previous key before the one specified.
++ * <p/>
++ * The key must implement <code>Comparable</code>.
++ *
++ * @param key the key to search for previous from
++ * @return the previous key, null if no match or at start
++ */
++ public K previousKey(K key) {
++ checkKey(key);
++ Node<K, V> node = nextSmaller(lookup((Comparable) key, KEY), KEY);
++ return (node == null ? null : node.getKey());
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a set view of the keys contained in this map in key order.
++ * <p/>
++ * The set is backed by the map, so changes to the map are reflected in
++ * the set, and vice-versa. If the map is modified while an iteration over
++ * the set is in progress, the results of the iteration are undefined.
++ * <p/>
++ * The set supports element removal, which removes the corresponding mapping
++ * from the map. It does not support the add or addAll operations.
++ *
++ * @return a set view of the keys contained in this map.
++ */
++ public Set<K> keySet() {
++ if (keySet == null) {
++ keySet = new View(this, KEY, KEY);
++ }
++ return keySet;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a set view of the values contained in this map in key order.
++ * The returned object can be cast to a Set.
++ * <p/>
++ * The set is backed by the map, so changes to the map are reflected in
++ * the set, and vice-versa. If the map is modified while an iteration over
++ * the set is in progress, the results of the iteration are undefined.
++ * <p/>
++ * The set supports element removal, which removes the corresponding mapping
++ * from the map. It does not support the add or addAll operations.
++ *
++ * @return a set view of the values contained in this map.
++ */
++ public Set<V> values() {
++ if (valuesSet == null) {
++ valuesSet = new View(this, KEY, VALUE);
++ }
++ return valuesSet;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a set view of the entries contained in this map in key order.
++ * For simple iteration through the map, the MapIterator is quicker.
++ * <p/>
++ * The set is backed by the map, so changes to the map are reflected in
++ * the set, and vice-versa. If the map is modified while an iteration over
++ * the set is in progress, the results of the iteration are undefined.
++ * <p/>
++ * The set supports element removal, which removes the corresponding mapping
++ * from the map. It does not support the add or addAll operations.
++ * The returned MapEntry objects do not support setValue.
++ *
++ * @return a set view of the values contained in this map.
++ */
++ public Set<Map.Entry<K, V>> entrySet() {
++ if (entrySet == null) {
++ return new EntryView(this, KEY, MAPENTRY);
++ }
++ return entrySet;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator over the map entries.
++ * <p/>
++ * For this map, this iterator is the fastest way to iterate over the entries.
++ *
++ * @return an iterator
++ */
++ public MapIterator<K, V> mapIterator() {
++ if (isEmpty()) {
++ return EmptyOrderedMapIterator.INSTANCE;
++ }
++ return new ViewMapIterator(this, KEY);
++ }
++
++ /**
++ * Gets an ordered iterator over the map entries.
++ * <p/>
++ * This iterator allows both forward and reverse iteration over the entries.
++ *
++ * @return an iterator
++ */
++ public OrderedMapIterator<K, V> orderedMapIterator() {
++ if (isEmpty()) {
++ return EmptyOrderedMapIterator.INSTANCE;
++ }
++ return new ViewMapIterator(this, KEY);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the inverse map for comparison.
++ *
++ * @return the inverse map
++ */
++ public BidiMap<V, K> inverseBidiMap() {
++ return inverseOrderedBidiMap();
++ }
++
++ /**
++ * Gets the inverse map for comparison.
++ *
++ * @return the inverse map
++ */
++ public OrderedBidiMap<V, K> inverseOrderedBidiMap() {
++ if (inverse == null) {
++ inverse = new Inverse<K, V>(this);
++ }
++ return inverse;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Compares for equals as per the API.
++ *
++ * @param obj the object to compare to
++ * @return true if equal
++ */
++ public boolean equals(Object obj) {
++ return this.doEquals(obj, KEY);
++ }
++
++ /**
++ * Gets the hash code value for this map as per the API.
++ *
++ * @return the hash code value for this map
++ */
++ public int hashCode() {
++ return this.doHashCode(KEY);
++ }
++
++ /**
++ * Returns a string version of this Map in standard format.
++ *
++ * @return a standard format string version of the map
++ */
++ public String toString() {
++ return this.doToString(KEY);
++ }
++
++ //-----------------------------------------------------------------------
++
++ /**
++ * Common get logic, used to get by value
++ *
++ * @param value the key or value that we're looking for
++ * @return the key (if the value was mapped) or the value (if the
++ * key was mapped); null if we couldn't find the specified
++ * object
++ */
++ private K doGetKey(final Comparable value) {
++ checkNonNullComparable(value);
++ Node<K, V> node = lookup(value, VALUE);
++ if (node == null) {
++ return null;
++ } else {
++ return node.getKey();
++ }
++ }
++
++ /**
++ * Common get logic, used to get by key
++ *
++ * @param key the key or value that we're looking for
++ * @return the key (if the value was mapped) or the value (if the
++ * key was mapped); null if we couldn't find the specified
++ * object
++ */
++ private V doGetValue(final Object key) {
++ checkNonNullComparable(key);
++ Node<K, V> node = lookup((Comparable) key, KEY);
++ if (node == null) {
++ return null;
++ } else {
++ return node.getValue();
++ }
++ }
++
++ /**
++ * Common put logic
++ *
++ * @param key the key, always the main map key
++ * @param value the value, always the main map value
++ * @return the previously mapped value
++ */
++ private V doPutByKey(final K key, final V value) {
++ checkKeyAndValue(key, value);
++
++ // store previous and remove previous mappings
++ V prev = doGetValue(key);
++
++ doPut(key, value);
++ return prev;
++ }
++
++ /**
++ * Common put logic
++ *
++ * @param key the key, always the main map key
++ * @param value the value, always the main map value
++ * @return the previously mapped value
++ */
++ private K doPutByValue(final K key, final V value) {
++ checkKeyAndValue(key, value);
++
++ // store previous and remove previous mappings
++ K prev = doGetKey(value);
++
++ doPut(key, value);
++ return prev;
++ }
++
++ private void doPut(final K key, final V value) {
++ doRemoveByKey(key);
++ doRemoveByValue(value);
++ Node<K, V> node = rootNode[KEY];
++ if (node == null) {
++ // map is empty
++ Node<K, V> root = new Node<K, V>(key, value);
++ rootNode[KEY] = root;
++ rootNode[VALUE] = root;
++ grow();
++
++ } else {
++ // add new mapping
++ while (true) {
++ int cmp = compare(key, node.getKey());
++
++ if (cmp == 0) {
++ // shouldn't happen
++ throw new IllegalArgumentException("Cannot store a duplicate key (\"" + key + "\") in this Map");
++ } else if (cmp < 0) {
++ if (node.getLeft(KEY) != null) {
++ node = node.getLeft(KEY);
++ } else {
++ Node<K, V> newNode = new Node<K, V>(key, value);
++
++ insertValue(newNode);
++ node.setLeft(newNode, KEY);
++ newNode.setParent(node, KEY);
++ doRedBlackInsert(newNode, KEY);
++ grow();
++
++ break;
++ }
++ } else { // cmp > 0
++ if (node.getRight(KEY) != null) {
++ node = node.getRight(KEY);
++ } else {
++ Node<K, V> newNode = new Node<K, V>(key, value);
++
++ insertValue(newNode);
++ node.setRight(newNode, KEY);
++ newNode.setParent(node, KEY);
++ doRedBlackInsert(newNode, KEY);
++ grow();
++
++ break;
++ }
++ }
++ }
++ }
++ }
++
++ /**
++ * Remove by key
++ *
++ * @param key the key
++ * @return the key, if remove by value, or the value, if remove by
++ * key. null if the specified key or value could not be
++ * found
++ */
++ private V doRemoveByKey(final K key) {
++ Node<K, V> node = lookup(key, KEY);
++ V rval = null;
++ if (node != null) {
++ rval = node.getValue();
++ doRedBlackDelete(node);
++ }
++ return rval;
++ }
++
++ /**
++ * Remove by value
++ *
++ * @param value the value
++ * @return the key, if remove by value, or the value, if remove by
++ * key. null if the specified key or value could not be
++ * found
++ */
++ private K doRemoveByValue(final Comparable value) {
++ Node<K, V> node = lookup(value, VALUE);
++ K rval = null;
++ if (node != null) {
++ rval = node.getKey();
++ doRedBlackDelete(node);
++ }
++ return rval;
++ }
++
++ /**
++ * do the actual lookup of a piece of data
++ *
++ * @param data the key or value to be looked up
++ * @param index the KEY or VALUE int
++ * @return the desired Node, or null if there is no mapping of the
++ * specified data
++ */
++ private Node<K, V> lookup(final Comparable data, final int index) {
++ Node<K, V> rval = null;
++ Node<K, V> node = rootNode[index];
++
++ while (node != null) {
++ int cmp = compare(data, node.getData(index));
++ if (cmp == 0) {
++ rval = node;
++ break;
++ } else {
++ node = (cmp < 0) ? node.getLeft(index) : node.getRight(index);
++ }
++ }
++
++ return rval;
++ }
++
++ /**
++ * get the next larger node from the specified node
++ *
++ * @param node the node to be searched from
++ * @param index the KEY or VALUE int
++ * @return the specified node
++ */
++ private Node<K, V> nextGreater(final Node<K, V> node, final int index) {
++ Node<K, V> rval = null;
++ if (node == null) {
++ rval = null;
++ } else if (node.getRight(index) != null) {
++ // everything to the node's right is larger. The least of
++ // the right node's descendants is the next larger node
++ rval = leastNode(node.getRight(index), index);
++ } else {
++ // traverse up our ancestry until we find an ancestor that
++ // is null or one whose left child is our ancestor. If we
++ // find a null, then this node IS the largest node in the
++ // tree, and there is no greater node. Otherwise, we are
++ // the largest node in the subtree on that ancestor's left
++ // ... and that ancestor is the next greatest node
++ Node<K, V> parent = node.getParent(index);
++ Node<K, V> child = node;
++
++ while ((parent != null) && (child == parent.getRight(index))) {
++ child = parent;
++ parent = parent.getParent(index);
++ }
++ rval = parent;
++ }
++ return rval;
++ }
++
++ /**
++ * get the next larger node from the specified node
++ *
++ * @param node the node to be searched from
++ * @param index the KEY or VALUE int
++ * @return the specified node
++ */
++ private Node<K, V> nextSmaller(final Node<K, V> node, final int index) {
++ Node<K, V> rval = null;
++ if (node == null) {
++ rval = null;
++ } else if (node.getLeft(index) != null) {
++ // everything to the node's left is smaller. The greatest of
++ // the left node's descendants is the next smaller node
++ rval = greatestNode(node.getLeft(index), index);
++ } else {
++ // traverse up our ancestry until we find an ancestor that
++ // is null or one whose right child is our ancestor. If we
++ // find a null, then this node IS the largest node in the
++ // tree, and there is no greater node. Otherwise, we are
++ // the largest node in the subtree on that ancestor's right
++ // ... and that ancestor is the next greatest node
++ Node<K, V> parent = node.getParent(index);
++ Node<K, V> child = node;
++
++ while ((parent != null) && (child == parent.getLeft(index))) {
++ child = parent;
++ parent = parent.getParent(index);
++ }
++ rval = parent;
++ }
++ return rval;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Get the opposite index of the specified index
++ *
++ * @param index the KEY or VALUE int
++ * @return VALUE (if KEY was specified), else KEY
++ */
++ private static int oppositeIndex(final int index) {
++ // old trick ... to find the opposite of a value, m or n,
++ // subtract the value from the sum of the two possible
++ // values. (m + n) - m = n; (m + n) - n = m
++ return SUM_OF_INDICES - index;
++ }
++
++ /**
++ * Compare two objects
++ *
++ * @param o1 the first object
++ * @param o2 the second object
++ * @return negative value if o1 < o2; 0 if o1 == o2; positive
++ * value if o1 > o2
++ */
++ private static int compare(final Comparable o1, final Comparable o2) {
++ return o1.compareTo(o2);
++ }
++
++ /**
++ * Find the least node from a given node.
++ *
++ * @param node the node from which we will start searching
++ * @param index the KEY or VALUE int
++ * @return the smallest node, from the specified node, in the
++ * specified mapping
++ */
++ private static <K extends Comparable,V extends Comparable> Node<K, V> leastNode(final Node<K, V> node, final int index) {
++ Node<K, V> rval = node;
++ if (rval != null) {
++ while (rval.getLeft(index) != null) {
++ rval = rval.getLeft(index);
++ }
++ }
++ return rval;
++ }
++
++ /**
++ * Find the greatest node from a given node.
++ *
++ * @param node the node from which we will start searching
++ * @param index the KEY or VALUE int
++ * @return the greatest node, from the specified node
++ */
++ private static <K extends Comparable,V extends Comparable> Node<K, V> greatestNode(final Node<K, V> node, final int index) {
++ Node<K, V> rval = node;
++ if (rval != null) {
++ while (rval.getRight(index) != null) {
++ rval = rval.getRight(index);
++ }
++ }
++ return rval;
++ }
++
++ /**
++ * copy the color from one node to another, dealing with the fact
++ * that one or both nodes may, in fact, be null
++ *
++ * @param from the node whose color we're copying; may be null
++ * @param to the node whose color we're changing; may be null
++ * @param index the KEY or VALUE int
++ */
++ private static void copyColor(final Node from, final Node to, final int index) {
++ if (to != null) {
++ if (from == null) {
++ // by default, make it black
++ to.setBlack(index);
++ } else {
++ to.copyColor(from, index);
++ }
++ }
++ }
++
++ /**
++ * is the specified node red? if the node does not exist, no, it's
++ * black, thank you
++ *
++ * @param node the node (may be null) in question
++ * @param index the KEY or VALUE int
++ */
++ private static boolean isRed(final Node node, final int index) {
++ return ((node == null) ? false : node.isRed(index));
++ }
++
++ /**
++ * is the specified black red? if the node does not exist, sure,
++ * it's black, thank you
++ *
++ * @param node the node (may be null) in question
++ * @param index the KEY or VALUE int
++ */
++ private static boolean isBlack(final Node node, final int index) {
++ return ((node == null) ? true : node.isBlack(index));
++ }
++
++ /**
++ * force a node (if it exists) red
++ *
++ * @param node the node (may be null) in question
++ * @param index the KEY or VALUE int
++ */
++ private static void makeRed(final Node node, final int index) {
++ if (node != null) {
++ node.setRed(index);
++ }
++ }
++
++ /**
++ * force a node (if it exists) black
++ *
++ * @param node the node (may be null) in question
++ * @param index the KEY or VALUE int
++ */
++ private static <K extends Comparable,V extends Comparable> void makeBlack(final Node<K, V> node, final int index) {
++ if (node != null) {
++ node.setBlack(index);
++ }
++ }
++
++ /**
++ * get a node's grandparent. mind you, the node, its parent, or
++ * its grandparent may not exist. no problem
++ *
++ * @param node the node (may be null) in question
++ * @param index the KEY or VALUE int
++ */
++ private static <K extends Comparable,V extends Comparable> Node<K, V> getGrandParent(final Node<K, V> node, final int index) {
++ return getParent(getParent(node, index), index);
++ }
++
++ /**
++ * get a node's parent. mind you, the node, or its parent, may not
++ * exist. no problem
++ *
++ * @param node the node (may be null) in question
++ * @param index the KEY or VALUE int
++ */
++ private static <K extends Comparable,V extends Comparable> Node<K, V> getParent(final Node<K, V> node, final int index) {
++ return ((node == null) ? null : node.getParent(index));
++ }
++
++ /**
++ * get a node's right child. mind you, the node may not exist. no
++ * problem
++ *
++ * @param node the node (may be null) in question
++ * @param index the KEY or VALUE int
++ */
++ private static <K extends Comparable,V extends Comparable> Node<K, V> getRightChild(final Node<K, V> node, final int index) {
++ return (node == null) ? null : node.getRight(index);
++ }
++
++ /**
++ * get a node's left child. mind you, the node may not exist. no
++ * problem
++ *
++ * @param node the node (may be null) in question
++ * @param index the KEY or VALUE int
++ */
++ private static <K extends Comparable,V extends Comparable> Node<K, V> getLeftChild(final Node<K, V> node, final int index) {
++ return (node == null) ? null : node.getLeft(index);
++ }
++
++ /**
++ * is this node its parent's left child? mind you, the node, or
++ * its parent, may not exist. no problem. if the node doesn't
++ * exist ... it's its non-existent parent's left child. If the
++ * node does exist but has no parent ... no, we're not the
++ * non-existent parent's left child. Otherwise (both the specified
++ * node AND its parent exist), check.
++ *
++ * @param node the node (may be null) in question
++ * @param index the KEY or VALUE int
++ */
++ private static <K extends Comparable,V extends Comparable> boolean isLeftChild(final Node<K, V> node, final int index) {
++ return (node == null) ? true : ((node.getParent(index) == null) ? false : (node == node.getParent(index).getLeft(index)));
++ }
++
++ /**
++ * is this node its parent's right child? mind you, the node, or
++ * its parent, may not exist. no problem. if the node doesn't
++ * exist ... it's its non-existent parent's right child. If the
++ * node does exist but has no parent ... no, we're not the
++ * non-existent parent's right child. Otherwise (both the
++ * specified node AND its parent exist), check.
++ *
++ * @param node the node (may be null) in question
++ * @param index the KEY or VALUE int
++ */
++ private static <K extends Comparable,V extends Comparable> boolean isRightChild(final Node<K, V> node, final int index) {
++ return (node == null) ? true : ((node.getParent(index) == null) ? false : (node == node.getParent(index).getRight(index)));
++ }
++
++ /**
++ * do a rotate left. standard fare in the world of balanced trees
++ *
++ * @param node the node to be rotated
++ * @param index the KEY or VALUE int
++ */
++ private void rotateLeft(final Node<K, V> node, final int index) {
++ Node<K, V> rightChild = node.getRight(index);
++ node.setRight(rightChild.getLeft(index), index);
++
++ if (rightChild.getLeft(index) != null) {
++ rightChild.getLeft(index).setParent(node, index);
++ }
++ rightChild.setParent(node.getParent(index), index);
++
++ if (node.getParent(index) == null) {
++ // node was the root ... now its right child is the root
++ rootNode[index] = rightChild;
++ } else if (node.getParent(index).getLeft(index) == node) {
++ node.getParent(index).setLeft(rightChild, index);
++ } else {
++ node.getParent(index).setRight(rightChild, index);
++ }
++
++ rightChild.setLeft(node, index);
++ node.setParent(rightChild, index);
++ }
++
++ /**
++ * do a rotate right. standard fare in the world of balanced trees
++ *
++ * @param node the node to be rotated
++ * @param index the KEY or VALUE int
++ */
++ private void rotateRight(final Node<K, V> node, final int index) {
++ Node<K, V> leftChild = node.getLeft(index);
++ node.setLeft(leftChild.getRight(index), index);
++ if (leftChild.getRight(index) != null) {
++ leftChild.getRight(index).setParent(node, index);
++ }
++ leftChild.setParent(node.getParent(index), index);
++
++ if (node.getParent(index) == null) {
++ // node was the root ... now its left child is the root
++ rootNode[index] = leftChild;
++ } else if (node.getParent(index).getRight(index) == node) {
++ node.getParent(index).setRight(leftChild, index);
++ } else {
++ node.getParent(index).setLeft(leftChild, index);
++ }
++
++ leftChild.setRight(node, index);
++ node.setParent(leftChild, index);
++ }
++
++ /**
++ * complicated red-black insert stuff. Based on Sun's TreeMap
++ * implementation, though it's barely recognizable any more
++ *
++ * @param insertedNode the node to be inserted
++ * @param index the KEY or VALUE int
++ */
++ private void doRedBlackInsert(final Node<K, V> insertedNode, final int index) {
++ Node<K, V> currentNode = insertedNode;
++ makeRed(currentNode, index);
++
++ while ((currentNode != null) && (currentNode != rootNode[index]) && (isRed(currentNode.getParent(index), index))) {
++ if (isLeftChild(getParent(currentNode, index), index)) {
++ Node<K, V> y = getRightChild(getGrandParent(currentNode, index), index);
++
++ if (isRed(y, index)) {
++ makeBlack(getParent(currentNode, index), index);
++ makeBlack(y, index);
++ makeRed(getGrandParent(currentNode, index), index);
++
++ currentNode = getGrandParent(currentNode, index);
++ } else {
++ if (isRightChild(currentNode, index)) {
++ currentNode = getParent(currentNode, index);
++
++ rotateLeft(currentNode, index);
++ }
++
++ makeBlack(getParent(currentNode, index), index);
++ makeRed(getGrandParent(currentNode, index), index);
++
++ if (getGrandParent(currentNode, index) != null) {
++ rotateRight(getGrandParent(currentNode, index), index);
++ }
++ }
++ } else {
++
++ // just like clause above, except swap left for right
++ Node<K, V> y = getLeftChild(getGrandParent(currentNode, index), index);
++
++ if (isRed(y, index)) {
++ makeBlack(getParent(currentNode, index), index);
++ makeBlack(y, index);
++ makeRed(getGrandParent(currentNode, index), index);
++
++ currentNode = getGrandParent(currentNode, index);
++ } else {
++ if (isLeftChild(currentNode, index)) {
++ currentNode = getParent(currentNode, index);
++
++ rotateRight(currentNode, index);
++ }
++
++ makeBlack(getParent(currentNode, index), index);
++ makeRed(getGrandParent(currentNode, index), index);
++
++ if (getGrandParent(currentNode, index) != null) {
++ rotateLeft(getGrandParent(currentNode, index), index);
++ }
++ }
++ }
++ }
++
++ makeBlack(rootNode[index], index);
++ }
++
++ /**
++ * complicated red-black delete stuff. Based on Sun's TreeMap
++ * implementation, though it's barely recognizable any more
++ *
++ * @param deletedNode the node to be deleted
++ */
++ private void doRedBlackDelete(final Node<K, V> deletedNode) {
++ for (int index = FIRST_INDEX; index < NUMBER_OF_INDICES; index++) {
++ // if deleted node has both left and children, swap with
++ // the next greater node
++ if ((deletedNode.getLeft(index) != null) && (deletedNode.getRight(index) != null)) {
++ swapPosition(nextGreater(deletedNode, index), deletedNode, index);
++ }
++
++ Node<K, V> replacement = ((deletedNode.getLeft(index) != null) ? deletedNode.getLeft(index) : deletedNode.getRight(index));
++
++ if (replacement != null) {
++ replacement.setParent(deletedNode.getParent(index), index);
++
++ if (deletedNode.getParent(index) == null) {
++ rootNode[index] = replacement;
++ } else if (deletedNode == deletedNode.getParent(index).getLeft(index)) {
++ deletedNode.getParent(index).setLeft(replacement, index);
++ } else {
++ deletedNode.getParent(index).setRight(replacement, index);
++ }
++
++ deletedNode.setLeft(null, index);
++ deletedNode.setRight(null, index);
++ deletedNode.setParent(null, index);
++
++ if (isBlack(deletedNode, index)) {
++ doRedBlackDeleteFixup(replacement, index);
++ }
++ } else {
++
++ // replacement is null
++ if (deletedNode.getParent(index) == null) {
++
++ // empty tree
++ rootNode[index] = null;
++ } else {
++
++ // deleted node had no children
++ if (isBlack(deletedNode, index)) {
++ doRedBlackDeleteFixup(deletedNode, index);
++ }
++
++ if (deletedNode.getParent(index) != null) {
++ if (deletedNode == deletedNode.getParent(index).getLeft(index)) {
++ deletedNode.getParent(index).setLeft(null, index);
++ } else {
++ deletedNode.getParent(index).setRight(null, index);
++ }
++
++ deletedNode.setParent(null, index);
++ }
++ }
++ }
++ }
++ shrink();
++ }
++
++ /**
++ * complicated red-black delete stuff. Based on Sun's TreeMap
++ * implementation, though it's barely recognizable any more. This
++ * rebalances the tree (somewhat, as red-black trees are not
++ * perfectly balanced -- perfect balancing takes longer)
++ *
++ * @param replacementNode the node being replaced
++ * @param index the KEY or VALUE int
++ */
++ private void doRedBlackDeleteFixup(final Node<K, V> replacementNode, final int index) {
++ Node<K, V> currentNode = replacementNode;
++
++ while ((currentNode != rootNode[index]) && (isBlack(currentNode, index))) {
++ if (isLeftChild(currentNode, index)) {
++ Node<K, V> siblingNode = getRightChild(getParent(currentNode, index), index);
++
++ if (isRed(siblingNode, index)) {
++ makeBlack(siblingNode, index);
++ makeRed(getParent(currentNode, index), index);
++ rotateLeft(getParent(currentNode, index), index);
++
++ siblingNode = getRightChild(getParent(currentNode, index), index);
++ }
++
++ if (isBlack(getLeftChild(siblingNode, index), index) && isBlack(getRightChild(siblingNode, index), index)) {
++ makeRed(siblingNode, index);
++
++ currentNode = getParent(currentNode, index);
++ } else {
++ if (isBlack(getRightChild(siblingNode, index), index)) {
++ makeBlack(getLeftChild(siblingNode, index), index);
++ makeRed(siblingNode, index);
++ rotateRight(siblingNode, index);
++
++ siblingNode = getRightChild(getParent(currentNode, index), index);
++ }
++
++ copyColor(getParent(currentNode, index), siblingNode, index);
++ makeBlack(getParent(currentNode, index), index);
++ makeBlack(getRightChild(siblingNode, index), index);
++ rotateLeft(getParent(currentNode, index), index);
++
++ currentNode = rootNode[index];
++ }
++ } else {
++ Node<K, V> siblingNode = getLeftChild(getParent(currentNode, index), index);
++
++ if (isRed(siblingNode, index)) {
++ makeBlack(siblingNode, index);
++ makeRed(getParent(currentNode, index), index);
++ rotateRight(getParent(currentNode, index), index);
++
++ siblingNode = getLeftChild(getParent(currentNode, index), index);
++ }
++
++ if (isBlack(getRightChild(siblingNode, index), index) && isBlack(getLeftChild(siblingNode, index), index)) {
++ makeRed(siblingNode, index);
++
++ currentNode = getParent(currentNode, index);
++ } else {
++ if (isBlack(getLeftChild(siblingNode, index), index)) {
++ makeBlack(getRightChild(siblingNode, index), index);
++ makeRed(siblingNode, index);
++ rotateLeft(siblingNode, index);
++
++ siblingNode = getLeftChild(getParent(currentNode, index), index);
++ }
++
++ copyColor(getParent(currentNode, index), siblingNode, index);
++ makeBlack(getParent(currentNode, index), index);
++ makeBlack(getLeftChild(siblingNode, index), index);
++ rotateRight(getParent(currentNode, index), index);
++
++ currentNode = rootNode[index];
++ }
++ }
++ }
++
++ makeBlack(currentNode, index);
++ }
++
++ /**
++ * swap two nodes (except for their content), taking care of
++ * special cases where one is the other's parent ... hey, it
++ * happens.
++ *
++ * @param x one node
++ * @param y another node
++ * @param index the KEY or VALUE int
++ */
++ private void swapPosition(final Node<K, V> x, final Node<K, V> y, final int index) {
++ // Save initial values.
++ Node<K, V> xFormerParent = x.getParent(index);
++ Node<K, V> xFormerLeftChild = x.getLeft(index);
++ Node<K, V> xFormerRightChild = x.getRight(index);
++ Node<K, V> yFormerParent = y.getParent(index);
++ Node<K, V> yFormerLeftChild = y.getLeft(index);
++ Node<K, V> yFormerRightChild = y.getRight(index);
++ boolean xWasLeftChild = (x.getParent(index) != null) && (x == x.getParent(index).getLeft(index));
++ boolean yWasLeftChild = (y.getParent(index) != null) && (y == y.getParent(index).getLeft(index));
++
++ // Swap, handling special cases of one being the other's parent.
++ if (x == yFormerParent) { // x was y's parent
++ x.setParent(y, index);
++
++ if (yWasLeftChild) {
++ y.setLeft(x, index);
++ y.setRight(xFormerRightChild, index);
++ } else {
++ y.setRight(x, index);
++ y.setLeft(xFormerLeftChild, index);
++ }
++ } else {
++ x.setParent(yFormerParent, index);
++
++ if (yFormerParent != null) {
++ if (yWasLeftChild) {
++ yFormerParent.setLeft(x, index);
++ } else {
++ yFormerParent.setRight(x, index);
++ }
++ }
++
++ y.setLeft(xFormerLeftChild, index);
++ y.setRight(xFormerRightChild, index);
++ }
++
++ if (y == xFormerParent) { // y was x's parent
++ y.setParent(x, index);
++
++ if (xWasLeftChild) {
++ x.setLeft(y, index);
++ x.setRight(yFormerRightChild, index);
++ } else {
++ x.setRight(y, index);
++ x.setLeft(yFormerLeftChild, index);
++ }
++ } else {
++ y.setParent(xFormerParent, index);
++
++ if (xFormerParent != null) {
++ if (xWasLeftChild) {
++ xFormerParent.setLeft(y, index);
++ } else {
++ xFormerParent.setRight(y, index);
++ }
++ }
++
++ x.setLeft(yFormerLeftChild, index);
++ x.setRight(yFormerRightChild, index);
++ }
++
++ // Fix children's parent pointers
++ if (x.getLeft(index) != null) {
++ x.getLeft(index).setParent(x, index);
++ }
++
++ if (x.getRight(index) != null) {
++ x.getRight(index).setParent(x, index);
++ }
++
++ if (y.getLeft(index) != null) {
++ y.getLeft(index).setParent(y, index);
++ }
++
++ if (y.getRight(index) != null) {
++ y.getRight(index).setParent(y, index);
++ }
++
++ x.swapColors(y, index);
++
++ // Check if root changed
++ if (rootNode[index] == x) {
++ rootNode[index] = y;
++ } else if (rootNode[index] == y) {
++ rootNode[index] = x;
++ }
++ }
++
++ /**
++ * check if an object is fit to be proper input ... has to be
++ * Comparable and non-null
++ *
++ * @param o the object being checked
++ * @throws NullPointerException if o is null
++ * @throws ClassCastException if o is not Comparable
++ */
++ private static void checkNonNullComparable(final Object o) {
++ if (o == null) {
++ throw new NullPointerException("Cannot be null");
++ }
++ if (!(o instanceof Comparable)) {
++ throw new ClassCastException("Must be Comparable");
++ }
++ }
++
++ /**
++ * check a key for validity (non-null and implements Comparable)
++ *
++ * @param key the key to be checked
++ * @throws NullPointerException if key is null
++ * @throws ClassCastException if key is not Comparable
++ */
++ private static void checkKey(final Object key) {
++ checkNonNullComparable(key);
++ }
++
++ /**
++ * check a value for validity (non-null and implements Comparable)
++ *
++ * @param value the value to be checked
++ * @throws NullPointerException if value is null
++ * @throws ClassCastException if value is not Comparable
++ */
++ private static void checkValue(final Object value) {
++ checkNonNullComparable(value);
++ }
++
++ /**
++ * check a key and a value for validity (non-null and implements
++ * Comparable)
++ *
++ * @param key the key to be checked
++ * @param value the value to be checked
++ * @throws NullPointerException if key or value is null
++ * @throws ClassCastException if key or value is not Comparable
++ */
++ private static void checkKeyAndValue(final Object key, final Object value) {
++ checkKey(key);
++ checkValue(value);
++ }
++
++ /**
++ * increment the modification count -- used to check for
++ * concurrent modification of the map through the map and through
++ * an Iterator from one of its Set or Collection views
++ */
++ private void modify() {
++ modifications++;
++ }
++
++ /**
++ * bump up the size and note that the map has changed
++ */
++ private void grow() {
++ modify();
++ nodeCount++;
++ }
++
++ /**
++ * decrement the size and note that the map has changed
++ */
++ private void shrink() {
++ modify();
++ nodeCount--;
++ }
++
++ /**
++ * insert a node by its value
++ *
++ * @param newNode the node to be inserted
++ * @throws IllegalArgumentException if the node already exists
++ * in the value mapping
++ */
++ private void insertValue(final Node<K, V> newNode) throws IllegalArgumentException {
++ Node<K, V> node = rootNode[VALUE];
++
++ while (true) {
++ int cmp = compare(newNode.getData(VALUE), node.getData(VALUE));
++
++ if (cmp == 0) {
++ throw new IllegalArgumentException("Cannot store a duplicate value (\"" + newNode.getData(VALUE) + "\") in this Map");
++ } else if (cmp < 0) {
++ if (node.getLeft(VALUE) != null) {
++ node = node.getLeft(VALUE);
++ } else {
++ node.setLeft(newNode, VALUE);
++ newNode.setParent(node, VALUE);
++ doRedBlackInsert(newNode, VALUE);
++
++ break;
++ }
++ } else { // cmp > 0
++ if (node.getRight(VALUE) != null) {
++ node = node.getRight(VALUE);
++ } else {
++ node.setRight(newNode, VALUE);
++ newNode.setParent(node, VALUE);
++ doRedBlackInsert(newNode, VALUE);
++
++ break;
++ }
++ }
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Compares for equals as per the API.
++ *
++ * @param obj the object to compare to
++ * @return true if equal
++ */
++ private boolean doEquals(Object obj, final int type) {
++ if (obj == this) {
++ return true;
++ }
++ if (obj instanceof Map == false) {
++ return false;
++ }
++ Map other = (Map) obj;
++ if (other.size() != size()) {
++ return false;
++ }
++
++ if (nodeCount > 0) {
++ try {
++ for (MapIterator it = new ViewMapIterator(this, type); it.hasNext();) {
++ Object key = it.next();
++ Object value = it.getValue();
++ if (value.equals(other.get(key)) == false) {
++ return false;
++ }
++ }
++ } catch (ClassCastException ex) {
++ return false;
++ } catch (NullPointerException ex) {
++ return false;
++ }
++ }
++ return true;
++ }
++
++ /**
++ * Gets the hash code value for this map as per the API.
++ *
++ * @return the hash code value for this map
++ */
++ private int doHashCode(final int type) {
++ int total = 0;
++ if (nodeCount > 0) {
++ for (MapIterator it = new ViewMapIterator(this, type); it.hasNext();) {
++ Object key = it.next();
++ Object value = it.getValue();
++ total += (key.hashCode() ^ value.hashCode());
++ }
++ }
++ return total;
++ }
++
++ /**
++ * Gets the string form of this map as per AbstractMap.
++ *
++ * @return the string form of this map
++ */
++ private String doToString(final int type) {
++ if (nodeCount == 0) {
++ return "{}";
++ }
++ StringBuffer buf = new StringBuffer(nodeCount * 32);
++ buf.append('{');
++ MapIterator it = new ViewMapIterator(this, type);
++ boolean hasNext = it.hasNext();
++ while (hasNext) {
++ Object key = it.next();
++ Object value = it.getValue();
++ buf.append(key == this ? "(this Map)" : key).append('=').append(value == this ? "(this Map)" : value);
++
++ hasNext = it.hasNext();
++ if (hasNext) {
++ buf.append(", ");
++ }
++ }
++
++ buf.append('}');
++ return buf.toString();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * A view of this map.
++ */
++ static class View <K extends Comparable,V extends Comparable> extends AbstractSet {
++
++ /**
++ * The parent map.
++ */
++ protected final TreeBidiMap main;
++ /**
++ * Whether to return KEY or VALUE order.
++ */
++ protected final int orderType;
++ /**
++ * Whether to return KEY, VALUE, MAPENTRY or INVERSEMAPENTRY data.
++ */
++ protected final int dataType;
++
++ /**
++ * Constructor.
++ *
++ * @param main the main map
++ * @param orderType the KEY or VALUE int for the order
++ * @param dataType the KEY, VALUE, MAPENTRY or INVERSEMAPENTRY int
++ */
++ View(final TreeBidiMap main, final int orderType, final int dataType) {
++ super();
++ this.main = main;
++ this.orderType = orderType;
++ this.dataType = dataType;
++ }
++
++ public Iterator iterator() {
++ return new ViewIterator(main, orderType, dataType);
++ }
++
++ public int size() {
++ return main.size();
++ }
++
++ public boolean contains(final Object obj) {
++ checkNonNullComparable(obj);
++ return (main.lookup((Comparable) obj, dataType) != null);
++ }
++
++ public boolean remove(final Object obj) {
++ if (dataType == KEY) {
++ return main.doRemoveByKey((K) obj) != null;
++ } else {
++ return main.doRemoveByValue((V) obj) != null;
++ }
++ }
++
++ public void clear() {
++ main.clear();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * An iterator over the map.
++ */
++ static class ViewIterator implements OrderedIterator {
++
++ /**
++ * The parent map.
++ */
++ protected final TreeBidiMap main;
++ /**
++ * Whether to return KEY or VALUE order.
++ */
++ protected final int orderType;
++ /**
++ * Whether to return KEY, VALUE, MAPENTRY or INVERSEMAPENTRY data.
++ */
++ protected final int dataType;
++ /**
++ * The last node returned by the iterator.
++ */
++ protected Node lastReturnedNode;
++ /**
++ * The next node to be returned by the iterator.
++ */
++ protected Node nextNode;
++ /**
++ * The previous node in the sequence returned by the iterator.
++ */
++ protected Node previousNode;
++ /**
++ * The modification count.
++ */
++ private int expectedModifications;
++
++ /**
++ * Constructor.
++ *
++ * @param main the main map
++ * @param orderType the KEY or VALUE int for the order
++ * @param dataType the KEY, VALUE, MAPENTRY or INVERSEMAPENTRY int
++ */
++ ViewIterator(final TreeBidiMap main, final int orderType, final int dataType) {
++ super();
++ this.main = main;
++ this.orderType = orderType;
++ this.dataType = dataType;
++ expectedModifications = main.modifications;
++ nextNode = leastNode(main.rootNode[orderType], orderType);
++ lastReturnedNode = null;
++ previousNode = null;
++ }
++
++ public final boolean hasNext() {
++ return (nextNode != null);
++ }
++
++ public final Object next() {
++ if (nextNode == null) {
++ throw new NoSuchElementException();
++ }
++ if (main.modifications != expectedModifications) {
++ throw new ConcurrentModificationException();
++ }
++ lastReturnedNode = nextNode;
++ previousNode = nextNode;
++ nextNode = main.nextGreater(nextNode, orderType);
++ return doGetData();
++ }
++
++ public boolean hasPrevious() {
++ return (previousNode != null);
++ }
++
++ public Object previous() {
++ if (previousNode == null) {
++ throw new NoSuchElementException();
++ }
++ if (main.modifications != expectedModifications) {
++ throw new ConcurrentModificationException();
++ }
++ nextNode = lastReturnedNode;
++ if (nextNode == null) {
++ nextNode = main.nextGreater(previousNode, orderType);
++ }
++ lastReturnedNode = previousNode;
++ previousNode = main.nextSmaller(previousNode, orderType);
++ return doGetData();
++ }
++
++ /**
++ * Gets the data value for the lastReturnedNode field.
++ *
++ * @return the data value
++ */
++ protected Object doGetData() {
++ switch (dataType) {
++ case KEY:
++ return lastReturnedNode.getKey();
++ case VALUE:
++ return lastReturnedNode.getValue();
++ case MAPENTRY:
++ return lastReturnedNode;
++ case INVERSEMAPENTRY:
++ return new UnmodifiableMapEntry(lastReturnedNode.getValue(), lastReturnedNode.getKey());
++ }
++ return null;
++ }
++
++ public final void remove() {
++ if (lastReturnedNode == null) {
++ throw new IllegalStateException();
++ }
++ if (main.modifications != expectedModifications) {
++ throw new ConcurrentModificationException();
++ }
++ main.doRedBlackDelete(lastReturnedNode);
++ expectedModifications++;
++ lastReturnedNode = null;
++ if (nextNode == null) {
++ previousNode = main.greatestNode(main.rootNode[orderType], orderType);
++ } else {
++ previousNode = main.nextSmaller(nextNode, orderType);
++ }
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * An iterator over the map.
++ */
++ static class ViewMapIterator extends ViewIterator implements OrderedMapIterator {
++
++ private final int oppositeType;
++
++ /**
++ * Constructor.
++ *
++ * @param main the main map
++ * @param orderType the KEY or VALUE int for the order
++ */
++ ViewMapIterator(final TreeBidiMap main, final int orderType) {
++ super(main, orderType, orderType);
++ this.oppositeType = oppositeIndex(dataType);
++ }
++
++ public Object getKey() {
++ if (lastReturnedNode == null) {
++ throw new IllegalStateException("Iterator getKey() can only be called after next() and before remove()");
++ }
++ return lastReturnedNode.getData(dataType);
++ }
++
++ public Object getValue() {
++ if (lastReturnedNode == null) {
++ throw new IllegalStateException("Iterator getValue() can only be called after next() and before remove()");
++ }
++ return lastReturnedNode.getData(oppositeType);
++ }
++
++ public Object setValue(final Object obj) {
++ throw new UnsupportedOperationException();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * A view of this map.
++ */
++ static class EntryView extends View {
++
++ private final int oppositeType;
++
++ /**
++ * Constructor.
++ *
++ * @param main the main map
++ * @param orderType the KEY or VALUE int for the order
++ * @param dataType the MAPENTRY or INVERSEMAPENTRY int for the returned data
++ */
++ EntryView(final TreeBidiMap main, final int orderType, final int dataType) {
++ super(main, orderType, dataType);
++ this.oppositeType = main.oppositeIndex(orderType);
++ }
++
++ public boolean contains(Object obj) {
++ if (obj instanceof Map.Entry == false) {
++ return false;
++ }
++ Map.Entry entry = (Map.Entry) obj;
++ Object value = entry.getValue();
++ Node node = main.lookup((Comparable) entry.getKey(), orderType);
++ return (node != null && node.getData(oppositeType).equals(value));
++ }
++
++ public boolean remove(Object obj) {
++ if (obj instanceof Map.Entry == false) {
++ return false;
++ }
++ Map.Entry entry = (Map.Entry) obj;
++ Object value = entry.getValue();
++ Node node = main.lookup((Comparable) entry.getKey(), orderType);
++ if (node != null && node.getData(oppositeType).equals(value)) {
++ main.doRedBlackDelete(node);
++ return true;
++ }
++ return false;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * A node used to store the data.
++ */
++ static class Node <K extends Comparable,V extends Comparable> implements Map.Entry<K, V>, KeyValue<K, V> {
++
++ private K key;
++ private V value;
++ private Node<K, V>[] leftNode;
++ private Node<K, V>[] rightNode;
++ private Node<K, V>[] parentNode;
++ private boolean[] blackColor;
++ private int hashcodeValue;
++ private boolean calculatedHashCode;
++
++ /**
++ * Make a new cell with given key and value, and with null
++ * links, and black (true) colors.
++ *
++ * @param key
++ * @param value
++ */
++ Node(final K key, final V value) {
++ super();
++ this.key = key;
++ this.value = value;
++ leftNode = new Node[2];
++ rightNode = new Node[2];
++ parentNode = new Node[2];
++ blackColor = new boolean[]{true, true};
++ calculatedHashCode = false;
++ }
++
++ /**
++ * Get the specified data.
++ *
++ * @param index the KEY or VALUE int
++ * @return the key or value
++ */
++ private Comparable getData(final int index) {
++ if (index == KEY) {
++ return key;
++ } else {
++ return value;
++ }
++ }
++
++ /**
++ * Set this node's left node.
++ *
++ * @param node the new left node
++ * @param index the KEY or VALUE int
++ */
++ private void setLeft(final Node<K, V> node, final int index) {
++ leftNode[index] = node;
++ }
++
++ /**
++ * Get the left node.
++ *
++ * @param index the KEY or VALUE int
++ * @return the left node, may be null
++ */
++ private Node<K, V> getLeft(final int index) {
++ return leftNode[index];
++ }
++
++ /**
++ * Set this node's right node.
++ *
++ * @param node the new right node
++ * @param index the KEY or VALUE int
++ */
++ private void setRight(final Node<K, V> node, final int index) {
++ rightNode[index] = node;
++ }
++
++ /**
++ * Get the right node.
++ *
++ * @param index the KEY or VALUE int
++ * @return the right node, may be null
++ */
++ private Node<K, V> getRight(final int index) {
++ return rightNode[index];
++ }
++
++ /**
++ * Set this node's parent node.
++ *
++ * @param node the new parent node
++ * @param index the KEY or VALUE int
++ */
++ private void setParent(final Node<K, V> node, final int index) {
++ parentNode[index] = node;
++ }
++
++ /**
++ * Get the parent node.
++ *
++ * @param index the KEY or VALUE int
++ * @return the parent node, may be null
++ */
++ private Node<K, V> getParent(final int index) {
++ return parentNode[index];
++ }
++
++ /**
++ * Exchange colors with another node.
++ *
++ * @param node the node to swap with
++ * @param index the KEY or VALUE int
++ */
++ private void swapColors(final Node<K, V> node, final int index) {
++ // Swap colors -- old hacker's trick
++ blackColor[index] ^= node.blackColor[index];
++ node.blackColor[index] ^= blackColor[index];
++ blackColor[index] ^= node.blackColor[index];
++ }
++
++ /**
++ * Is this node black?
++ *
++ * @param index the KEY or VALUE int
++ * @return true if black (which is represented as a true boolean)
++ */
++ private boolean isBlack(final int index) {
++ return blackColor[index];
++ }
++
++ /**
++ * Is this node red?
++ *
++ * @param index the KEY or VALUE int
++ * @return true if non-black
++ */
++ private boolean isRed(final int index) {
++ return !blackColor[index];
++ }
++
++ /**
++ * Make this node black.
++ *
++ * @param index the KEY or VALUE int
++ */
++ private void setBlack(final int index) {
++ blackColor[index] = true;
++ }
++
++ /**
++ * Make this node red.
++ *
++ * @param index the KEY or VALUE int
++ */
++ private void setRed(final int index) {
++ blackColor[index] = false;
++ }
++
++ /**
++ * Make this node the same color as another
++ *
++ * @param node the node whose color we're adopting
++ * @param index the KEY or VALUE int
++ */
++ private void copyColor(final Node<K, V> node, final int index) {
++ blackColor[index] = node.blackColor[index];
++ }
++
++ //-------------------------------------------------------------------
++ /**
++ * Gets the key.
++ *
++ * @return the key corresponding to this entry.
++ */
++ public K getKey() {
++ return key;
++ }
++
++ /**
++ * Gets the value.
++ *
++ * @return the value corresponding to this entry.
++ */
++ public V getValue() {
++ return value;
++ }
++
++ /**
++ * Optional operation that is not permitted in this implementation
++ *
++ * @param ignored
++ * @return does not return
++ * @throws UnsupportedOperationException always
++ */
++ public V setValue(final V ignored) throws UnsupportedOperationException {
++ throw new UnsupportedOperationException("Map.Entry.setValue is not supported");
++ }
++
++ /**
++ * Compares the specified object with this entry for equality.
++ * Returns true if the given object is also a map entry and
++ * the two entries represent the same mapping.
++ *
++ * @param obj the object to be compared for equality with this entry.
++ * @return true if the specified object is equal to this entry.
++ */
++ public boolean equals(final Object obj) {
++ if (obj == this) {
++ return true;
++ }
++ if (!(obj instanceof Map.Entry)) {
++ return false;
++ }
++ Map.Entry e = (Map.Entry) obj;
++ return key.equals(e.getKey()) && value.equals(e.getValue());
++ }
++
++ /**
++ * @return the hash code value for this map entry.
++ */
++ public int hashCode() {
++ if (!calculatedHashCode) {
++ hashcodeValue = key.hashCode() ^ value.hashCode();
++ calculatedHashCode = true;
++ }
++ return hashcodeValue;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * A node used to store the data.
++ */
++ static class Inverse <K extends Comparable,V extends Comparable> implements OrderedBidiMap<V, K> {
++
++ /**
++ * The parent map.
++ */
++ private final TreeBidiMap<K, V> main;
++ /**
++ * Store the keySet once created.
++ */
++ private Set keySet;
++ /**
++ * Store the valuesSet once created.
++ */
++ private Set valuesSet;
++ /**
++ * Store the entrySet once created.
++ */
++ private Set entrySet;
++
++ /**
++ * Constructor.
++ *
++ * @param main the main map
++ */
++ Inverse(final TreeBidiMap<K, V> main) {
++ super();
++ this.main = main;
++ }
++
++ public int size() {
++ return main.size();
++ }
++
++ public boolean isEmpty() {
++ return main.isEmpty();
++ }
++
++ public K get(final Object key) {
++ return main.getKey((V) key);
++ }
++
++ public V getKey(final Object value) {
++ return main.get(value);
++ }
++
++ public boolean containsKey(final Object key) {
++ return main.containsValue(key);
++ }
++
++ public boolean containsValue(final Object value) {
++ return main.containsKey(value);
++ }
++
++ public V firstKey() {
++ if (main.nodeCount == 0) {
++ throw new NoSuchElementException("Map is empty");
++ }
++ return main.leastNode(main.rootNode[VALUE], VALUE).getValue();
++ }
++
++ public V lastKey() {
++ if (main.nodeCount == 0) {
++ throw new NoSuchElementException("Map is empty");
++ }
++ return main.greatestNode(main.rootNode[VALUE], VALUE).getValue();
++ }
++
++ public V nextKey(V key) {
++ checkKey(key);
++ Node<K, V> node = main.nextGreater(main.lookup((Comparable) key, VALUE), VALUE);
++ return (node == null ? null : node.getValue());
++ }
++
++ public V previousKey(V key) {
++ checkKey(key);
++ Node<K, V> node = main.nextSmaller(main.lookup((Comparable) key, VALUE), VALUE);
++ return (node == null ? null : node.getValue());
++ }
++
++ public K put(final V key, final K value) {
++ return main.doPutByValue(value, key);
++ }
++
++ public void putAll(Map<? extends V, ? extends K> map) {
++ Iterator it = map.entrySet().iterator();
++ while (it.hasNext()) {
++ Map.Entry entry = (Map.Entry) it.next();
++ put((V) entry.getKey(), (K) entry.getValue());
++ }
++ }
++
++ public K remove(final Object key) {
++ return main.removeValue((V) key);
++ }
++
++ public V removeValue(final Object value) {
++ return main.remove(value);
++ }
++
++ public void clear() {
++ main.clear();
++ }
++
++ public Set<V> keySet() {
++ if (keySet == null) {
++ keySet = new View(main, VALUE, VALUE);
++ }
++ return keySet;
++ }
++
++ public Set<K> values() {
++ if (valuesSet == null) {
++ valuesSet = new View(main, VALUE, KEY);
++ }
++ return valuesSet;
++ }
++
++ public Set<Map.Entry<V, K>> entrySet() {
++ if (entrySet == null) {
++ return new EntryView(main, VALUE, INVERSEMAPENTRY);
++ }
++ return entrySet;
++ }
++
++ public MapIterator<V, K> mapIterator() {
++ if (isEmpty()) {
++ return EmptyOrderedMapIterator.INSTANCE;
++ }
++ return new ViewMapIterator(main, VALUE);
++ }
++
++ public OrderedMapIterator<V, K> orderedMapIterator() {
++ if (isEmpty()) {
++ return EmptyOrderedMapIterator.INSTANCE;
++ }
++ return new ViewMapIterator(main, VALUE);
++ }
++
++ public BidiMap<K, V> inverseBidiMap() {
++ return main;
++ }
++
++ public OrderedBidiMap<K, V> inverseOrderedBidiMap() {
++ return main;
++ }
++
++ public boolean equals(Object obj) {
++ return main.doEquals(obj, VALUE);
++ }
++
++ public int hashCode() {
++ return main.doHashCode(VALUE);
++ }
++
++ public String toString() {
++ return main.doToString(VALUE);
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bidimap/UnmodifiableBidiMap.java
+@@ -0,0 +1,120 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bidimap;
++
++import org.apache.commons.collections15.BidiMap;
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.Unmodifiable;
++import org.apache.commons.collections15.iterators.UnmodifiableMapIterator;
++import org.apache.commons.collections15.map.UnmodifiableEntrySet;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * Decorates another <code>BidiMap</code> to ensure it can't be altered.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableBidiMap <K,V> extends AbstractBidiMapDecorator<K, V> implements Unmodifiable {
++
++ /**
++ * The inverse unmodifiable map
++ */
++ private UnmodifiableBidiMap<V, K> inverse;
++
++ /**
++ * Factory method to create an unmodifiable map.
++ * <p/>
++ * If the map passed in is already unmodifiable, it is returned.
++ *
++ * @param map the map to decorate, must not be null
++ * @return an unmodifiable BidiMap
++ * @throws IllegalArgumentException if map is null
++ */
++ public static <K,V> BidiMap<K, V> decorate(BidiMap<K, V> map) {
++ if (map instanceof Unmodifiable) {
++ return map;
++ }
++ return new UnmodifiableBidiMap<K, V>(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ private UnmodifiableBidiMap(BidiMap<K, V> map) {
++ super(map);
++ }
++
++ //-----------------------------------------------------------------------
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public V put(K key, V value) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void putAll(Map<? extends K, ? extends V> mapToCopy) {
++ throw new UnsupportedOperationException();
++ }
++
++ public V remove(Object key) {
++ throw new UnsupportedOperationException();
++ }
++
++ public Set<Map.Entry<K, V>> entrySet() {
++ Set<Map.Entry<K, V>> set = super.entrySet();
++ return UnmodifiableEntrySet.decorate(set);
++ }
++
++ public Set<K> keySet() {
++ Set<K> set = super.keySet();
++ return UnmodifiableSet.decorate(set);
++ }
++
++ public Set<V> values() {
++ Set<V> coll = super.values();
++ return (Set<V>) UnmodifiableSet.decorate(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ public K removeValue(Object value) {
++ throw new UnsupportedOperationException();
++ }
++
++ public MapIterator<K, V> mapIterator() {
++ MapIterator<K, V> it = getBidiMap().mapIterator();
++ return UnmodifiableMapIterator.decorate(it);
++ }
++
++ public BidiMap<V, K> inverseBidiMap() {
++ if (inverse == null) {
++ inverse = new UnmodifiableBidiMap<V, K>(getBidiMap().inverseBidiMap());
++ inverse.inverse = this;
++ }
++ return inverse;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bidimap/UnmodifiableOrderedBidiMap.java
+@@ -0,0 +1,127 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bidimap;
++
++import org.apache.commons.collections15.*;
++import org.apache.commons.collections15.iterators.UnmodifiableOrderedMapIterator;
++import org.apache.commons.collections15.map.UnmodifiableEntrySet;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * Decorates another <code>OrderedBidiMap</code> to ensure it can't be altered.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableOrderedBidiMap <K,V> extends AbstractOrderedBidiMapDecorator<K, V> implements Unmodifiable {
++
++ /**
++ * The inverse unmodifiable map
++ */
++ private UnmodifiableOrderedBidiMap<V, K> inverse;
++
++ /**
++ * Factory method to create an unmodifiable map.
++ * <p/>
++ * If the map passed in is already unmodifiable, it is returned.
++ *
++ * @param map the map to decorate, must not be null
++ * @return an unmodifiable OrderedBidiMap
++ * @throws IllegalArgumentException if map is null
++ */
++ public static <K,V> OrderedBidiMap<K, V> decorate(OrderedBidiMap<K, V> map) {
++ if (map instanceof Unmodifiable) {
++ return map;
++ }
++ return new UnmodifiableOrderedBidiMap<K, V>(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ private UnmodifiableOrderedBidiMap(OrderedBidiMap<K, V> map) {
++ super(map);
++ }
++
++ //-----------------------------------------------------------------------
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public V put(K key, V value) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void putAll(Map<? extends K, ? extends V> mapToCopy) {
++ throw new UnsupportedOperationException();
++ }
++
++ public V remove(Object key) {
++ throw new UnsupportedOperationException();
++ }
++
++ public Set<Map.Entry<K, V>> entrySet() {
++ Set<Map.Entry<K, V>> set = super.entrySet();
++ return UnmodifiableEntrySet.decorate(set);
++ }
++
++ public Set<K> keySet() {
++ Set<K> set = super.keySet();
++ return UnmodifiableSet.decorate(set);
++ }
++
++ public Set<V> values() {
++ Set<V> coll = super.values();
++ return UnmodifiableSet.decorate(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ public K removeValue(Object value) {
++ throw new UnsupportedOperationException();
++ }
++
++ public MapIterator<K, V> mapIterator() {
++ return orderedMapIterator();
++ }
++
++ public BidiMap<V, K> inverseBidiMap() {
++ return inverseOrderedBidiMap();
++ }
++
++ //-----------------------------------------------------------------------
++ public OrderedMapIterator<K, V> orderedMapIterator() {
++ OrderedMapIterator<K, V> it = getOrderedBidiMap().orderedMapIterator();
++ return UnmodifiableOrderedMapIterator.decorate(it);
++ }
++
++ public OrderedBidiMap<V, K> inverseOrderedBidiMap() {
++ if (inverse == null) {
++ inverse = new UnmodifiableOrderedBidiMap<V, K>(getOrderedBidiMap().inverseOrderedBidiMap());
++ inverse.inverse = this;
++ }
++ return inverse;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bidimap/UnmodifiableSortedBidiMap.java
+@@ -0,0 +1,149 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.bidimap;
++
++import org.apache.commons.collections15.*;
++import org.apache.commons.collections15.iterators.UnmodifiableOrderedMapIterator;
++import org.apache.commons.collections15.map.UnmodifiableEntrySet;
++import org.apache.commons.collections15.map.UnmodifiableSortedMap;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++import java.util.Map;
++import java.util.Set;
++import java.util.SortedMap;
++
++/**
++ * Decorates another <code>SortedBidiMap</code> to ensure it can't be altered.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableSortedBidiMap <K,V> extends AbstractSortedBidiMapDecorator<K, V> implements Unmodifiable {
++
++ /**
++ * The inverse unmodifiable map
++ */
++ private UnmodifiableSortedBidiMap<V, K> inverse;
++
++ /**
++ * Factory method to create an unmodifiable map.
++ * <p/>
++ * If the map passed in is already unmodifiable, it is returned.
++ *
++ * @param map the map to decorate, must not be null
++ * @return an unmodifiable SortedBidiMap
++ * @throws IllegalArgumentException if map is null
++ */
++ public static <K,V> SortedBidiMap<K, V> decorate(SortedBidiMap<K, V> map) {
++ if (map instanceof Unmodifiable) {
++ return map;
++ }
++ return new UnmodifiableSortedBidiMap<K, V>(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ private UnmodifiableSortedBidiMap(SortedBidiMap<K, V> map) {
++ super(map);
++ }
++
++ //-----------------------------------------------------------------------
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public V put(K key, V value) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void putAll(Map<? extends K, ? extends V> mapToCopy) {
++ throw new UnsupportedOperationException();
++ }
++
++ public V remove(Object key) {
++ throw new UnsupportedOperationException();
++ }
++
++ public Set<Map.Entry<K, V>> entrySet() {
++ Set<Map.Entry<K, V>> set = super.entrySet();
++ return UnmodifiableEntrySet.decorate(set);
++ }
++
++ public Set<K> keySet() {
++ Set<K> set = super.keySet();
++ return UnmodifiableSet.decorate(set);
++ }
++
++ public Set<V> values() {
++ Set<V> coll = super.values();
++ return UnmodifiableSet.decorate(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ public K removeValue(Object value) {
++ throw new UnsupportedOperationException();
++ }
++
++ public MapIterator<K, V> mapIterator() {
++ return orderedMapIterator();
++ }
++
++ public BidiMap<V, K> inverseBidiMap() {
++ return inverseSortedBidiMap();
++ }
++
++ //-----------------------------------------------------------------------
++ public OrderedMapIterator<K, V> orderedMapIterator() {
++ OrderedMapIterator<K, V> it = getSortedBidiMap().orderedMapIterator();
++ return UnmodifiableOrderedMapIterator.decorate(it);
++ }
++
++ public OrderedBidiMap<V, K> inverseOrderedBidiMap() {
++ return inverseSortedBidiMap();
++ }
++
++ //-----------------------------------------------------------------------
++ public SortedBidiMap<V, K> inverseSortedBidiMap() {
++ if (inverse == null) {
++ inverse = new UnmodifiableSortedBidiMap<V, K>(getSortedBidiMap().inverseSortedBidiMap());
++ inverse.inverse = this;
++ }
++ return inverse;
++ }
++
++ public SortedMap<K, V> subMap(K fromKey, K toKey) {
++ SortedMap<K, V> sm = getSortedBidiMap().subMap(fromKey, toKey);
++ return UnmodifiableSortedMap.decorate(sm);
++ }
++
++ public SortedMap<K, V> headMap(K toKey) {
++ SortedMap<K, V> sm = getSortedBidiMap().headMap(toKey);
++ return UnmodifiableSortedMap.decorate(sm);
++ }
++
++ public SortedMap<K, V> tailMap(K fromKey) {
++ SortedMap<K, V> sm = getSortedBidiMap().tailMap(fromKey);
++ return UnmodifiableSortedMap.decorate(sm);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/bidimap/package.html
+@@ -0,0 +1,47 @@
++<!-- $Id: package.html,v 1.1 2005/10/11 17:05:19 pents90 Exp $ -->
++ <!--
++ Copyright 2003-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<BODY>
++<p>
++This package contains implementations of the
++{@link org.apache.commons.collections.BidiMap BidiMap},
++{@link org.apache.commons.collections.OrderedBidiMap OrderedBidiMap} and
++{@link org.apache.commons.collections.SortedBidiMap SortedBidiMap} interfaces.
++A BidiMap is an extension to Map that allows keys and values to be looked up with equal ease.
++One example usage is a system communicating to a legacy datasource that must convert codes
++from the new format to the old format and vice versa.
++<p>
++The following implementations are provided in the package:
++<ul>
++<li>DualHashBidiMap - uses two HashMaps to implement BidiMap
++<li>DualTreeBidiMap - uses two TreeMaps to implement SortedBidiMap
++<li>TreeBidiMap - red-black tree implementation of OrderedBidiMap
++</ul>
++<p>
++The following decorators are provided in the package:
++<ul>
++<li>Unmodifiable - ensures the map cannot be altered
++<!--
++<li>Synchronized - synchronizes method access for multi-threaded environments
++<li>Predicated - ensures that only elements that are valid according to a predicate can be added
++<li>Typed - ensures that only elements that are of a specific type can be added
++<li>Transformed - transforms each element added
++<li>FixedSize - ensures that the size of the map cannot change
++<li>Lazy - creates objects in the map on demand
++<li>ListOrdered - ensures that insertion order is retained-->
++</ul>
++</pre>
++</BODY>
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/buffer/AbstractBufferDecorator.java
+@@ -0,0 +1,70 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.buffer;
++
++import org.apache.commons.collections15.Buffer;
++import org.apache.commons.collections15.collection.AbstractCollectionDecorator;
++
++/**
++ * Decorates another <code>Buffer</code> to provide additional behaviour.
++ * <p/>
++ * Methods are forwarded directly to the decorated buffer.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractBufferDecorator <E> extends AbstractCollectionDecorator<E> implements Buffer<E> {
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ *
++ * @since Commons Collections 3.1
++ */
++ protected AbstractBufferDecorator() {
++ super();
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ protected AbstractBufferDecorator(Buffer<E> buffer) {
++ super(buffer);
++ }
++
++ /**
++ * Gets the buffer being decorated.
++ *
++ * @return the decorated buffer
++ */
++ protected Buffer<E> getBuffer() {
++ return (Buffer<E>) getCollection();
++ }
++
++ //-----------------------------------------------------------------------
++ public E get() {
++ return getBuffer().get();
++ }
++
++ public E remove() {
++ return getBuffer().remove();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/buffer/BlockingBuffer.java
+@@ -0,0 +1,118 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.buffer;
++
++import org.apache.commons.collections15.Buffer;
++import org.apache.commons.collections15.BufferUnderflowException;
++
++import java.util.Collection;
++
++/**
++ * Decorates another <code>Buffer</code> to make {@link #get()} and
++ * {@link #remove()} block when the <code>Buffer</code> is empty.
++ * <p/>
++ * If either <code>get</code> or <code>remove</code> is called on an empty
++ * <code>Buffer</code>, the calling thread waits for notification that
++ * an <code>add</code> or <code>addAll</code> operation has completed.
++ * <p/>
++ * When one or more entries are added to an empty <code>Buffer</code>,
++ * all threads blocked in <code>get</code> or <code>remove</code> are notified.
++ * There is no guarantee that concurrent blocked <code>get</code> or
++ * <code>remove</code> requests will be "unblocked" and receive data in the
++ * order that they arrive.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Janek Bogucki
++ * @author Matt Hall, John Watkinson, Phil Steitz
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public class BlockingBuffer <E> extends SynchronizedBuffer<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 1719328905017860541L;
++
++ /**
++ * Factory method to create a blocking buffer.
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @return a new blocking Buffer
++ * @throws IllegalArgumentException if buffer is null
++ */
++ public static <E> Buffer<E> decorate(Buffer<E> buffer) {
++ return new BlockingBuffer<E>(buffer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @throws IllegalArgumentException if the buffer is null
++ */
++ protected BlockingBuffer(Buffer<E> buffer) {
++ super(buffer);
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean add(E o) {
++ synchronized (lock) {
++ boolean result = collection.add(o);
++ notifyAll();
++ return result;
++ }
++ }
++
++ public boolean addAll(Collection<? extends E> c) {
++ synchronized (lock) {
++ boolean result = collection.addAll(c);
++ notifyAll();
++ return result;
++ }
++ }
++
++ public E get() {
++ synchronized (lock) {
++ while (collection.isEmpty()) {
++ try {
++ wait();
++ } catch (InterruptedException e) {
++ throw new BufferUnderflowException();
++ }
++ }
++ return getBuffer().get();
++ }
++ }
++
++ public E remove() {
++ synchronized (lock) {
++ while (collection.isEmpty()) {
++ try {
++ wait();
++ } catch (InterruptedException e) {
++ throw new BufferUnderflowException();
++ }
++ }
++ return getBuffer().remove();
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/buffer/BoundedFifoBuffer.java
+@@ -0,0 +1,363 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.buffer;
++
++import org.apache.commons.collections15.BoundedCollection;
++import org.apache.commons.collections15.Buffer;
++import org.apache.commons.collections15.BufferOverflowException;
++import org.apache.commons.collections15.BufferUnderflowException;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.*;
++
++/**
++ * 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.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Avalon
++ * @author Berin Loritsch
++ * @author Paul Jack
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Herve Quiroz
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0 (previously in main package v2.1)
++ */
++public class BoundedFifoBuffer <E> extends AbstractCollection<E> implements Buffer<E>, BoundedCollection<E>, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 5603722811189451017L;
++
++ private transient E[] elements;
++ private transient int start = 0;
++ private transient int end = 0;
++ private transient boolean 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");
++ }
++ elements = (E[]) new Object[size];
++ maxElements = 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<E> coll) {
++ this(coll.size());
++ addAll(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the buffer out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeInt(size());
++ for (Iterator it = iterator(); it.hasNext();) {
++ out.writeObject(it.next());
++ }
++ }
++
++ /**
++ * Read the buffer in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ elements = (E[]) new Object[maxElements];
++ int size = in.readInt();
++ for (int i = 0; i < size; i++) {
++ elements[i] = (E) in.readObject();
++ }
++ start = 0;
++ full = (size == maxElements);
++ if (full) {
++ end = 0;
++ } else {
++ end = size;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns the number of elements stored in the buffer.
++ *
++ * @return this buffer's size
++ */
++ public int size() {
++ int size = 0;
++
++ if (end < start) {
++ size = maxElements - start + end;
++ } else if (end == start) {
++ size = (full ? maxElements : 0);
++ } else {
++ size = end - 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() {
++ full = false;
++ start = 0;
++ end = 0;
++ Arrays.fill(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(E element) {
++ if (null == element) {
++ throw new NullPointerException("Attempted to add null object to buffer");
++ }
++
++ if (full) {
++ throw new BufferOverflowException("The buffer cannot hold more than " + maxElements + " objects.");
++ }
++
++ elements[end++] = element;
++
++ if (end >= maxElements) {
++ end = 0;
++ }
++
++ if (end == start) {
++ 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 E get() {
++ if (isEmpty()) {
++ throw new BufferUnderflowException("The buffer is already empty");
++ }
++
++ return elements[start];
++ }
++
++ /**
++ * Removes the least recently inserted element from this buffer.
++ *
++ * @return the least recently inserted element
++ * @throws BufferUnderflowException if the buffer is empty
++ */
++ public E remove() {
++ if (isEmpty()) {
++ throw new BufferUnderflowException("The buffer is already empty");
++ }
++
++ E element = elements[start];
++
++ if (null != element) {
++ elements[start++] = null;
++
++ if (start >= maxElements) {
++ start = 0;
++ }
++
++ 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<E> iterator() {
++ return new Iterator() {
++
++ private int index = start;
++ private int lastReturnedIndex = -1;
++ private boolean isFirst = full;
++
++ public boolean hasNext() {
++ return isFirst || (index != end);
++
++ }
++
++ public E next() {
++ if (!hasNext()) {
++ throw new NoSuchElementException();
++ }
++ isFirst = false;
++ lastReturnedIndex = index;
++ index = increment(index);
++ return elements[lastReturnedIndex];
++ }
++
++ public void remove() {
++ if (lastReturnedIndex == -1) {
++ throw new IllegalStateException();
++ }
++
++ // First element can be removed quickly
++ if (lastReturnedIndex == start) {
++ BoundedFifoBuffer.this.remove();
++ lastReturnedIndex = -1;
++ return;
++ }
++
++ // Other elements require us to shift the subsequent elements
++ int i = lastReturnedIndex + 1;
++ while (i != end) {
++ if (i >= maxElements) {
++ elements[i - 1] = elements[0];
++ i = 0;
++ } else {
++ elements[i - 1] = elements[i];
++ i++;
++ }
++ }
++
++ lastReturnedIndex = -1;
++ end = decrement(end);
++ elements[end] = null;
++ full = false;
++ index = decrement(index);
++ }
++
++ };
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/buffer/CircularFifoBuffer.java
+@@ -0,0 +1,97 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.buffer;
++
++import java.util.Collection;
++
++/**
++ * CircularFifoBuffer is a first in first out buffer with a fixed size that
++ * replaces its oldest element if full.
++ * <p/>
++ * The removal order of a <code>CircularFifoBuffer</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>CircularFifoBuffer</code>:
++ * <pre>
++ * Buffer fifo = BufferUtils.synchronizedBuffer(new CircularFifoBuffer());
++ * </pre>
++ * <p/>
++ * This buffer prevents null objects from being added.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stefano Fornari
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public class CircularFifoBuffer <E> extends BoundedFifoBuffer<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -8423413834657610406L;
++
++ /**
++ * Constructor that creates a buffer with the default size of 32.
++ */
++ public CircularFifoBuffer() {
++ super(32);
++ }
++
++ /**
++ * Constructor that creates a buffer with the specified size.
++ *
++ * @param size the size of the buffer (cannot be changed)
++ * @throws IllegalArgumentException if the size is less than 1
++ */
++ public CircularFifoBuffer(int size) {
++ super(size);
++ }
++
++ /**
++ * Constructor that creates a buffer from the specified collection.
++ * The collection size also sets the buffer size
++ *
++ * @param coll the collection to copy into the buffer, may not be null
++ * @throws NullPointerException if the collection is null
++ */
++ public CircularFifoBuffer(Collection<E> coll) {
++ super(coll);
++ }
++
++ /**
++ * If the buffer is full, the least recently added element is discarded so
++ * that a new element can be inserted.
++ *
++ * @param element the element to add
++ * @return true, always
++ */
++ public boolean add(E element) {
++ if (isFull()) {
++ remove();
++ }
++ return super.add(element);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/buffer/PredicatedBuffer.java
+@@ -0,0 +1,98 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.buffer;
++
++import org.apache.commons.collections15.Buffer;
++import org.apache.commons.collections15.Predicate;
++import org.apache.commons.collections15.collection.PredicatedCollection;
++
++/**
++ * Decorates another <code>Buffer</code> to validate that additions
++ * match a specified predicate.
++ * <p/>
++ * This buffer exists to provide validation for the decorated buffer.
++ * It is normally created to decorate an empty buffer.
++ * If an object cannot be added to the buffer, an IllegalArgumentException is thrown.
++ * <p/>
++ * One usage would be to ensure that no null entries are added to the buffer.
++ * <pre>Buffer buffer = PredicatedBuffer.decorate(new UnboundedFifoBuffer(), NotNullPredicate.INSTANCE);</pre>
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public class PredicatedBuffer <E> extends PredicatedCollection<E> implements Buffer<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 2307609000539943581L;
++
++ /**
++ * Factory method to create a predicated (validating) buffer.
++ * <p/>
++ * If there are any elements already in the buffer being decorated, they
++ * are validated.
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @return a new predicated Buffer
++ * @throws IllegalArgumentException if buffer or predicate is null
++ * @throws IllegalArgumentException if the buffer contains invalid elements
++ */
++ public static <E> Buffer<E> decorate(Buffer<E> buffer, Predicate<? super E> predicate) {
++ return new PredicatedBuffer(buffer, predicate);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the collection being decorated, they
++ * are validated.
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @throws IllegalArgumentException if buffer or predicate is null
++ * @throws IllegalArgumentException if the buffer contains invalid elements
++ */
++ protected PredicatedBuffer(Buffer<E> buffer, Predicate<? super E> predicate) {
++ super(buffer, predicate);
++ }
++
++ /**
++ * Gets the buffer being decorated.
++ *
++ * @return the decorated buffer
++ */
++ protected Buffer<E> getBuffer() {
++ return (Buffer<E>) getCollection();
++ }
++
++ //-----------------------------------------------------------------------
++ public E get() {
++ return getBuffer().get();
++ }
++
++ public E remove() {
++ return getBuffer().remove();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/buffer/PriorityBuffer.java
+@@ -0,0 +1,536 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.buffer;
++
++import org.apache.commons.collections15.Buffer;
++import org.apache.commons.collections15.BufferUnderflowException;
++
++import java.util.AbstractCollection;
++import java.util.Comparator;
++import java.util.Iterator;
++import java.util.NoSuchElementException;
++
++/**
++ * Binary heap implementation of <code>Buffer</code> that provides for
++ * removal based on <code>Comparator</code> ordering.
++ * <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 #remove()} method always returns the first element as determined
++ * by the sort order. (The <code>ascendingOrder</code> flag in the constructors
++ * can be used to reverse the sort order, in which case {@link #remove()}
++ * 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 #add(Object)} and {@link #remove()} operations perform
++ * in logarithmic time. The {@link #get()} operation performs in constant
++ * time. All other operations perform in linear time or worse.
++ * <p/>
++ * Note that this implementation is not synchronized. Use
++ * {@link org.apache.commons.collections15.BufferUtils#synchronizedBuffer(Buffer)} or
++ * {@link org.apache.commons.collections15.buffer.SynchronizedBuffer#decorate(Buffer)}
++ * to provide synchronized access to a <code>PriorityBuffer</code>:
++ * <p/>
++ * <pre>
++ * Buffer heap = SynchronizedBuffer.decorate(new PriorityBuffer());
++ * </pre>
++ *
++ * @author Peter Donald
++ * @author Ram Chidambaram
++ * @author Michael A. Smith
++ * @author Paul Jack
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0 (previously BinaryHeap v1.0)
++ */
++public class PriorityBuffer <E> extends AbstractCollection<E> implements Buffer<E> {
++
++ /**
++ * The default capacity for the buffer.
++ */
++ private static final int DEFAULT_CAPACITY = 13;
++
++ /**
++ * The elements in this buffer.
++ */
++ protected E[] elements;
++ /**
++ * The number of elements currently in this buffer.
++ */
++ protected int size;
++ /**
++ * 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.
++ */
++ protected boolean ascendingOrder;
++ /**
++ * The comparator used to order the elements
++ */
++ protected Comparator<? super E> comparator;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructs a new empty buffer that sorts in ascending order by the
++ * natural order of the objects added.
++ */
++ public PriorityBuffer() {
++ this(DEFAULT_CAPACITY, true, null);
++ }
++
++ /**
++ * Constructs a new empty buffer that sorts in ascending order using the
++ * specified comparator.
++ *
++ * @param comparator the comparator used to order the elements,
++ * null means use natural order
++ */
++ public PriorityBuffer(Comparator<? super E> comparator) {
++ this(DEFAULT_CAPACITY, true, comparator);
++ }
++
++ /**
++ * Constructs a new empty buffer specifying the sort order and using the
++ * natural order of the objects added.
++ *
++ * @param ascendingOrder if <code>true</code> the heap is created as a
++ * minimum heap; otherwise, the heap is created as a maximum heap
++ */
++ public PriorityBuffer(boolean ascendingOrder) {
++ this(DEFAULT_CAPACITY, ascendingOrder, null);
++ }
++
++ /**
++ * Constructs a new empty buffer specifying the sort order and comparator.
++ *
++ * @param ascendingOrder 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 PriorityBuffer(boolean ascendingOrder, Comparator<? super E> comparator) {
++ this(DEFAULT_CAPACITY, ascendingOrder, comparator);
++ }
++
++ /**
++ * Constructs a new empty buffer that sorts in ascending order by the
++ * natural order of the objects added, specifying an initial capacity.
++ *
++ * @param capacity the initial capacity for the buffer, greater than zero
++ * @throws IllegalArgumentException if <code>capacity</code> is <= <code>0</code>
++ */
++ public PriorityBuffer(int capacity) {
++ this(capacity, true, null);
++ }
++
++ /**
++ * Constructs a new empty buffer that sorts in ascending order using the
++ * specified comparator and initial capacity.
++ *
++ * @param capacity the initial capacity for the buffer, greater than zero
++ * @param comparator the comparator used to order the elements,
++ * null means use natural order
++ * @throws IllegalArgumentException if <code>capacity</code> is <= <code>0</code>
++ */
++ public PriorityBuffer(int capacity, Comparator<? super E> comparator) {
++ this(capacity, true, comparator);
++ }
++
++ /**
++ * Constructs a new empty buffer that specifying initial capacity and
++ * sort order, using the natural order of the objects added.
++ *
++ * @param capacity the initial capacity for the buffer, greater than zero
++ * @param ascendingOrder 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><= 0</code>
++ */
++ public PriorityBuffer(int capacity, boolean ascendingOrder) {
++ this(capacity, ascendingOrder, null);
++ }
++
++ /**
++ * Constructs a new empty buffer that specifying initial capacity,
++ * sort order and comparator.
++ *
++ * @param capacity the initial capacity for the buffer, greater than zero
++ * @param ascendingOrder 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><= 0</code>
++ */
++ public PriorityBuffer(int capacity, boolean ascendingOrder, Comparator<? super E> comparator) {
++ super();
++ if (capacity <= 0) {
++ throw new IllegalArgumentException("invalid capacity");
++ }
++ this.ascendingOrder = ascendingOrder;
++
++ //+1 as 0 is noop
++ this.elements = (E[]) new Object[capacity + 1];
++ this.comparator = comparator;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Checks whether the heap is ascending or descending order.
++ *
++ * @return true if ascending order (a min heap)
++ */
++ public boolean isAscendingOrder() {
++ return ascendingOrder;
++ }
++
++ /**
++ * Gets the comparator being used for this buffer, null is natural order.
++ *
++ * @return the comparator in use, null is natural order
++ */
++ public Comparator<? super E> comparator() {
++ return comparator;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns the number of elements in this buffer.
++ *
++ * @return the number of elements in this buffer
++ */
++ public int size() {
++ return size;
++ }
++
++ /**
++ * Clears all elements from the buffer.
++ */
++ public void clear() {
++ elements = (E[]) new Object[elements.length]; // for gc
++ size = 0;
++ }
++
++ /**
++ * Adds an element to the buffer.
++ * <p/>
++ * The element added will be sorted according to the comparator in use.
++ *
++ * @param element the element to be added
++ * @return true always
++ */
++ public boolean add(E element) {
++ if (isAtCapacity()) {
++ grow();
++ }
++ // percolate element to it's place in tree
++ if (ascendingOrder) {
++ percolateUpMinHeap(element);
++ } else {
++ percolateUpMaxHeap(element);
++ }
++ return true;
++ }
++
++ /**
++ * Gets the next element to be removed without actually removing it (peek).
++ *
++ * @return the next element
++ * @throws BufferUnderflowException if the buffer is empty
++ */
++ public E get() {
++ if (isEmpty()) {
++ throw new BufferUnderflowException();
++ } else {
++ return elements[1];
++ }
++ }
++
++ /**
++ * Gets and removes the next element (pop).
++ *
++ * @return the next element
++ * @throws BufferUnderflowException if the buffer is empty
++ */
++ public E remove() {
++ final E result = get();
++ elements[1] = elements[size--];
++
++ // set the unused element to 'null' so that the garbage collector
++ // can free the object if not used anywhere else.(remove reference)
++ elements[size + 1] = null;
++
++ if (size != 0) {
++ // percolate top element to it's place in tree
++ if (ascendingOrder) {
++ percolateDownMinHeap(1);
++ } else {
++ percolateDownMaxHeap(1);
++ }
++ }
++
++ return result;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Tests if the buffer is at capacity.
++ *
++ * @return <code>true</code> if buffer is full; <code>false</code> otherwise.
++ */
++ protected boolean isAtCapacity() {
++ //+1 as element 0 is noop
++ return elements.length == size + 1;
++ }
++
++
++ /**
++ * 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 E element = elements[index];
++ int hole = index;
++
++ while ((hole * 2) <= 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 != size && compare(elements[child + 1], elements[child]) < 0) {
++ child++;
++ }
++
++ // if we found resting place of bubble then terminate search
++ if (compare(elements[child], element) >= 0) {
++ break;
++ }
++
++ elements[hole] = elements[child];
++ hole = child;
++ }
++
++ 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 E element = elements[index];
++ int hole = index;
++
++ while ((hole * 2) <= 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 != size && compare(elements[child + 1], elements[child]) > 0) {
++ child++;
++ }
++
++ // if we found resting place of bubble then terminate search
++ if (compare(elements[child], element) <= 0) {
++ break;
++ }
++
++ elements[hole] = elements[child];
++ hole = child;
++ }
++
++ 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;
++ E element = elements[hole];
++ while (hole > 1 && compare(element, elements[hole / 2]) < 0) {
++ // save element that is being pushed down
++ // as the element "bubble" is percolated up
++ final int next = hole / 2;
++ elements[hole] = elements[next];
++ hole = next;
++ }
++ 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 E element) {
++ elements[++size] = element;
++ percolateUpMinHeap(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;
++ E element = elements[hole];
++
++ while (hole > 1 && compare(element, elements[hole / 2]) > 0) {
++ // save element that is being pushed down
++ // as the element "bubble" is percolated up
++ final int next = hole / 2;
++ elements[hole] = elements[next];
++ hole = next;
++ }
++
++ 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 E element) {
++ elements[++size] = element;
++ percolateUpMaxHeap(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
++ */
++ protected int compare(E a, E b) {
++ if (comparator != null) {
++ return comparator.compare(a, b);
++ } else {
++ return ((Comparable) a).compareTo(b);
++ }
++ }
++
++ /**
++ * Increases the size of the heap to support additional elements
++ */
++ protected void grow() {
++ final E[] array = (E[]) new Object[elements.length * 2];
++ System.arraycopy(elements, 0, array, 0, elements.length);
++ elements = array;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns an iterator over this heap's elements.
++ *
++ * @return an iterator over this heap's elements
++ */
++ public Iterator<E> iterator() {
++ return new Iterator<E>() {
++
++ private int index = 1;
++ private int lastReturnedIndex = -1;
++
++ public boolean hasNext() {
++ return index <= size;
++ }
++
++ public E next() {
++ if (!hasNext()) {
++ throw new NoSuchElementException();
++ }
++ lastReturnedIndex = index;
++ index++;
++ return elements[lastReturnedIndex];
++ }
++
++ public void remove() {
++ if (lastReturnedIndex == -1) {
++ throw new IllegalStateException();
++ }
++ elements[lastReturnedIndex] = elements[size];
++ elements[size] = null;
++ size--;
++ if (size != 0 && lastReturnedIndex <= size) {
++ int compareToParent = 0;
++ if (lastReturnedIndex > 1) {
++ compareToParent = compare(elements[lastReturnedIndex], elements[lastReturnedIndex / 2]);
++ }
++ if (ascendingOrder) {
++ 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;
++ }
++
++ };
++ }
++
++ /**
++ * Returns a string representation of this heap. The returned string
++ * is similar to those produced by standard JDK collections15.
++ *
++ * @return a string representation of this heap
++ */
++ public String toString() {
++ final StringBuffer sb = new StringBuffer();
++
++ sb.append("[ ");
++
++ for (int i = 1; i < size + 1; i++) {
++ if (i != 1) {
++ sb.append(", ");
++ }
++ sb.append(elements[i]);
++ }
++
++ sb.append(" ]");
++
++ return sb.toString();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/buffer/SynchronizedBuffer.java
+@@ -0,0 +1,96 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.buffer;
++
++import org.apache.commons.collections15.Buffer;
++import org.apache.commons.collections15.collection.SynchronizedCollection;
++
++/**
++ * Decorates another <code>Buffer</code> to synchronize its behaviour
++ * for a multi-threaded environment.
++ * <p/>
++ * Methods are synchronized, then forwarded to the decorated buffer.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public class SynchronizedBuffer <E> extends SynchronizedCollection<E> implements Buffer<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -6859936183953626253L;
++
++ /**
++ * Factory method to create a synchronized buffer.
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @return a new synchronized Buffer
++ * @throws IllegalArgumentException if buffer is null
++ */
++ public static <E> Buffer<E> decorate(Buffer<E> buffer) {
++ return new SynchronizedBuffer(buffer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @throws IllegalArgumentException if the buffer is null
++ */
++ protected SynchronizedBuffer(Buffer<E> buffer) {
++ super(buffer);
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @param lock the lock object to use, must not be null
++ * @throws IllegalArgumentException if the buffer is null
++ */
++ protected SynchronizedBuffer(Buffer<E> buffer, Object lock) {
++ super(buffer, lock);
++ }
++
++ /**
++ * Gets the buffer being decorated.
++ *
++ * @return the decorated buffer
++ */
++ protected Buffer<E> getBuffer() {
++ return (Buffer<E>) collection;
++ }
++
++ //-----------------------------------------------------------------------
++ public E get() {
++ synchronized (lock) {
++ return getBuffer().get();
++ }
++ }
++
++ public E remove() {
++ synchronized (lock) {
++ return getBuffer().remove();
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/buffer/TransformedBuffer.java
+@@ -0,0 +1,94 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.buffer;
++
++import org.apache.commons.collections15.Buffer;
++import org.apache.commons.collections15.Transformer;
++import org.apache.commons.collections15.collection.TransformedCollection;
++
++/**
++ * Decorates another <code>Buffer</code> to transform objects that are added.
++ * <p/>
++ * The add methods are affected by this class.
++ * Thus objects must be removed or searched for using their transformed form.
++ * For example, if the transformation converts Strings to Integers, you must
++ * use the Integer form to remove objects.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ * <p>
++ * Note: This class cannot support generics without breaking the Collection contract.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public class TransformedBuffer <I,O> extends TransformedCollection<I, O> implements Buffer {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -7901091318986132033L;
++
++ /**
++ * Factory method to create a transforming buffer.
++ * <p/>
++ * If there are any elements already in the buffer being decorated, they
++ * are NOT transformed.
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @return a new transformed Buffer
++ * @throws IllegalArgumentException if buffer or transformer is null
++ */
++ public static <I,O> Buffer<O> decorate(Buffer<I> buffer, Transformer<? super I, ? extends O> transformer) {
++ return new TransformedBuffer<I, O>(buffer, transformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the buffer being decorated, they
++ * are NOT transformed.
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @throws IllegalArgumentException if buffer or transformer is null
++ */
++ protected TransformedBuffer(Buffer<I> buffer, Transformer<? super I, ? extends O> transformer) {
++ super(buffer, transformer);
++ }
++
++ /**
++ * Gets the decorated buffer.
++ *
++ * @return the decorated buffer
++ */
++ protected Buffer<O> getBuffer() {
++ return (Buffer<O>) collection;
++ }
++
++ //-----------------------------------------------------------------------
++ public Object get() {
++ return getBuffer().get();
++ }
++
++ public Object remove() {
++ return getBuffer().remove();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/buffer/TypedBuffer.java
+@@ -0,0 +1,60 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.buffer;
++
++import org.apache.commons.collections15.Buffer;
++import org.apache.commons.collections15.functors.InstanceofPredicate;
++
++/**
++ * Decorates another <code>Buffer</code> to validate that elements added
++ * are of a specific type.
++ * <p/>
++ * The validation of additions is performed via an instanceof test against
++ * a specified <code>Class</code>. If an object cannot be added to the
++ * collection, an IllegalArgumentException is thrown.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @author Matthew Hawthorne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public class TypedBuffer <E> {
++
++ /**
++ * Factory method to create a typed list.
++ * <p/>
++ * If there are any elements already in the buffer being decorated, they
++ * are validated.
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @param type the type to allow into the buffer, must not be null
++ * @return a new typed Buffer
++ * @throws IllegalArgumentException if buffer or type is null
++ * @throws IllegalArgumentException if the buffer contains invalid elements
++ */
++ public static <E> Buffer<E> decorate(Buffer<E> buffer, Class type) {
++ return new PredicatedBuffer<E>(buffer, InstanceofPredicate.getInstance(type));
++ }
++
++ /**
++ * Restrictive constructor.
++ */
++ protected TypedBuffer() {
++ super();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/buffer/UnboundedFifoBuffer.java
+@@ -0,0 +1,334 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.buffer;
++
++import org.apache.commons.collections15.Buffer;
++import org.apache.commons.collections15.BufferUnderflowException;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++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.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Avalon
++ * @author Federico Barbieri
++ * @author Berin Loritsch
++ * @author Paul Jack
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0 (previously in main package v2.1)
++ */
++public class UnboundedFifoBuffer <E> extends AbstractCollection<E> implements Buffer<E>, Serializable {
++
++ /**
++ * Serialization vesrion
++ */
++ private static final long serialVersionUID = -3482960336579541419L;
++
++ /**
++ * The array of objects in the buffer.
++ */
++ protected transient E[] buffer;
++ /**
++ * The current head index.
++ */
++ protected transient int head;
++ /**
++ * The current tail index.
++ */
++ protected transient int tail;
++
++ /**
++ * Constructs an UnboundedFifoBuffer with the default number of elements.
++ * It is exactly the same as performing the following:
++ * <p/>
++ * <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");
++ }
++ buffer = (E[]) new Object[initialSize + 1];
++ head = 0;
++ tail = 0;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the buffer out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeInt(size());
++ for (Iterator it = iterator(); it.hasNext();) {
++ out.writeObject(it.next());
++ }
++ }
++
++ /**
++ * Read the buffer in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ int size = in.readInt();
++ buffer = (E[]) new Object[size];
++ for (int i = 0; i < size; i++) {
++ buffer[i] = (E) in.readObject();
++ }
++ head = 0;
++ tail = size;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns the number of elements stored in the buffer.
++ *
++ * @return this buffer's size
++ */
++ public int size() {
++ int size = 0;
++
++ if (tail < head) {
++ size = buffer.length - head + tail;
++ } else {
++ size = tail - 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
++ */
++ public boolean add(final E obj) {
++ if (obj == null) {
++ throw new NullPointerException("Attempted to add null object to buffer");
++ }
++
++ if (size() + 1 >= buffer.length) {
++ E[] tmp = (E[]) new Object[((buffer.length - 1) * 2) + 1];
++
++ int j = 0;
++ for (int i = head; i != tail;) {
++ tmp[j] = buffer[i];
++ buffer[i] = null;
++
++ j++;
++ i++;
++ if (i == buffer.length) {
++ i = 0;
++ }
++ }
++
++ buffer = tmp;
++ head = 0;
++ tail = j;
++ }
++
++ buffer[tail] = obj;
++ tail++;
++ if (tail >= buffer.length) {
++ 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 E get() {
++ if (isEmpty()) {
++ throw new BufferUnderflowException("The buffer is already empty");
++ }
++
++ return buffer[head];
++ }
++
++ /**
++ * Removes the next object from the buffer
++ *
++ * @return the removed object
++ * @throws BufferUnderflowException if this buffer is empty
++ */
++ public E remove() {
++ if (isEmpty()) {
++ throw new BufferUnderflowException("The buffer is already empty");
++ }
++
++ E element = buffer[head];
++
++ if (null != element) {
++ buffer[head] = null;
++
++ head++;
++ if (head >= buffer.length) {
++ 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 >= 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 = buffer.length - 1;
++ }
++ return index;
++ }
++
++ /**
++ * Returns an iterator over this buffer's elements.
++ *
++ * @return an iterator over this buffer's elements
++ */
++ public Iterator<E> iterator() {
++ return new Iterator<E>() {
++
++ private int index = head;
++ private int lastReturnedIndex = -1;
++
++ public boolean hasNext() {
++ return index != tail;
++
++ }
++
++ public E next() {
++ if (!hasNext()) {
++ throw new NoSuchElementException();
++ }
++ lastReturnedIndex = index;
++ index = increment(index);
++ return buffer[lastReturnedIndex];
++ }
++
++ public void remove() {
++ if (lastReturnedIndex == -1) {
++ throw new IllegalStateException();
++ }
++
++ // First element can be removed quickly
++ if (lastReturnedIndex == head) {
++ UnboundedFifoBuffer.this.remove();
++ lastReturnedIndex = -1;
++ return;
++ }
++
++ // Other elements require us to shift the subsequent elements
++ int i = lastReturnedIndex + 1;
++ while (i != tail) {
++ if (i >= buffer.length) {
++ buffer[i - 1] = buffer[0];
++ i = 0;
++ } else {
++ buffer[i - 1] = buffer[i];
++ i++;
++ }
++ }
++
++ lastReturnedIndex = -1;
++ tail = decrement(tail);
++ buffer[tail] = null;
++ index = decrement(index);
++ }
++
++ };
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/buffer/UnmodifiableBuffer.java
+@@ -0,0 +1,131 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.buffer;
++
++import org.apache.commons.collections15.Buffer;
++import org.apache.commons.collections15.Unmodifiable;
++import org.apache.commons.collections15.iterators.UnmodifiableIterator;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Iterator;
++
++/**
++ * Decorates another <code>Buffer</code> to ensure it can't be altered.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableBuffer <E> extends AbstractBufferDecorator<E> implements Unmodifiable, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 1832948656215393357L;
++
++ /**
++ * Factory method to create an unmodifiable buffer.
++ * <p/>
++ * If the buffer passed in is already unmodifiable, it is returned.
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @return an unmodifiable Buffer
++ * @throws IllegalArgumentException if buffer is null
++ */
++ public static <E> Buffer<E> decorate(Buffer<E> buffer) {
++ if (buffer instanceof Unmodifiable) {
++ return buffer;
++ }
++ return new UnmodifiableBuffer<E>(buffer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param buffer the buffer to decorate, must not be null
++ * @throws IllegalArgumentException if buffer is null
++ */
++ private UnmodifiableBuffer(Buffer<E> buffer) {
++ super(buffer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the collection out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(collection);
++ }
++
++ /**
++ * Read the collection in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ collection = (Collection<E>) in.readObject();
++ }
++
++ //-----------------------------------------------------------------------
++ public Iterator<E> iterator() {
++ return UnmodifiableIterator.decorate(getCollection().iterator());
++ }
++
++ public boolean add(E object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean remove(Object object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ //-----------------------------------------------------------------------
++ public E remove() {
++ throw new UnsupportedOperationException();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/buffer/package.html
+@@ -0,0 +1,40 @@
++<!-- $Id: package.html,v 1.1 2005/10/11 17:05:20 pents90 Exp $ -->
++ <!--
++ Copyright 2003-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<BODY>
++<p>
++This package contains implementations of the
++{@link org.apache.commons.collections.Buffer Buffer} interface.
++<p>
++The following implementations are provided in the package:
++<ul>
++<li>PriorityBuffer - provides for removal based on a comparator ordering
++<li>BoundedFifoBuffer - implements a buffer with a fixed size that throws exceptions when full
++<li>CircularFifoBuffer - implements a buffer with a fixed size that discards oldest when full
++<li>UnboundedFifoBuffer - implements a buffer that grows in size if necessary
++</ul>
++<p>
++The following decorators are provided in the package:
++<ul>
++<li>Synchronized - synchronizes method access for multi-threaded environments
++<li>Unmodifiable - ensures the collection cannot be altered
++<li>Predicated - ensures that only elements that are valid according to a predicate can be added
++<li>Typed - ensures that only elements that are of a specific type can be added
++<li>Transformed - transforms elements added to the buffer
++<li>Blocking - blocks on get and remove until an element is available
++</ul>
++</pre>
++</BODY>
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/collection/AbstractCollectionDecorator.java
+@@ -0,0 +1,148 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.collection;
++
++import java.util.Collection;
++import java.util.Iterator;
++
++/**
++ * Decorates another <code>Collection</code> to provide additional behaviour.
++ * <p/>
++ * Each method call made on this <code>Collection</code> is forwarded to the
++ * decorated <code>Collection</code>. This class is used as a framework on which
++ * to build to extensions such as synchronized and unmodifiable behaviour. The
++ * main advantage of decoration is that one decorator can wrap any implementation
++ * of <code>Collection</code>, whereas sub-classing requires a new class to be
++ * written for each implementation.
++ * <p/>
++ * This implementation does not perform any special processing with
++ * {@link #iterator()}. Instead it simply returns the value from the
++ * wrapped collection. This may be undesirable, for example if you are trying
++ * to write an unmodifiable implementation it might provide a loophole.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractCollectionDecorator <E> implements Collection<E> {
++
++ /**
++ * The collection being decorated
++ */
++ protected Collection<E> collection;
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ *
++ * @since Commons Collections 3.1
++ */
++ protected AbstractCollectionDecorator() {
++ super();
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param coll the collection to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ protected AbstractCollectionDecorator(Collection<E> coll) {
++ if (coll == null) {
++ throw new IllegalArgumentException("Collection must not be null");
++ }
++ this.collection = coll;
++ }
++
++ /**
++ * Gets the collection being decorated.
++ *
++ * @return the decorated collection
++ */
++ protected Collection<E> getCollection() {
++ return collection;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean add(E object) {
++ return collection.add(object);
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ return collection.addAll(coll);
++ }
++
++ public void clear() {
++ collection.clear();
++ }
++
++ public boolean contains(Object object) {
++ return collection.contains(object);
++ }
++
++ public boolean isEmpty() {
++ return collection.isEmpty();
++ }
++
++ public Iterator<E> iterator() {
++ return collection.iterator();
++ }
++
++ public boolean remove(Object object) {
++ return collection.remove(object);
++ }
++
++ public int size() {
++ return collection.size();
++ }
++
++ public Object[] toArray() {
++ return (Object[]) collection.toArray();
++ }
++
++ public <T> T[] toArray(T[] object) {
++ return (T[]) collection.toArray(object);
++ }
++
++ public boolean containsAll(Collection<?> coll) {
++ return collection.containsAll(coll);
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ return collection.removeAll(coll);
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ return collection.retainAll(coll);
++ }
++
++ public boolean equals(Object object) {
++ if (object == this) {
++ return true;
++ }
++ return collection.equals(object);
++ }
++
++ public int hashCode() {
++ return collection.hashCode();
++ }
++
++ public String toString() {
++ return collection.toString();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/collection/AbstractSerializableCollectionDecorator.java
+@@ -0,0 +1,69 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.collection;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++
++/**
++ * Serializable subclass of AbstractCollectionDecorator.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @since Commons Collections 3.1
++ */
++public abstract class AbstractSerializableCollectionDecorator <E> extends AbstractCollectionDecorator<E> implements Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 6249888059822088500L;
++
++ /**
++ * Constructor.
++ */
++ protected AbstractSerializableCollectionDecorator(Collection<E> coll) {
++ super(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the collection out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(collection);
++ }
++
++ /**
++ * Read the collection in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ collection = (Collection<E>) in.readObject();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/collection/CompositeCollection.java
+@@ -0,0 +1,444 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.collection;
++
++import org.apache.commons.collections15.iterators.EmptyIterator;
++import org.apache.commons.collections15.iterators.IteratorChain;
++import org.apache.commons.collections15.list.UnmodifiableList;
++
++import java.lang.reflect.Array;
++import java.util.ArrayList;
++import java.util.Arrays;
++import java.util.Collection;
++import java.util.Iterator;
++
++/**
++ * Decorates a collection of other collections15 to provide a single unified view.
++ * <p/>
++ * Changes made to this collection will actually be made on the decorated collection.
++ * Add and remove operations require the use of a pluggable strategy. If no
++ * strategy is provided then add and remove are unsupported.
++ *
++ * @author Brian McCallister
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Phil Steitz
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public class CompositeCollection <E> implements Collection<E> {
++
++ /**
++ * CollectionMutator to handle changes to the collection
++ */
++ protected CollectionMutator<E> mutator;
++
++ /**
++ * Collections in the composite
++ */
++ protected Collection<E>[] all;
++
++ /**
++ * Create an empty CompositeCollection.
++ */
++ public CompositeCollection() {
++ super();
++ this.all = new Collection[0];
++ }
++
++ /**
++ * Create a Composite Collection with only coll composited.
++ *
++ * @param coll a collection to decorate
++ */
++ public CompositeCollection(Collection<E> coll) {
++ this();
++ this.addComposited(coll);
++ }
++
++ /**
++ * Create a CompositeCollection with colls as the initial list of
++ * composited collections15.
++ *
++ * @param colls a variable number of collections15 to decorate
++ */
++ public CompositeCollection(Collection<E>... colls) {
++ this();
++ this.addComposited(colls);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the size of this composite collection.
++ * <p/>
++ * This implementation calls <code>size()</code> on each collection.
++ *
++ * @return total number of elements in all contained containers
++ */
++ public int size() {
++ int size = 0;
++ for (int i = this.all.length - 1; i >= 0; i--) {
++ size += this.all[i].size();
++ }
++ return size;
++ }
++
++ /**
++ * Checks whether this composite collection is empty.
++ * <p/>
++ * This implementation calls <code>isEmpty()</code> on each collection.
++ *
++ * @return true if all of the contained collections15 are empty
++ */
++ public boolean isEmpty() {
++ for (int i = this.all.length - 1; i >= 0; i--) {
++ if (this.all[i].isEmpty() == false) {
++ return false;
++ }
++ }
++ return true;
++ }
++
++ /**
++ * Checks whether this composite collection contains the object.
++ * <p/>
++ * This implementation calls <code>contains()</code> on each collection.
++ *
++ * @param obj the object to search for
++ * @return true if obj is contained in any of the contained collections15
++ */
++ public boolean contains(Object obj) {
++ for (int i = this.all.length - 1; i >= 0; i--) {
++ if (this.all[i].contains(obj)) {
++ return true;
++ }
++ }
++ return false;
++ }
++
++ /**
++ * Gets an iterator over all the collections15 in this composite.
++ * <p/>
++ * This implementation uses an <code>IteratorChain</code>.
++ *
++ * @return an <code>IteratorChain</code> instance which supports
++ * <code>remove()</code>. Iteration occurs over contained collections15 in
++ * the order they were added, but this behavior should not be relied upon.
++ * @see IteratorChain
++ */
++ public Iterator<E> iterator() {
++ if (this.all.length == 0) {
++ return EmptyIterator.INSTANCE;
++ }
++ IteratorChain<E> chain = new IteratorChain<E>();
++ for (int i = 0; i < this.all.length; ++i) {
++ chain.addIterator(this.all[i].iterator());
++ }
++ return chain;
++ }
++
++ /**
++ * Returns an array containing all of the elements in this composite.
++ *
++ * @return an object array of all the elements in the collection
++ */
++ public E[] toArray() {
++ final E[] result = (E[]) new Object[this.size()];
++ int i = 0;
++ for (Iterator<E> it = this.iterator(); it.hasNext(); i++) {
++ result[i] = (E) it.next();
++ }
++ return result;
++ }
++
++ /**
++ * Returns an object array, populating the supplied array if possible.
++ * See <code>Collection</code> interface for full details.
++ *
++ * @param array the array to use, populating if possible
++ * @return an array of all the elements in the collection
++ */
++
++ public <E> E[] toArray(E[] array) {
++ int size = this.size();
++ E[] result = null;
++ if (array.length >= size) {
++ result = array;
++ } else {
++ result = (E[]) Array.newInstance(array.getClass().getComponentType(), size);
++ }
++
++ int offset = 0;
++ for (int i = 0; i < this.all.length; ++i) {
++ for (Iterator it = this.all[i].iterator(); it.hasNext();) {
++ result[offset++] = (E) it.next();
++ }
++ }
++ if (result.length > size) {
++ result[size] = null;
++ }
++ return result;
++ }
++
++ /**
++ * Adds an object to the collection, throwing UnsupportedOperationException
++ * unless a CollectionMutator strategy is specified.
++ *
++ * @param obj the object to add
++ * @return true if the collection was modified
++ * @throws UnsupportedOperationException if CollectionMutator hasn't been set
++ * @throws UnsupportedOperationException if add is unsupported
++ * @throws ClassCastException if the object cannot be added due to its type
++ * @throws NullPointerException if the object cannot be added because its null
++ * @throws IllegalArgumentException if the object cannot be added
++ */
++ public boolean add(E obj) {
++ if (this.mutator == null) {
++ throw new UnsupportedOperationException("add() is not supported on CompositeCollection without a CollectionMutator strategy");
++ }
++ return this.mutator.add(this, this.all, obj);
++ }
++
++ /**
++ * Removes an object from the collection, throwing UnsupportedOperationException
++ * unless a CollectionMutator strategy is specified.
++ *
++ * @param obj the object being removed
++ * @return true if the collection is changed
++ * @throws UnsupportedOperationException if removed is unsupported
++ * @throws ClassCastException if the object cannot be removed due to its type
++ * @throws NullPointerException if the object cannot be removed because its null
++ * @throws IllegalArgumentException if the object cannot be removed
++ */
++ public boolean remove(Object obj) {
++ if (this.mutator == null) {
++ throw new UnsupportedOperationException("remove() is not supported on CompositeCollection without a CollectionMutator strategy");
++ }
++ return this.mutator.remove(this, this.all, obj);
++ }
++
++ /**
++ * Checks whether this composite contains all the elements in the specified collection.
++ * <p/>
++ * This implementation calls <code>contains()</code> for each element in the
++ * specified collection.
++ *
++ * @param coll the collection to check for
++ * @return true if all elements contained
++ */
++ public boolean containsAll(Collection<?> coll) {
++ for (Iterator it = coll.iterator(); it.hasNext();) {
++ if (this.contains(it.next()) == false) {
++ return false;
++ }
++ }
++ return true;
++ }
++
++ /**
++ * Adds a collection of elements to this collection, throwing
++ * UnsupportedOperationException unless a CollectionMutator strategy is specified.
++ *
++ * @param coll the collection to add
++ * @return true if the collection was modified
++ * @throws UnsupportedOperationException if CollectionMutator hasn't been set
++ * @throws UnsupportedOperationException if add is unsupported
++ * @throws ClassCastException if the object cannot be added due to its type
++ * @throws NullPointerException if the object cannot be added because its null
++ * @throws IllegalArgumentException if the object cannot be added
++ */
++ public boolean addAll(Collection<? extends E> coll) {
++ if (this.mutator == null) {
++ throw new UnsupportedOperationException("addAll() is not supported on CompositeCollection without a CollectionMutator strategy");
++ }
++ return this.mutator.addAll(this, this.all, coll);
++ }
++
++ /**
++ * Removes the elements in the specified collection from this composite collection.
++ * <p/>
++ * This implementation calls <code>removeAll</code> on each collection.
++ *
++ * @param coll the collection to remove
++ * @return true if the collection was modified
++ * @throws UnsupportedOperationException if removeAll is unsupported
++ */
++ public boolean removeAll(Collection<?> coll) {
++ if (coll.size() == 0) {
++ return false;
++ }
++ boolean changed = false;
++ for (int i = this.all.length - 1; i >= 0; i--) {
++ changed = (this.all[i].removeAll(coll) || changed);
++ }
++ return changed;
++ }
++
++ /**
++ * Retains all the elements in the specified collection in this composite collection,
++ * removing all others.
++ * <p/>
++ * This implementation calls <code>retainAll()</code> on each collection.
++ *
++ * @param coll the collection to remove
++ * @return true if the collection was modified
++ * @throws UnsupportedOperationException if retainAll is unsupported
++ */
++ public boolean retainAll(final Collection<?> coll) {
++ boolean changed = false;
++ for (int i = this.all.length - 1; i >= 0; i--) {
++ changed = (this.all[i].retainAll(coll) || changed);
++ }
++ return changed;
++ }
++
++ /**
++ * Removes all of the elements from this collection .
++ * <p/>
++ * This implementation calls <code>clear()</code> on each collection.
++ *
++ * @throws UnsupportedOperationException if clear is unsupported
++ */
++ public void clear() {
++ for (int i = 0; i < this.all.length; ++i) {
++ this.all[i].clear();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Specify a CollectionMutator strategy instance to handle changes.
++ *
++ * @param mutator the mutator to use
++ */
++ public void setMutator(CollectionMutator<E> mutator) {
++ this.mutator = mutator;
++ }
++
++ /**
++ * Add these Collections to the list of collections15 in this composite
++ *
++ * @param comps Collections to be appended to the composite
++ */
++ public void addComposited(Collection<? extends E>... comps) {
++ ArrayList list = new ArrayList(Arrays.asList(this.all));
++ list.addAll(Arrays.asList(comps));
++ all = (Collection<E>[]) list.toArray(new Collection[list.size()]);
++ }
++
++ /**
++ * Add an additional collection to this composite.
++ *
++ * @param c the collection to add
++ */
++ public void addComposited(Collection<? extends E> c) {
++ this.addComposited(new Collection[]{c});
++ }
++
++ /**
++ * Add two additional collections15 to this composite.
++ *
++ * @deprecated Superceded by the variable argument implementation of addComposited()
++ * @param c the first collection to add
++ * @param d the second collection to add
++ */
++ public void addComposited(Collection<? extends E> c, Collection<? extends E> d) {
++ this.addComposited(new Collection[]{c, d});
++ }
++
++ /**
++ * Removes a collection from the those being decorated in this composite.
++ *
++ * @param coll collection to be removed
++ */
++ public void removeComposited(Collection<? extends E> coll) {
++ ArrayList list = new ArrayList(this.all.length);
++ list.addAll(Arrays.asList(this.all));
++ list.remove(coll);
++ this.all = (Collection<E>[]) list.toArray(new Collection[list.size()]);
++ }
++
++ /**
++ * Returns a new collection containing all of the elements
++ *
++ * @return A new ArrayList containing all of the elements in this composite.
++ * The new collection is <i>not</i> backed by this composite.
++ */
++ public Collection<E> toCollection() {
++ return new ArrayList<E>(this);
++ }
++
++ /**
++ * Gets the collections15 being decorated.
++ *
++ * @return Unmodifiable collection of all collections15 in this composite.
++ */
++ public Collection<Collection<E>> getCollections() {
++ return UnmodifiableList.decorate(Arrays.asList(this.all));
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Pluggable strategy to handle changes to the composite.
++ */
++ public interface CollectionMutator <E> {
++
++ /**
++ * Called when an object is to be added to the composite.
++ *
++ * @param composite the CompositeCollection being changed
++ * @param collections all of the Collection instances in this CompositeCollection
++ * @param obj the object being added
++ * @return true if the collection is changed
++ * @throws UnsupportedOperationException if add is unsupported
++ * @throws ClassCastException if the object cannot be added due to its type
++ * @throws NullPointerException if the object cannot be added because its null
++ * @throws IllegalArgumentException if the object cannot be added
++ */
++ public boolean add(CompositeCollection<? extends E> composite, Collection<? extends E>[] collections, Object obj);
++
++ /**
++ * Called when a collection is to be added to the composite.
++ *
++ * @param composite the CompositeCollection being changed
++ * @param collections all of the Collection instances in this CompositeCollection
++ * @param coll the collection being added
++ * @return true if the collection is changed
++ * @throws UnsupportedOperationException if add is unsupported
++ * @throws ClassCastException if the object cannot be added due to its type
++ * @throws NullPointerException if the object cannot be added because its null
++ * @throws IllegalArgumentException if the object cannot be added
++ */
++ public boolean addAll(CompositeCollection<? extends E> composite, Collection<? extends E>[] collections, Collection<? extends E> coll);
++
++ /**
++ * Called when an object is to be removed to the composite.
++ *
++ * @param composite the CompositeCollection being changed
++ * @param collections all of the Collection instances in this CompositeCollection
++ * @param obj the object being removed
++ * @return true if the collection is changed
++ * @throws UnsupportedOperationException if removed is unsupported
++ * @throws ClassCastException if the object cannot be removed due to its type
++ * @throws NullPointerException if the object cannot be removed because its null
++ * @throws IllegalArgumentException if the object cannot be removed
++ */
++ public boolean remove(CompositeCollection<? extends E> composite, Collection<? extends E>[] collections, Object obj);
++
++ }
++
++}
++
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/collection/PredicatedCollection.java
+@@ -0,0 +1,138 @@
++// GenericsNotes: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.collection;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.util.Collection;
++import java.util.Iterator;
++
++/**
++ * Decorates another <code>Collection</code> to validate that additions
++ * match a specified predicate.
++ * <p/>
++ * This collection exists to provide validation for the decorated collection.
++ * It is normally created to decorate an empty collection.
++ * If an object cannot be added to the collection, an IllegalArgumentException is thrown.
++ * <p/>
++ * One usage would be to ensure that no null entries are added to the collection.
++ * <pre>Collection coll = PredicatedCollection.decorate(new ArrayList(), NotNullPredicate.INSTANCE);</pre>
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public class PredicatedCollection <E> extends AbstractSerializableCollectionDecorator<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -5259182142076705162L;
++
++ /**
++ * The predicate to use
++ */
++ protected final Predicate<? super E> predicate;
++
++ /**
++ * Factory method to create a predicated (validating) collection.
++ * <p/>
++ * If there are any elements already in the collection being decorated, they
++ * are validated.
++ *
++ * @param coll the collection to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @return a new predicated collection
++ * @throws IllegalArgumentException if collection or predicate is null
++ * @throws IllegalArgumentException if the collection contains invalid elements
++ */
++ public static <E> Collection<E> decorate(Collection<E> coll, Predicate<? super E> predicate) {
++ return new PredicatedCollection(coll, predicate);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the collection being decorated, they
++ * are validated.
++ *
++ * @param coll the collection to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @throws IllegalArgumentException if collection or predicate is null
++ * @throws IllegalArgumentException if the collection contains invalid elements
++ */
++ protected PredicatedCollection(Collection<E> coll, Predicate<? super E> predicate) {
++ super(coll);
++ if (predicate == null) {
++ throw new IllegalArgumentException("Predicate must not be null");
++ }
++ this.predicate = predicate;
++ for (Iterator<E> it = coll.iterator(); it.hasNext();) {
++ validate(it.next());
++ }
++ }
++
++ /**
++ * Validates the object being added to ensure it matches the predicate.
++ * <p/>
++ * The predicate itself should not throw an exception, but return false to
++ * indicate that the object cannot be added.
++ *
++ * @param object the object being added
++ * @throws IllegalArgumentException if the add is invalid
++ */
++ protected void validate(E object) {
++ if (predicate.evaluate(object) == false) {
++ throw new IllegalArgumentException("Cannot add Object '" + object + "' - Predicate rejected it");
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Override to validate the object being added to ensure it matches
++ * the predicate.
++ *
++ * @param object the object being added
++ * @return the result of adding to the underlying collection
++ * @throws IllegalArgumentException if the add is invalid
++ */
++ public boolean add(E object) {
++ validate(object);
++ return getCollection().add(object);
++ }
++
++ /**
++ * Override to validate the objects being added to ensure they match
++ * the predicate. If any one fails, no update is made to the underlying
++ * collection.
++ *
++ * @param coll the collection being added
++ * @return the result of adding to the underlying collection
++ * @throws IllegalArgumentException if the add is invalid
++ */
++ public boolean addAll(Collection<? extends E> coll) {
++ for (Iterator<? extends E> it = coll.iterator(); it.hasNext();) {
++ validate(it.next());
++ }
++ return getCollection().addAll(coll);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/collection/SynchronizedCollection.java
+@@ -0,0 +1,206 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.collection;
++
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Iterator;
++
++/**
++ * Decorates another <code>Collection</code> to synchronize its behaviour
++ * for a multi-threaded environment.
++ * <p/>
++ * Iterators must be manually synchronized:
++ * <pre>
++ * synchronized (coll) {
++ * Iterator it = coll.iterator();
++ * // do stuff with iterator
++ * }
++ * </pre>
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public class SynchronizedCollection <E> implements Collection<E>, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 2412805092710877986L;
++
++ /**
++ * The collection to decorate
++ */
++ protected final Collection<E> collection;
++ /**
++ * The object to lock on, needed for List/SortedSet views
++ */
++ protected final Object lock;
++
++ /**
++ * Factory method to create a synchronized collection.
++ *
++ * @param coll the collection to decorate, must not be null
++ * @return a new synchronized collection
++ * @throws IllegalArgumentException if collection is null
++ */
++ public static <E> Collection<E> decorate(Collection<E> coll) {
++ return new SynchronizedCollection<E>(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param collection the collection to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ protected SynchronizedCollection(Collection<E> collection) {
++ if (collection == null) {
++ throw new IllegalArgumentException("Collection must not be null");
++ }
++ this.collection = collection;
++ this.lock = this;
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param collection the collection to decorate, must not be null
++ * @param lock the lock object to use, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ protected SynchronizedCollection(Collection<E> collection, Object lock) {
++ if (collection == null) {
++ throw new IllegalArgumentException("Collection must not be null");
++ }
++ this.collection = collection;
++ this.lock = lock;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean add(E object) {
++ synchronized (lock) {
++ return collection.add(object);
++ }
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ synchronized (lock) {
++ return collection.addAll(coll);
++ }
++ }
++
++ public void clear() {
++ synchronized (lock) {
++ collection.clear();
++ }
++ }
++
++ public boolean contains(Object object) {
++ synchronized (lock) {
++ return collection.contains(object);
++ }
++ }
++
++ public boolean containsAll(Collection<?> coll) {
++ synchronized (lock) {
++ return collection.containsAll(coll);
++ }
++ }
++
++ public boolean isEmpty() {
++ synchronized (lock) {
++ return collection.isEmpty();
++ }
++ }
++
++ /**
++ * Iterators must be manually synchronized.
++ * <pre>
++ * synchronized (coll) {
++ * Iterator it = coll.iterator();
++ * // do stuff with iterator
++ * }
++ *
++ * @return an iterator that must be manually synchronized on the collection
++ */
++ public Iterator<E> iterator() {
++ return collection.iterator();
++ }
++
++ public Object[] toArray() {
++ synchronized (lock) {
++ return collection.toArray();
++ }
++ }
++
++ public <T> T[] toArray(T[] object) {
++ synchronized (lock) {
++ return collection.toArray(object);
++ }
++ }
++
++ public boolean remove(Object object) {
++ synchronized (lock) {
++ return collection.remove(object);
++ }
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ synchronized (lock) {
++ return collection.removeAll(coll);
++ }
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ synchronized (lock) {
++ return collection.retainAll(coll);
++ }
++ }
++
++ public int size() {
++ synchronized (lock) {
++ return collection.size();
++ }
++ }
++
++ public boolean equals(Object object) {
++ synchronized (lock) {
++ if (object == this) {
++ return true;
++ }
++ return collection.equals(object);
++ }
++ }
++
++ public int hashCode() {
++ synchronized (lock) {
++ return collection.hashCode();
++ }
++ }
++
++ public String toString() {
++ synchronized (lock) {
++ return collection.toString();
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/collection/TransformedCollection.java
+@@ -0,0 +1,141 @@
++// GenericsNote: Converted, but unfortunately very little type-safety could be achieved without breaking Collection interface.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.collection;
++
++import org.apache.commons.collections15.Transformer;
++
++import java.util.ArrayList;
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.List;
++
++/**
++ * Decorates another <code>Collection</code> to transform objects that are added.
++ * <p/>
++ * The add methods are affected by this class.
++ * Thus objects must be removed or searched for using their transformed form.
++ * For example, if the transformation converts Strings to Integers, you must
++ * use the Integer form to remove objects.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ * <p>
++ * Note: This class cannot support generics without breaking the Collection contract.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public class TransformedCollection <I,O> extends AbstractSerializableCollectionDecorator {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 8692300188161871514L;
++
++ /**
++ * The transformer to use
++ */
++ protected final Transformer<? super I, ? extends O> transformer;
++
++ /**
++ * Factory method to create a transforming collection.
++ * <p/>
++ * If there are any elements already in the collection being decorated, they
++ * are NOT transformed.
++ *
++ * @param coll the collection to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @return a new transformed collection
++ * @throws IllegalArgumentException if collection or transformer is null
++ */
++ public static <I,O> Collection<O> decorate(Collection<I> coll, Transformer<? super I, ? extends O> transformer) {
++ return new TransformedCollection<I, O>(coll, transformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the collection being decorated, they
++ * are NOT transformed.
++ *
++ * @param coll the collection to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @throws IllegalArgumentException if collection or transformer is null
++ */
++ protected TransformedCollection(Collection<I> coll, Transformer<? super I, ? extends O> transformer) {
++ super(coll);
++ if (transformer == null) {
++ throw new IllegalArgumentException("Transformer must not be null");
++ }
++ this.transformer = transformer;
++ }
++
++ /**
++ * Transforms an object.
++ * <p/>
++ * The transformer itself may throw an exception if necessary.
++ *
++ * @param object the object to transform
++ * @return a transformed object
++ */
++ protected O transform(I object) {
++ return transformer.transform(object);
++ }
++
++ /**
++ * Transforms a collection.
++ * <p/>
++ * The transformer itself may throw an exception if necessary.
++ *
++ * @param coll the collection to transform
++ * @return a transformed object
++ */
++ protected Collection<O> transform(Collection<? extends I> coll) {
++ List<O> list = new ArrayList<O>(coll.size());
++ for (Iterator<? extends I> it = coll.iterator(); it.hasNext();) {
++ list.add(transform(it.next()));
++ }
++ return list;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean add(Object object) {
++ O transformed = transform((I) object);
++ return getCollection().add(transformed);
++ }
++
++ /**
++ * A better typed version of the add method (although breaks the Collection interface).
++ */
++ public boolean addTyped(I object) {
++ return add(object);
++ }
++
++ public boolean addAll(Collection coll) {
++ Collection<O> col2 = transform((Collection<? extends I>) coll);
++ return getCollection().addAll(col2);
++ }
++
++ /**
++ * A better typed version of the addAll method (although breaks the Collection interface).
++ */
++ public boolean addAllTyped(Collection<? extends I> coll) {
++ return addAll(coll);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/collection/TypedCollection.java
+@@ -0,0 +1,61 @@
++// GenericsNote: Not converted, deprecated.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.collection;
++
++import org.apache.commons.collections15.functors.InstanceofPredicate;
++
++import java.util.Collection;
++
++/**
++ * Decorates a <code>Collection</code> to validate that elements added are of a specific type.
++ * <p/>
++ * The validation of additions is performed via an instanceof test against
++ * a specified <code>Class</code>. If an object cannot be added to the
++ * collection, an IllegalArgumentException is thrown.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Matthew Hawthorne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ * @deprecated Type safe classes are no longer required under 1.5.
++ */
++public class TypedCollection {
++
++ /**
++ * Factory method to create a typed collection.
++ * <p/>
++ * If there are any elements already in the collection being decorated, they
++ * are validated.
++ *
++ * @param coll the collection to decorate, must not be null
++ * @param type the type to allow into the collection, must not be null
++ * @return a new typed collection
++ * @throws IllegalArgumentException if collection or type is null
++ * @throws IllegalArgumentException if the collection contains invalid elements
++ */
++ public static Collection decorate(Collection coll, Class type) {
++ return new PredicatedCollection(coll, InstanceofPredicate.getInstance(type));
++ }
++
++ /**
++ * Restrictive constructor.
++ */
++ protected TypedCollection() {
++ super();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/collection/UnmodifiableBoundedCollection.java
+@@ -0,0 +1,141 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.collection;
++
++import org.apache.commons.collections15.BoundedCollection;
++import org.apache.commons.collections15.iterators.UnmodifiableIterator;
++
++import java.util.Collection;
++import java.util.Iterator;
++
++/**
++ * <code>UnmodifiableBoundedCollection</code> decorates another
++ * <code>BoundedCollection</code> to ensure it can't be altered.
++ * <p/>
++ * If a BoundedCollection is first wrapped in some other collection decorator,
++ * such as synchronized or predicated, the BoundedCollection methods are no
++ * longer accessible.
++ * The factory on this class will attempt to retrieve the bounded nature by
++ * examining the package scope variables.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableBoundedCollection <E> extends AbstractSerializableCollectionDecorator<E> implements BoundedCollection<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -7112672385450340330L;
++
++ /**
++ * Factory method to create an unmodifiable bounded collection.
++ *
++ * @param coll the <code>BoundedCollection</code> to decorate, must not be null
++ * @return a new unmodifiable bounded collection
++ * @throws IllegalArgumentException if bag is null
++ */
++ public static <E> BoundedCollection<E> decorate(BoundedCollection<E> coll) {
++ return new UnmodifiableBoundedCollection<E>(coll);
++ }
++
++ /**
++ * Factory method to create an unmodifiable bounded collection.
++ * <p/>
++ * This method is capable of drilling down through up to 1000 other decorators
++ * to find a suitable BoundedCollection.
++ *
++ * @param coll the <code>BoundedCollection</code> to decorate, must not be null
++ * @return a new unmodifiable bounded collection
++ * @throws IllegalArgumentException if bag is null
++ */
++ public static <E> BoundedCollection<E> decorateUsing(Collection<E> coll) {
++ if (coll == null) {
++ throw new IllegalArgumentException("The collection must not be null");
++ }
++
++ // handle decorators
++ for (int i = 0; i < 1000; i++) { // counter to prevent infinite looping
++ if (coll instanceof BoundedCollection) {
++ break; // normal loop exit
++ } else if (coll instanceof AbstractCollectionDecorator) {
++ coll = ((AbstractCollectionDecorator<E>) coll).collection;
++ } else if (coll instanceof SynchronizedCollection) {
++ coll = ((SynchronizedCollection<E>) coll).collection;
++ } else {
++ break; // normal loop exit
++ }
++ }
++
++ if (coll instanceof BoundedCollection == false) {
++ throw new IllegalArgumentException("The collection is not a bounded collection");
++ }
++ return new UnmodifiableBoundedCollection<E>((BoundedCollection) coll);
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param coll the collection to decorate, must not be null
++ * @throws IllegalArgumentException if coll is null
++ */
++ private UnmodifiableBoundedCollection(BoundedCollection<E> coll) {
++ super(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ public Iterator<E> iterator() {
++ return UnmodifiableIterator.decorate(getCollection().iterator());
++ }
++
++ public boolean add(E object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean remove(Object object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean isFull() {
++ return ((BoundedCollection) collection).isFull();
++ }
++
++ public int maxSize() {
++ return ((BoundedCollection) collection).maxSize();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/collection/UnmodifiableCollection.java
+@@ -0,0 +1,97 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.collection;
++
++import org.apache.commons.collections15.Unmodifiable;
++import org.apache.commons.collections15.iterators.UnmodifiableIterator;
++
++import java.util.Collection;
++import java.util.Iterator;
++
++/**
++ * Decorates another <code>Collection</code> to ensure it can't be altered.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableCollection <E> extends AbstractSerializableCollectionDecorator<E> implements Unmodifiable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -239892006883819945L;
++
++ /**
++ * Factory method to create an unmodifiable collection.
++ * <p/>
++ * If the collection passed in is already unmodifiable, it is returned.
++ *
++ * @param coll the collection to decorate, must not be null
++ * @return an unmodifiable collection
++ * @throws IllegalArgumentException if collection is null
++ */
++ public static <E> Collection<E> decorate(Collection<E> coll) {
++ if (coll instanceof Unmodifiable) {
++ return coll;
++ }
++ return new UnmodifiableCollection<E>(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param coll the collection to decorate, must not be null
++ * @throws IllegalArgumentException if collection is null
++ */
++ private UnmodifiableCollection(Collection<E> coll) {
++ super(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ public Iterator<E> iterator() {
++ return UnmodifiableIterator.decorate(getCollection().iterator());
++ }
++
++ public boolean add(E object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean remove(Object object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/collection/package.html
+@@ -0,0 +1,35 @@
++<!-- $Id: package.html,v 1.1 2005/10/11 17:05:20 pents90 Exp $ -->
++ <!--
++ Copyright 2003-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<BODY>
++<p>
++This package contains implementations of the
++{@link java.util.Collection Collection} interface.
++<p>
++The following implementations are provided in the package:
++<ul>
++<li>CompositeCollection - a collection that combines multiple collections into one
++</ul>
++The following decorators are provided in the package:
++<ul>
++<li>Synchronized - synchronizes method access for multi-threaded environments
++<li>Unmodifiable - ensures the collection cannot be altered
++<li>Predicated - ensures that only elements that are valid according to a predicate can be added
++<li>Typed - ensures that only elements that are of a specific type can be added
++<li>Transformed - transforms elements as they are added
++</ul>
++</pre>
++</BODY>
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/comparators/BooleanComparator.java
+@@ -0,0 +1,194 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.comparators;
++
++import java.io.Serializable;
++import java.util.Comparator;
++
++/**
++ * A {@link Comparator} for {@link Boolean} objects that can sort either
++ * true or false first.
++ * <p/>
++ *
++ * @author Matt Hall, John Watkinson, Rodney Waldhoff
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @see #getTrueFirstComparator()
++ * @see #getFalseFirstComparator()
++ * @see #getBooleanComparator(boolean)
++ * @since Commons Collections 3.0
++ */
++public final class BooleanComparator implements Comparator<Boolean>, Serializable {
++
++ /**
++ * Serialization version.
++ */
++ private static final long serialVersionUID = 1830042991606340609L;
++
++ /**
++ * Constant "true first" reference.
++ */
++ private static final BooleanComparator TRUE_FIRST = new BooleanComparator(true);
++
++ /**
++ * Constant "false first" reference.
++ */
++ private static final BooleanComparator FALSE_FIRST = new BooleanComparator(false);
++
++ /**
++ * <code>true</code> iff <code>true</code> values sort before <code>false</code> values.
++ */
++ private boolean trueFirst = false;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a BooleanComparator instance that sorts
++ * <code>true</code> values before <code>false</code> values.
++ * <p />
++ * Clients are encouraged to use the value returned from
++ * this method instead of constructing a new instance
++ * to reduce allocation and garbage collection overhead when
++ * multiple BooleanComparators may be used in the same
++ * virtual machine.
++ *
++ * @return the true first singleton BooleanComparator
++ */
++ public static BooleanComparator getTrueFirstComparator() {
++ return TRUE_FIRST;
++ }
++
++ /**
++ * Returns a BooleanComparator instance that sorts
++ * <code>false</code> values before <code>true</code> values.
++ * <p />
++ * Clients are encouraged to use the value returned from
++ * this method instead of constructing a new instance
++ * to reduce allocation and garbage collection overhead when
++ * multiple BooleanComparators may be used in the same
++ * virtual machine.
++ *
++ * @return the false first singleton BooleanComparator
++ */
++ public static BooleanComparator getFalseFirstComparator() {
++ return FALSE_FIRST;
++ }
++
++ /**
++ * Returns a BooleanComparator instance that sorts
++ * <code><i>trueFirst</i></code> values before
++ * <code>!<i>trueFirst</i></code> values.
++ * <p />
++ * Clients are encouraged to use the value returned from
++ * this method instead of constructing a new instance
++ * to reduce allocation and garbage collection overhead when
++ * multiple BooleanComparators may be used in the same
++ * virtual machine.
++ *
++ * @param trueFirst when <code>true</code>, sort
++ * <code>true</code> <code>Boolean</code>s before <code>false</code>
++ * @return a singleton BooleanComparator instance
++ */
++ public static BooleanComparator getBooleanComparator(boolean trueFirst) {
++ return trueFirst ? TRUE_FIRST : FALSE_FIRST;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Creates a <code>BooleanComparator</code> that sorts
++ * <code>false</code> values before <code>true</code> values.
++ * <p/>
++ * Equivalent to {@link #BooleanComparator(boolean) BooleanComparator(false)}.
++ * <p/>
++ * Please use the static factory instead whenever possible.
++ */
++ public BooleanComparator() {
++ this(false);
++ }
++
++ /**
++ * Creates a <code>BooleanComparator</code> that sorts
++ * <code><i>trueFirst</i></code> values before
++ * <code>!<i>trueFirst</i></code> values.
++ * <p/>
++ * Please use the static factories instead whenever possible.
++ *
++ * @param trueFirst when <code>true</code>, sort
++ * <code>true</code> boolean values before <code>false</code>
++ */
++ public BooleanComparator(boolean trueFirst) {
++ this.trueFirst = trueFirst;
++ }
++
++ /**
++ * Compares two non-<code>null</code> <code>Boolean</code> objects
++ * according to the value of {@link #trueFirst}.
++ *
++ * @param b1 the first boolean to compare
++ * @param b2 the second boolean to compare
++ * @return negative if obj1 is less, positive if greater, zero if equal
++ * @throws NullPointerException when either argument <code>null</code>
++ */
++ public int compare(Boolean b1, Boolean b2) {
++ boolean v1 = b1.booleanValue();
++ boolean v2 = b2.booleanValue();
++
++ return (v1 ^ v2) ? ((v1 ^ trueFirst) ? 1 : -1) : 0;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Implement a hash code for this comparator that is consistent with
++ * {@link #equals(Object) equals}.
++ *
++ * @return a hash code for this comparator.
++ */
++ public int hashCode() {
++ int hash = "BooleanComparator".hashCode();
++ return trueFirst ? -1 * hash : hash;
++ }
++
++ /**
++ * Returns <code>true</code> iff <i>that</i> Object is
++ * is a {@link Comparator} whose ordering is known to be
++ * equivalent to mine.
++ * <p/>
++ * This implementation returns <code>true</code>
++ * iff <code><i>that</i></code> is a {@link BooleanComparator}
++ * whose {@link #trueFirst} value is equal to mine.
++ *
++ * @param object the object to compare to
++ * @return true if equal
++ */
++ public boolean equals(Object object) {
++ return (this == object) || ((object instanceof BooleanComparator) && (this.trueFirst == ((BooleanComparator) object).trueFirst));
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns <code>true</code> iff
++ * I sort <code>true</code> values before
++ * <code>false</code> values. In other words,
++ * returns <code>true</code> iff
++ * {@link #compare(Boolean,Boolean) compare(Boolean.FALSE,Boolean.TRUE)}
++ * returns a positive value.
++ *
++ * @return the trueFirst flag
++ */
++ public boolean sortsTrueFirst() {
++ return trueFirst;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/comparators/ComparableComparator.java
+@@ -0,0 +1,128 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.comparators;
++
++import java.io.Serializable;
++import java.util.Comparator;
++
++/**
++ * A {@link Comparator Comparator} that compares
++ * {@link Comparable Comparable} objects.
++ * <p />
++ * This Comparator is useful, for example,
++ * for enforcing the natural order in custom implementations
++ * of SortedSet and SortedMap.
++ * <p />
++ * Note: In the 2.0 and 2.1 releases of Commons Collections,
++ * this class would throw a {@link ClassCastException} if
++ * either of the arguments to {@link #compare(Object, Object) compare}
++ * were <code>null</code>, not {@link Comparable Comparable},
++ * or for which {@link Comparable#compareTo(Object) compareTo} gave
++ * inconsistent results. This is no longer the case. See
++ * {@link #compare(Object, Object) compare} for details.
++ *
++ * @author Matt Hall, John Watkinson, Henri Yandell
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @see java.util.Collections#reverseOrder()
++ * @since Commons Collections 2.0
++ */
++public class ComparableComparator<T extends Comparable> implements Comparator<T>, Serializable {
++
++ /**
++ * Serialization version.
++ */
++ private static final long serialVersionUID = -291439688585137865L;
++
++ /**
++ * The singleton instance.
++ */
++ private static final ComparableComparator instance = new ComparableComparator();
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the singleton instance of a ComparableComparator.
++ * <p/>
++ * Developers are encouraged to use the comparator returned from this method
++ * instead of constructing a new instance to reduce allocation and GC overhead
++ * when multiple comparable comparators may be used in the same VM.
++ *
++ * @return the singleton ComparableComparator
++ */
++ public static <T> Comparator<T> getInstance() {
++ return instance;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor whose use should be avoided.
++ * <p/>
++ * Please use the {@link #getInstance()} method whenever possible.
++ */
++ public ComparableComparator() {
++ super();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Compare the two {@link Comparable Comparable} arguments.
++ * This method is equivalent to:
++ * <pre>((Comparable)obj1).compareTo(obj2)</pre>
++ *
++ * @param obj1 the first object to compare
++ * @param obj2 the second object to compare
++ * @return negative if obj1 is less, positive if greater, zero if equal
++ * @throws NullPointerException when <i>obj1</i> is <code>null</code>,
++ * or when <code>((Comparable)obj1).compareTo(obj2)</code> does
++ * @throws ClassCastException when <i>obj1</i> is not a <code>Comparable</code>,
++ * or when <code>((Comparable)obj1).compareTo(obj2)</code> does
++ */
++ public int compare(T obj1, T obj2) {
++ return obj1.compareTo(obj2);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Implement a hash code for this comparator that is consistent with
++ * {@link #equals(Object) equals}.
++ *
++ * @return a hash code for this comparator.
++ * @since Commons Collections 3.0
++ */
++ public int hashCode() {
++ return "ComparableComparator".hashCode();
++ }
++
++ /**
++ * Returns <code>true</code> iff <i>that</i> Object is
++ * is a {@link Comparator Comparator} whose ordering is
++ * known to be equivalent to mine.
++ * <p/>
++ * This implementation returns <code>true</code>
++ * iff <code><i>object</i>.{@link Object#getClass() getClass()}</code>
++ * equals <code>this.getClass()</code>.
++ * Subclasses may want to override this behavior to remain consistent
++ * with the {@link Comparator#equals(Object)} contract.
++ *
++ * @param object the object to compare with
++ * @return true if equal
++ * @since Commons Collections 3.0
++ */
++ public boolean equals(Object object) {
++ return (this == object) || ((null != object) && (object.getClass().equals(this.getClass())));
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/comparators/ComparatorChain.java
+@@ -0,0 +1,347 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.comparators;
++
++import java.io.Serializable;
++import java.util.*;
++
++/**
++ * <p>A ComparatorChain is a Comparator that wraps one or
++ * more Comparators in sequence. The ComparatorChain
++ * calls each Comparator in sequence until either 1)
++ * any single Comparator returns a non-zero result
++ * (and that result is then returned),
++ * or 2) the ComparatorChain is exhausted (and zero is
++ * returned). This type of sorting is very similar
++ * to multi-column sorting in SQL, and this class
++ * allows Java classes to emulate that kind of behaviour
++ * when sorting a List.</p>
++ * <p/>
++ * <p>To further facilitate SQL-like sorting, the order of
++ * any single Comparator in the list can be reversed.</p>
++ * <p/>
++ * <p>Calling a method that adds new Comparators or
++ * changes the ascend/descend sort <i>after compare(Object,
++ * Object) has been called</i> will result in an
++ * UnsupportedOperationException. However, <i>take care</i>
++ * to not alter the underlying List of Comparators
++ * or the BitSet that defines the sort order.</p>
++ * <p/>
++ * <p>Instances of ComparatorChain are not synchronized.
++ * The class is not thread-safe at construction time, but
++ * it <i>is</i> thread-safe to perform multiple comparisons
++ * after all the setup operations are complete.</p>
++ *
++ * @author Matt Hall, John Watkinson, Morgan Delagrange
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 2.0
++ */
++public class ComparatorChain <T> implements Comparator<T>, Serializable {
++
++ /**
++ * Serialization version from Collections 2.0.
++ */
++ private static final long serialVersionUID = -721644942746081630L;
++
++ /**
++ * The list of comparators in the chain.
++ */
++ protected List<Comparator<T>> comparatorChain = null;
++ /**
++ * Order - false (clear) = ascend; true (set) = descend.
++ */
++ protected BitSet orderingBits = null;
++ /**
++ * Whether the chain has been "locked".
++ */
++ protected boolean isLocked = false;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Construct a ComparatorChain with no Comparators.
++ * You must add at least one Comparator before calling
++ * the compare(Object,Object) method, or an
++ * UnsupportedOperationException is thrown
++ */
++ public ComparatorChain() {
++ this(new ArrayList<Comparator<T>>(), new BitSet());
++ }
++
++ /**
++ * Construct a ComparatorChain with a single Comparator,
++ * sorting in the forward order
++ *
++ * @param comparator First comparator in the Comparator chain
++ */
++ public ComparatorChain(Comparator<T> comparator) {
++ this(comparator, false);
++ }
++
++ /**
++ * Construct a Comparator chain with a single Comparator,
++ * sorting in the given order
++ *
++ * @param comparator First Comparator in the ComparatorChain
++ * @param reverse false = forward sort; true = reverse sort
++ */
++ public ComparatorChain(Comparator<T> comparator, boolean reverse) {
++ comparatorChain = new ArrayList<Comparator<T>>();
++ comparatorChain.add(comparator);
++ orderingBits = new BitSet(1);
++ if (reverse == true) {
++ orderingBits.set(0);
++ }
++ }
++
++ /**
++ * Construct a ComparatorChain from the Comparators in the
++ * List. All Comparators will default to the forward
++ * sort order.
++ *
++ * @param list List of Comparators
++ * @see #ComparatorChain(List,BitSet)
++ */
++ public ComparatorChain(List<Comparator<T>> list) {
++ this(list, new BitSet(list.size()));
++ }
++
++ /**
++ * Construct a ComparatorChain from the Comparators in the
++ * given List. The sort order of each column will be
++ * drawn from the given BitSet. When determining the sort
++ * order for Comparator at index <i>i</i> in the List,
++ * the ComparatorChain will call BitSet.get(<i>i</i>).
++ * If that method returns <i>false</i>, the forward
++ * sort order is used; a return value of <i>true</i>
++ * indicates reverse sort order.
++ *
++ * @param list List of Comparators. NOTE: This constructor does not perform a
++ * defensive copy of the list
++ * @param bits Sort order for each Comparator. Extra bits are ignored,
++ * unless extra Comparators are added by another method.
++ */
++ public ComparatorChain(List<Comparator<T>> list, BitSet bits) {
++ comparatorChain = list;
++ orderingBits = bits;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Add a Comparator to the end of the chain using the
++ * forward sort order
++ *
++ * @param comparator Comparator with the forward sort order
++ */
++ public void addComparator(Comparator<T> comparator) {
++ addComparator(comparator, false);
++ }
++
++ /**
++ * Add a Comparator to the end of the chain using the
++ * given sort order
++ *
++ * @param comparator Comparator to add to the end of the chain
++ * @param reverse false = forward sort order; true = reverse sort order
++ */
++ public void addComparator(Comparator<T> comparator, boolean reverse) {
++ checkLocked();
++
++ comparatorChain.add(comparator);
++ if (reverse == true) {
++ orderingBits.set(comparatorChain.size() - 1);
++ }
++ }
++
++ /**
++ * Replace the Comparator at the given index, maintaining
++ * the existing sort order.
++ *
++ * @param index index of the Comparator to replace
++ * @param comparator Comparator to place at the given index
++ * @throws IndexOutOfBoundsException if index < 0 or index >= size()
++ */
++ public void setComparator(int index, Comparator<T> comparator) throws IndexOutOfBoundsException {
++ setComparator(index, comparator, false);
++ }
++
++ /**
++ * Replace the Comparator at the given index in the
++ * ComparatorChain, using the given sort order
++ *
++ * @param index index of the Comparator to replace
++ * @param comparator Comparator to set
++ * @param reverse false = forward sort order; true = reverse sort order
++ */
++ public void setComparator(int index, Comparator<T> comparator, boolean reverse) {
++ checkLocked();
++
++ comparatorChain.set(index, comparator);
++ if (reverse == true) {
++ orderingBits.set(index);
++ } else {
++ orderingBits.clear(index);
++ }
++ }
++
++
++ /**
++ * Change the sort order at the given index in the
++ * ComparatorChain to a forward sort.
++ *
++ * @param index Index of the ComparatorChain
++ */
++ public void setForwardSort(int index) {
++ checkLocked();
++ orderingBits.clear(index);
++ }
++
++ /**
++ * Change the sort order at the given index in the
++ * ComparatorChain to a reverse sort.
++ *
++ * @param index Index of the ComparatorChain
++ */
++ public void setReverseSort(int index) {
++ checkLocked();
++ orderingBits.set(index);
++ }
++
++ /**
++ * Number of Comparators in the current ComparatorChain.
++ *
++ * @return Comparator count
++ */
++ public int size() {
++ return comparatorChain.size();
++ }
++
++ /**
++ * Determine if modifications can still be made to the
++ * ComparatorChain. ComparatorChains cannot be modified
++ * once they have performed a comparison.
++ *
++ * @return true = ComparatorChain cannot be modified; false =
++ * ComparatorChain can still be modified.
++ */
++ public boolean isLocked() {
++ return isLocked;
++ }
++
++ // throw an exception if the ComparatorChain is locked
++ private void checkLocked() {
++ if (isLocked == true) {
++ throw new UnsupportedOperationException("Comparator ordering cannot be changed after the first comparison is performed");
++ }
++ }
++
++ private void checkChainIntegrity() {
++ if (comparatorChain.size() == 0) {
++ throw new UnsupportedOperationException("ComparatorChains must contain at least one Comparator");
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Perform comparisons on the Objects as per
++ * Comparator.compare(o1,o2).
++ *
++ * @param o1 the first object to compare
++ * @param o2 the second object to compare
++ * @return -1, 0, or 1
++ * @throws UnsupportedOperationException if the ComparatorChain does not contain at least one
++ * Comparator
++ */
++ public int compare(T o1, T o2) throws UnsupportedOperationException {
++ if (isLocked == false) {
++ checkChainIntegrity();
++ isLocked = true;
++ }
++
++ // iterate over all comparators in the chain
++ Iterator<Comparator<T>> comparators = comparatorChain.iterator();
++ for (int comparatorIndex = 0; comparators.hasNext(); ++comparatorIndex) {
++
++ Comparator<T> comparator = comparators.next();
++ int retval = comparator.compare(o1, o2);
++ if (retval != 0) {
++ // invert the order if it is a reverse sort
++ if (orderingBits.get(comparatorIndex) == true) {
++ if (Integer.MIN_VALUE == retval) {
++ retval = Integer.MAX_VALUE;
++ } else {
++ retval *= -1;
++ }
++ }
++
++ return retval;
++ }
++
++ }
++
++ // if comparators are exhausted, return 0
++ return 0;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Implement a hash code for this comparator that is consistent with
++ * {@link #equals(Object) equals}.
++ *
++ * @return a suitable hash code
++ * @since Commons Collections 3.0
++ */
++ public int hashCode() {
++ int hash = 0;
++ if (null != comparatorChain) {
++ hash ^= comparatorChain.hashCode();
++ }
++ if (null != orderingBits) {
++ hash ^= orderingBits.hashCode();
++ }
++ return hash;
++ }
++
++ /**
++ * Returns <code>true</code> iff <i>that</i> Object is
++ * is a {@link Comparator} whose ordering is known to be
++ * equivalent to mine.
++ * <p/>
++ * This implementation returns <code>true</code>
++ * iff <code><i>object</i>.{@link Object#getClass() getClass()}</code>
++ * equals <code>this.getClass()</code>, and the underlying
++ * comparators and order bits are equal.
++ * Subclasses may want to override this behavior to remain consistent
++ * with the {@link Comparator#equals(Object)} contract.
++ *
++ * @param object the object to compare with
++ * @return true if equal
++ * @since Commons Collections 3.0
++ */
++ public boolean equals(Object object) {
++ if (this == object) {
++ return true;
++ } else if (null == object) {
++ return false;
++ } else if (object.getClass().equals(this.getClass())) {
++ ComparatorChain chain = (ComparatorChain) object;
++ return ((null == orderingBits ? null == chain.orderingBits : orderingBits.equals(chain.orderingBits)) && (null == comparatorChain ? null == chain.comparatorChain : comparatorChain.equals(chain.comparatorChain)));
++ } else {
++ return false;
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/comparators/FixedOrderComparator.java
+@@ -0,0 +1,267 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.comparators;
++
++import java.util.*;
++
++/**
++ * A Comparator which imposes a specific order on a specific set of Objects.
++ * Objects are presented to the FixedOrderComparator in a specified order and
++ * subsequent calls to {@link #compare(Object, Object) compare} yield that order.
++ * For example:
++ * <pre>
++ * String[] planets = {"Mercury", "Venus", "Earth", "Mars"};
++ * FixedOrderComparator distanceFromSun = new FixedOrderComparator(planets);
++ * Arrays.sort(planets); // Sort to alphabetical order
++ * Arrays.sort(planets, distanceFromSun); // Back to original order
++ * </pre>
++ * <p/>
++ * Once <code>compare</code> has been called, the FixedOrderComparator is locked
++ * and attempts to modify it yield an UnsupportedOperationException.
++ * <p/>
++ * Instances of FixedOrderComparator are not synchronized. The class is not
++ * thread-safe at construction time, but it is thread-safe to perform
++ * multiple comparisons after all the setup operations are complete.
++ *
++ * @author David Leppik
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Janek Bogucki
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 3.0
++ */
++public class FixedOrderComparator <T> implements Comparator<T> {
++
++ /**
++ * Behavior when comparing unknown Objects:
++ * unknown objects compare as before known Objects.
++ */
++ public static final int UNKNOWN_BEFORE = 0;
++
++ /**
++ * Behavior when comparing unknown Objects:
++ * unknown objects compare as after known Objects.
++ */
++ public static final int UNKNOWN_AFTER = 1;
++
++ /**
++ * Behavior when comparing unknown Objects:
++ * unknown objects cause a IllegalArgumentException to be thrown.
++ * This is the default behavior.
++ */
++ public static final int UNKNOWN_THROW_EXCEPTION = 2;
++
++ /**
++ * Internal map of object to position
++ */
++ private final Map<T, Integer> map = new HashMap<T, Integer>();
++ /**
++ * Counter used in determining the position in the map
++ */
++ private int counter = 0;
++ /**
++ * Is the comparator locked against further change
++ */
++ private boolean isLocked = false;
++ /**
++ * The behaviour in the case of an unknown object
++ */
++ private int unknownObjectBehavior = UNKNOWN_THROW_EXCEPTION;
++
++ // Constructors
++ //-----------------------------------------------------------------------
++ /**
++ * Constructs an empty FixedOrderComparator.
++ */
++ public FixedOrderComparator() {
++ super();
++ }
++
++ /**
++ * Constructs a FixedOrderComparator which uses the order of the given array
++ * to compare the objects.
++ * <p/>
++ * The array is copied, so later changes will not affect the comparator.
++ *
++ * @param items the items that the comparator can compare in order
++ * @throws IllegalArgumentException if the array is null
++ */
++ public FixedOrderComparator(T[] items) {
++ super();
++ if (items == null) {
++ throw new IllegalArgumentException("The list of items must not be null");
++ }
++ for (int i = 0; i < items.length; i++) {
++ add(items[i]);
++ }
++ }
++
++ /**
++ * Constructs a FixedOrderComparator which uses the order of the given list
++ * to compare the objects.
++ * <p/>
++ * The list is copied, so later changes will not affect the comparator.
++ *
++ * @param items the items that the comparator can compare in order
++ * @throws IllegalArgumentException if the list is null
++ */
++ public FixedOrderComparator(List<T> items) {
++ super();
++ if (items == null) {
++ throw new IllegalArgumentException("The list of items must not be null");
++ }
++ for (Iterator<T> it = items.iterator(); it.hasNext();) {
++ add(it.next());
++ }
++ }
++
++ // Bean methods / state querying methods
++ //-----------------------------------------------------------------------
++ /**
++ * Returns true if modifications cannot be made to the FixedOrderComparator.
++ * FixedOrderComparators cannot be modified once they have performed a comparison.
++ *
++ * @return true if attempts to change the FixedOrderComparator yield an
++ * UnsupportedOperationException, false if it can be changed.
++ */
++ public boolean isLocked() {
++ return isLocked;
++ }
++
++ /**
++ * Checks to see whether the comparator is now locked against further changes.
++ *
++ * @throws UnsupportedOperationException if the comparator is locked
++ */
++ protected void checkLocked() {
++ if (isLocked()) {
++ throw new UnsupportedOperationException("Cannot modify a FixedOrderComparator after a comparison");
++ }
++ }
++
++ /**
++ * Gets the behavior for comparing unknown objects.
++ *
++ * @return the flag for unknown behaviour - UNKNOWN_AFTER,
++ * UNKNOWN_BEFORE or UNKNOWN_THROW_EXCEPTION
++ */
++ public int getUnknownObjectBehavior() {
++ return unknownObjectBehavior;
++ }
++
++ /**
++ * Sets the behavior for comparing unknown objects.
++ *
++ * @param unknownObjectBehavior the flag for unknown behaviour -
++ * UNKNOWN_AFTER, UNKNOWN_BEFORE or UNKNOWN_THROW_EXCEPTION
++ * @throws UnsupportedOperationException if a comparison has been performed
++ * @throws IllegalArgumentException if the unknown flag is not valid
++ */
++ public void setUnknownObjectBehavior(int unknownObjectBehavior) {
++ checkLocked();
++ if (unknownObjectBehavior != UNKNOWN_AFTER && unknownObjectBehavior != UNKNOWN_BEFORE && unknownObjectBehavior != UNKNOWN_THROW_EXCEPTION) {
++ throw new IllegalArgumentException("Unrecognised value for unknown behaviour flag");
++ }
++ this.unknownObjectBehavior = unknownObjectBehavior;
++ }
++
++ // Methods for adding items
++ //-----------------------------------------------------------------------
++ /**
++ * Adds an item, which compares as after all items known to the Comparator.
++ * If the item is already known to the Comparator, its old position is
++ * replaced with the new position.
++ *
++ * @param obj the item to be added to the Comparator.
++ * @return true if obj has been added for the first time, false if
++ * it was already known to the Comparator.
++ * @throws UnsupportedOperationException if a comparison has already been made
++ */
++ public boolean add(T obj) {
++ checkLocked();
++ Integer position = map.put(obj, new Integer(counter++));
++ return (position == null);
++ }
++
++ /**
++ * Adds a new item, which compares as equal to the given existing item.
++ *
++ * @param existingObj an item already in the Comparator's set of
++ * known objects
++ * @param newObj an item to be added to the Comparator's set of
++ * known objects
++ * @return true if newObj has been added for the first time, false if
++ * it was already known to the Comparator.
++ * @throws IllegalArgumentException if existingObject is not in the
++ * Comparator's set of known objects.
++ * @throws UnsupportedOperationException if a comparison has already been made
++ */
++ public boolean addAsEqual(T existingObj, T newObj) {
++ checkLocked();
++ Integer position = (Integer) map.get(existingObj);
++ if (position == null) {
++ throw new IllegalArgumentException(existingObj + " not known to " + this);
++ }
++ Integer result = map.put(newObj, position);
++ return (result == null);
++ }
++
++ // Comparator methods
++ //-----------------------------------------------------------------------
++ /**
++ * Compares two objects according to the order of this Comparator.
++ * <p/>
++ * It is important to note that this class will throw an IllegalArgumentException
++ * in the case of an unrecognised object. This is not specified in the
++ * Comparator interface, but is the most appropriate exception.
++ *
++ * @param obj1 the first object to compare
++ * @param obj2 the second object to compare
++ * @return negative if obj1 is less, positive if greater, zero if equal
++ * @throws IllegalArgumentException if obj1 or obj2 are not known
++ * to this Comparator and an alternative behavior has not been set
++ * via {@link #setUnknownObjectBehavior(int)}.
++ */
++ public int compare(T obj1, T obj2) {
++ isLocked = true;
++ Integer position1 = (Integer) map.get(obj1);
++ Integer position2 = (Integer) map.get(obj2);
++ if (position1 == null || position2 == null) {
++ switch (unknownObjectBehavior) {
++ case UNKNOWN_BEFORE:
++ if (position1 == null) {
++ return (position2 == null) ? 0 : -1;
++ } else {
++ return 1;
++ }
++ case UNKNOWN_AFTER:
++ if (position1 == null) {
++ return (position2 == null) ? 0 : 1;
++ } else {
++ return -1;
++ }
++ case UNKNOWN_THROW_EXCEPTION:
++ Object unknownObj = (position1 == null) ? obj1 : obj2;
++ throw new IllegalArgumentException("Attempting to compare unknown object " + unknownObj);
++ default :
++ throw new UnsupportedOperationException("Unknown unknownObjectBehavior: " + unknownObjectBehavior);
++ }
++ } else {
++ return position1.compareTo(position2);
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/comparators/NullComparator.java
+@@ -0,0 +1,157 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.comparators;
++
++import java.io.Serializable;
++import java.util.Comparator;
++
++/**
++ * A Comparator that will compare nulls to be either lower or higher than
++ * other objects.
++ *
++ * @author Matt Hall, John Watkinson, Michael A. Smith
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @since Commons Collections 2.0
++ */
++public class NullComparator <T> implements Comparator<T>, Serializable {
++
++ /**
++ * Serialization version.
++ */
++ private static final long serialVersionUID = -5820772575483504339L;
++
++ /**
++ * The comparator to use when comparing two non-<code>null</code> objects.
++ */
++ private Comparator<T> nonNullComparator;
++
++ /**
++ * Specifies whether a <code>null</code> are compared as higher than
++ * non-<code>null</code> objects.
++ */
++ private boolean nullsAreHigh;
++
++ /**
++ * Construct an instance that sorts <code>null</code> higher than any
++ * non-<code>null</code> object it is compared with. When comparing two
++ * non-<code>null</code> objects, the specified {@link Comparator} is
++ * used.
++ *
++ * @param nonNullComparator the comparator to use when comparing two
++ * non-<code>null</code> objects. This argument cannot be
++ * <code>null</code>
++ * @throws NullPointerException if <code>nonNullComparator</code> is
++ * <code>null</code>
++ */
++ public NullComparator(Comparator<T> nonNullComparator) {
++ this(nonNullComparator, true);
++ }
++
++ /**
++ * Construct an instance that sorts <code>null</code> higher or lower than
++ * any non-<code>null</code> object it is compared with. When comparing
++ * two non-<code>null</code> objects, the specified {@link Comparator} is
++ * used.
++ *
++ * @param nonNullComparator the comparator to use when comparing two
++ * non-<code>null</code> objects. This argument cannot be
++ * <code>null</code>
++ * @param nullsAreHigh a <code>true</code> value indicates that
++ * <code>null</code> should be compared as higher than a
++ * non-<code>null</code> object. A <code>false</code> value indicates
++ * that <code>null</code> should be compared as lower than a
++ * non-<code>null</code> object.
++ * @throws NullPointerException if <code>nonNullComparator</code> is
++ * <code>null</code>
++ */
++ public NullComparator(Comparator<T> nonNullComparator, boolean nullsAreHigh) {
++ this.nonNullComparator = nonNullComparator;
++ this.nullsAreHigh = nullsAreHigh;
++
++ if (nonNullComparator == null) {
++ throw new NullPointerException("null nonNullComparator");
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Perform a comparison between two objects. If both objects are
++ * <code>null</code>, a <code>0</code> value is returned. If one object
++ * is <code>null</code> and the other is not, the result is determined on
++ * whether the Comparator was constructed to have nulls as higher or lower
++ * than other objects. If neither object is <code>null</code>, an
++ * underlying comparator specified in the constructor (or the default) is
++ * used to compare the non-<code>null</code> objects.
++ *
++ * @param o1 the first object to compare
++ * @param o2 the object to compare it to.
++ * @return <code>-1</code> if <code>o1</code> is "lower" than (less than,
++ * before, etc.) <code>o2</code>; <code>1</code> if <code>o1</code> is
++ * "higher" than (greater than, after, etc.) <code>o2</code>; or
++ * <code>0</code> if <code>o1</code> and <code>o2</code> are equal.
++ */
++ public int compare(T o1, T o2) {
++ if (o1 == o2) {
++ return 0;
++ }
++ if (o1 == null) {
++ return (this.nullsAreHigh ? 1 : -1);
++ }
++ if (o2 == null) {
++ return (this.nullsAreHigh ? -1 : 1);
++ }
++ return this.nonNullComparator.compare(o1, o2);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Implement a hash code for this comparator that is consistent with
++ * {@link #equals(Object)}.
++ *
++ * @return a hash code for this comparator.
++ */
++ public int hashCode() {
++ return (nullsAreHigh ? -1 : 1) * nonNullComparator.hashCode();
++ }
++
++ /**
++ * Determines whether the specified object represents a comparator that is
++ * equal to this comparator.
++ *
++ * @param obj the object to compare this comparator with.
++ * @return <code>true</code> if the specified object is a NullComparator
++ * with equivalent <code>null</code> comparison behavior
++ * (i.e. <code>null</code> high or low) and with equivalent underlying
++ * non-<code>null</code> object comparators.
++ */
++ public boolean equals(Object obj) {
++ if (obj == null) {
++ return false;
++ }
++ if (obj == this) {
++ return true;
++ }
++ if (!obj.getClass().equals(this.getClass())) {
++ return false;
++ }
++
++ NullComparator other = (NullComparator) obj;
++
++ return ((this.nullsAreHigh == other.nullsAreHigh) && (this.nonNullComparator.equals(other.nonNullComparator)));
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/comparators/ReverseComparator.java
+@@ -0,0 +1,109 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.comparators;
++
++import java.io.Serializable;
++import java.util.Comparator;
++
++/**
++ * Reverses the order of another comparator by reversing the arguments
++ * to its {@link #compare(Object, Object) compare} method.
++ *
++ * @author Henri Yandell
++ * @author Matt Hall, John Watkinson, Michael A. Smith
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @see java.util.Collections#reverseOrder()
++ * @since Commons Collections 2.0
++ */
++public class ReverseComparator <T> implements Comparator<T>, Serializable {
++
++ /**
++ * Serialization version from Collections 2.0.
++ */
++ private static final long serialVersionUID = 2858887242028539265L;
++
++ /**
++ * The comparator being decorated.
++ */
++ private Comparator<T> comparator;
++
++ /**
++ * Creates a comparator that inverts the comparison
++ * of the given comparator. Pass in a {@link ComparableComparator}
++ * for reversing the natural order, as per
++ * {@link java.util.Collections#reverseOrder()}</b>.
++ *
++ * @param comparator Comparator to reverse
++ */
++ public ReverseComparator(Comparator<T> comparator) {
++ this.comparator = comparator;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Compares two objects in reverse order.
++ *
++ * @param obj1 the first object to compare
++ * @param obj2 the second object to compare
++ * @return negative if obj1 is less, positive if greater, zero if equal
++ */
++ public int compare(T obj1, T obj2) {
++ return comparator.compare(obj2, obj1);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Implement a hash code for this comparator that is consistent with
++ * {@link #equals(Object) equals}.
++ *
++ * @return a suitable hash code
++ * @since Commons Collections 3.0
++ */
++ public int hashCode() {
++ return "ReverseComparator".hashCode() ^ comparator.hashCode();
++ }
++
++ /**
++ * Returns <code>true</code> iff <i>that</i> Object is
++ * is a {@link Comparator} whose ordering is known to be
++ * equivalent to mine.
++ * <p/>
++ * This implementation returns <code>true</code>
++ * iff <code><i>object</i>.{@link Object#getClass() getClass()}</code>
++ * equals <code>this.getClass()</code>, and the underlying
++ * comparators are equal.
++ * Subclasses may want to override this behavior to remain consistent
++ * with the {@link Comparator#equals(Object) equals} contract.
++ *
++ * @param object the object to compare to
++ * @return true if equal
++ * @since Commons Collections 3.0
++ */
++ public boolean equals(Object object) {
++ if (this == object) {
++ return true;
++ } else if (null == object) {
++ return false;
++ } else if (object.getClass().equals(this.getClass())) {
++ ReverseComparator thatrc = (ReverseComparator) object;
++ return comparator.equals(thatrc.comparator);
++ } else {
++ return false;
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/comparators/TransformingComparator.java
+@@ -0,0 +1,70 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.comparators;
++
++import org.apache.commons.collections15.Transformer;
++
++import java.util.Comparator;
++
++/**
++ * Decorates another Comparator with transformation behavior. That is, the
++ * return value from the transform operation will be passed to the decorated
++ * {@link Comparator#compare(Object,Object) compare} method.
++ *
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:20 $
++ * @see org.apache.commons.collections15.Transformer
++ * @see org.apache.commons.collections15.comparators.ComparableComparator
++ * @since Commons Collections 2.0 (?)
++ */
++public class TransformingComparator <I,O> implements Comparator<I> {
++
++ /**
++ * The decorated comparator.
++ */
++ protected Comparator<O> decorated;
++ /**
++ * The transformer being used.
++ */
++ protected Transformer<I, O> transformer;
++
++ /**
++ * Constructs an instance with the given Transformer and Comparator.
++ *
++ * @param transformer what will transform the arguments to <code>compare</code>
++ * @param decorated the decorated Comparator
++ */
++ public TransformingComparator(Transformer<I, O> transformer, Comparator<O> decorated) {
++ this.decorated = decorated;
++ this.transformer = transformer;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns the result of comparing the values from the transform operation.
++ *
++ * @param obj1 the first object to transform then compare
++ * @param obj2 the second object to transform then compare
++ * @return negative if obj1 is less, positive if greater, zero if equal
++ */
++ public int compare(I obj1, I obj2) {
++ O value1 = this.transformer.transform(obj1);
++ O value2 = this.transformer.transform(obj2);
++ return this.decorated.compare(value1, value2);
++ }
++
++}
++
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/comparators/package.html
+@@ -0,0 +1,26 @@
++<!-- $Id: package.html,v 1.1 2005/10/11 17:05:20 pents90 Exp $ -->
++ <!--
++ Copyright 2002-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<BODY>
++<p>
++This package contains implementations of the
++{@link java.util.Comparator Comparator} interface.
++<p>
++You may also consider using
++{@link org.apache.commons.collections.ComparatorUtils ComparatorUtils},
++which is a single class that uses static methods to construct instances
++of the classes in this package.
++</BODY>
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/AllPredicate.java
+@@ -0,0 +1,108 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++import java.util.Collection;
++
++/**
++ * Predicate implementation that returns true if all the predicates return true.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class AllPredicate <T> implements Predicate<T>, PredicateDecorator<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -3094696765038308799L;
++
++ /**
++ * The array of predicates to call
++ */
++ private final Predicate<? super T>[] iPredicates;
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @param predicates the predicates to check, cloned, not null
++ * @return the <code>all</code> predicate
++ * @throws IllegalArgumentException if the predicates array is null
++ * @throws IllegalArgumentException if the predicates array has less than 2 elements
++ * @throws IllegalArgumentException if any predicate in the array is null
++ */
++ public static <T> Predicate<T> getInstance(Predicate<? super T>[] predicates) {
++ FunctorUtils.validateMin2(predicates);
++ predicates = FunctorUtils.copy(predicates);
++ return new AllPredicate<T>(predicates);
++ }
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @param predicates the predicates to check, cloned, not null
++ * @return the <code>all</code> predicate
++ * @throws IllegalArgumentException if the predicates array is null
++ * @throws IllegalArgumentException if any predicate in the array is null
++ * @throws IllegalArgumentException if the predicates array has less than 2 elements
++ */
++ public static <T> Predicate<T> getInstance(Collection<Predicate<? super T>> predicates) {
++ Predicate[] preds = FunctorUtils.<T>validate(predicates);
++ return new AllPredicate<T>(preds);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicates the predicates to check, not cloned, not null
++ */
++ public AllPredicate(Predicate<? super T>[] predicates) {
++ super();
++ iPredicates = predicates;
++ }
++
++ /**
++ * Evaluates the predicate returning true if all predicates return true.
++ *
++ * @param object the input object
++ * @return true if all decorated predicates return true
++ */
++ public boolean evaluate(T object) {
++ for (int i = 0; i < iPredicates.length; i++) {
++ if (iPredicates[i].evaluate(object) == false) {
++ return false;
++ }
++ }
++ return true;
++ }
++
++ /**
++ * Gets the predicates, do not modify the array.
++ *
++ * @return the predicates
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T>[] getPredicates() {
++ return iPredicates;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/AndPredicate.java
+@@ -0,0 +1,94 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that returns true if both the predicates return true.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class AndPredicate <T> implements Predicate<T>, PredicateDecorator<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 4189014213763186912L;
++
++ /**
++ * The array of predicates to call
++ */
++ private final Predicate<? super T> iPredicate1;
++ /**
++ * The array of predicates to call
++ */
++ private final Predicate<? super T> iPredicate2;
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @param predicate1 the first predicate to check, not null
++ * @param predicate2 the second predicate to check, not null
++ * @return the <code>and</code> predicate
++ * @throws IllegalArgumentException if either predicate is null
++ */
++ public static <T> Predicate<T> getInstance(Predicate<? super T> predicate1, Predicate<? super T> predicate2) {
++ if (predicate1 == null || predicate2 == null) {
++ throw new IllegalArgumentException("Predicate must not be null");
++ }
++ return new AndPredicate<T>(predicate1, predicate2);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicate1 the first predicate to check, not null
++ * @param predicate2 the second predicate to check, not null
++ */
++ public AndPredicate(Predicate<? super T> predicate1, Predicate<? super T> predicate2) {
++ super();
++ iPredicate1 = predicate1;
++ iPredicate2 = predicate2;
++ }
++
++ /**
++ * Evaluates the predicate returning true if both predicates return true.
++ *
++ * @param object the input object
++ * @return true if both decorated predicates return true
++ */
++ public boolean evaluate(T object) {
++ return (iPredicate1.evaluate(object) && iPredicate2.evaluate(object));
++ }
++
++ /**
++ * Gets the two predicates being decorated as an array.
++ *
++ * @return the predicates
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T>[] getPredicates() {
++ return new Predicate[]{iPredicate1, iPredicate2};
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/AnyPredicate.java
+@@ -0,0 +1,108 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++import java.util.Collection;
++
++/**
++ * Predicate implementation that returns true if any of the predicates return true.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class AnyPredicate <T> implements Predicate<T>, PredicateDecorator<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 7429999530934647542L;
++
++ /**
++ * The array of predicates to call
++ */
++ private final Predicate<? super T>[] iPredicates;
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @param predicates the predicates to check, cloned, not null
++ * @return the <code>any</code> predicate
++ * @throws IllegalArgumentException if the predicates array is null
++ * @throws IllegalArgumentException if the predicates array has less than 2 elements
++ * @throws IllegalArgumentException if any predicate in the array is null
++ */
++ public static <T> Predicate<T> getInstance(Predicate<? super T>[] predicates) {
++ FunctorUtils.validateMin2(predicates);
++ predicates = FunctorUtils.copy(predicates);
++ return new AnyPredicate<T>(predicates);
++ }
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @param predicates the predicates to check, cloned, not null
++ * @return the <code>all</code> predicate
++ * @throws IllegalArgumentException if the predicates array is null
++ * @throws IllegalArgumentException if any predicate in the array is null
++ * @throws IllegalArgumentException if the predicates array has less than 2 elements
++ */
++ public static <T> Predicate<T> getInstance(Collection<Predicate<? super T>> predicates) {
++ Predicate[] preds = FunctorUtils.validate(predicates);
++ return new AnyPredicate<T>(preds);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicates the predicates to check, not cloned, not null
++ */
++ public AnyPredicate(Predicate<? super T>[] predicates) {
++ super();
++ iPredicates = predicates;
++ }
++
++ /**
++ * Evaluates the predicate returning true if any predicate returns true.
++ *
++ * @param object the input object
++ * @return true if any decorated predicate return true
++ */
++ public boolean evaluate(T object) {
++ for (int i = 0; i < iPredicates.length; i++) {
++ if (iPredicates[i].evaluate(object)) {
++ return true;
++ }
++ }
++ return false;
++ }
++
++ /**
++ * Gets the predicates, do not modify the array.
++ *
++ * @return the predicates
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T>[] getPredicates() {
++ return iPredicates;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/ChainedClosure.java
+@@ -0,0 +1,136 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Closure;
++
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Iterator;
++
++/**
++ * Closure implementation that chains the specified closures together.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class ChainedClosure <T> implements Closure<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -3520677225766901240L;
++
++ /**
++ * The closures to call in turn
++ */
++ private final Closure<? super T>[] iClosures;
++
++ /**
++ * Factory method that performs validation and copies the parameter array.
++ *
++ * @param closures the closures to chain, copied, no nulls
++ * @return the <code>chained</code> closure
++ * @throws IllegalArgumentException if the closures array is null
++ * @throws IllegalArgumentException if any closure in the array is null
++ */
++ public static <T> Closure<T> getInstance(Closure<? super T>[] closures) {
++ FunctorUtils.validate(closures);
++ if (closures.length == 0) {
++ return NOPClosure.INSTANCE;
++ }
++ closures = FunctorUtils.copy(closures);
++ return new ChainedClosure<T>(closures);
++ }
++
++ /**
++ * Create a new Closure that calls each closure in turn, passing the
++ * result into the next closure. The ordering is that of the iterator()
++ * method on the collection.
++ *
++ * @param closures a collection of closures to chain
++ * @return the <code>chained</code> closure
++ * @throws IllegalArgumentException if the closures collection is null
++ * @throws IllegalArgumentException if any closure in the collection is null
++ */
++ public static <T> Closure<T> getInstance(Collection<? super T> closures) {
++ if (closures == null) {
++ throw new IllegalArgumentException("Closure collection must not be null");
++ }
++ if (closures.size() == 0) {
++ return NOPClosure.INSTANCE;
++ }
++ // convert to array like this to guarantee iterator() ordering
++ Closure<? super T>[] cmds = new Closure[closures.size()];
++ int i = 0;
++ for (Iterator it = closures.iterator(); it.hasNext();) {
++ cmds[i++] = (Closure<? super T>) it.next();
++ }
++ FunctorUtils.validate(cmds);
++ return new ChainedClosure(cmds);
++ }
++
++ /**
++ * Factory method that performs validation.
++ *
++ * @param closure1 the first closure, not null
++ * @param closure2 the second closure, not null
++ * @return the <code>chained</code> closure
++ * @throws IllegalArgumentException if either closure is null
++ */
++ public static <T> Closure<T> getInstance(Closure<? super T> closure1, Closure<? super T> closure2) {
++ if (closure1 == null || closure2 == null) {
++ throw new IllegalArgumentException("Closures must not be null");
++ }
++ Closure<? super T>[] closures = new Closure[]{closure1, closure2};
++ return new ChainedClosure<T>(closures);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param closures the closures to chain, not copied, no nulls
++ */
++ public ChainedClosure(Closure<? super T>[] closures) {
++ super();
++ iClosures = closures;
++ }
++
++ /**
++ * Execute a list of closures.
++ *
++ * @param input the input object passed to each closure
++ */
++ public void execute(T input) {
++ for (int i = 0; i < iClosures.length; i++) {
++ iClosures[i].execute(input);
++ }
++ }
++
++ /**
++ * Gets the closures, do not modify the array.
++ *
++ * @return the closures
++ * @since Commons Collections 3.1
++ */
++ public Closure<? super T>[] getClosures() {
++ return iClosures;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/ChainedTransformer.java
+@@ -0,0 +1,142 @@
++// GenericsNote: Converted, but only partially type-safe.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Iterator;
++
++/**
++ * Transformer implementation that chains the specified transformers together.
++ * <p/>
++ * The input object is passed to the first transformer. The transformed result
++ * is passed to the second transformer and so on.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class ChainedTransformer <I,O> implements Transformer<I, O>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 3514945074733160196L;
++
++ /**
++ * The transformers to call in turn
++ */
++ private final Transformer[] iTransformers;
++
++ /**
++ * Factory method that performs validation and copies the parameter array.
++ *
++ * @param transformers the transformers to chain, copied, no nulls
++ * @return the <code>chained</code> transformer
++ * @throws IllegalArgumentException if the transformers array is null
++ * @throws IllegalArgumentException if any transformer in the array is null
++ */
++ public static <I,O> Transformer<I, O> getInstance(Transformer[] transformers) {
++ FunctorUtils.validate(transformers);
++ if (transformers.length == 0) {
++ return NOPTransformer.INSTANCE;
++ }
++ transformers = FunctorUtils.copy(transformers);
++ return new ChainedTransformer<I, O>(transformers);
++ }
++
++ /**
++ * Create a new Transformer that calls each transformer in turn, passing the
++ * result into the next transformer. The ordering is that of the iterator()
++ * method on the collection.
++ *
++ * @param transformers a collection of transformers to chain
++ * @return the <code>chained</code> transformer
++ * @throws IllegalArgumentException if the transformers collection is null
++ * @throws IllegalArgumentException if any transformer in the collection is null
++ */
++ public static <I,O> Transformer<I, O> getInstance(Collection<Transformer> transformers) {
++ if (transformers == null) {
++ throw new IllegalArgumentException("Transformer collection must not be null");
++ }
++ if (transformers.size() == 0) {
++ return NOPTransformer.INSTANCE;
++ }
++ // convert to array like this to guarantee iterator() ordering
++ Transformer[] cmds = new Transformer[transformers.size()];
++ int i = 0;
++ for (Iterator<Transformer> it = transformers.iterator(); it.hasNext();) {
++ cmds[i++] = it.next();
++ }
++ FunctorUtils.validate(cmds);
++ return new ChainedTransformer<I, O>(cmds);
++ }
++
++ /**
++ * Factory method that performs validation.
++ *
++ * @param transformer1 the first transformer, not null
++ * @param transformer2 the second transformer, not null
++ * @return the <code>chained</code> transformer
++ * @throws IllegalArgumentException if either transformer is null
++ */
++ public static <I,M,O> Transformer<I, O> getInstance(Transformer<I, ? extends M> transformer1, Transformer<? super M, O> transformer2) {
++ if (transformer1 == null || transformer2 == null) {
++ throw new IllegalArgumentException("Transformers must not be null");
++ }
++ Transformer[] transformers = new Transformer[]{transformer1, transformer2};
++ return new ChainedTransformer<I, O>(transformers);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param transformers the transformers to chain, not copied, no nulls
++ */
++ public ChainedTransformer(Transformer[] transformers) {
++ super();
++ iTransformers = transformers;
++ }
++
++ /**
++ * Transforms the input to result via each decorated transformer
++ *
++ * @param object the input object passed to the first transformer
++ * @return the transformed result
++ */
++ public O transform(I object) {
++ Object intermediate = object;
++ for (int i = 0; i < iTransformers.length; i++) {
++ intermediate = iTransformers[i].transform(intermediate);
++ }
++ return (O) intermediate;
++ }
++
++ /**
++ * Gets the transformers, do not modify the array.
++ *
++ * @return the transformers
++ * @since Commons Collections 3.1
++ */
++ public Transformer[] getTransformers() {
++ return iTransformers;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/CloneTransformer.java
+@@ -0,0 +1,74 @@
++// GenericsNote: Converted (nothing to convert).
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++
++/**
++ * Transformer implementation that returns a clone of the input object.
++ * <p/>
++ * Clone is performed using <code>PrototypeFactory.getInstance(input).create()</code>.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class CloneTransformer<T> implements Transformer<T,T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -8188742709499652567L;
++
++ /**
++ * Singleton predicate instance
++ */
++ public static final Transformer INSTANCE = new CloneTransformer();
++
++ /**
++ * Factory returning the singleton instance.
++ *
++ * @return the singleton instance
++ * @since Commons Collections 3.1
++ */
++ public static <T> Transformer<T,T> getInstance() {
++ return INSTANCE;
++ }
++
++ /**
++ * Constructor
++ */
++ private CloneTransformer() {
++ super();
++ }
++
++ /**
++ * Transforms the input to result by cloning it.
++ *
++ * @param input the input object to transform
++ * @return the transformed result
++ */
++ public T transform(T input) {
++ if (input == null) {
++ return null;
++ }
++ return PrototypeFactory.getInstance(input).create();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/ClosureTransformer.java
+@@ -0,0 +1,90 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Closure;
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++
++/**
++ * Transformer implementation that calls a Closure using the input object
++ * and then returns the input.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class ClosureTransformer <T> implements Transformer<T, T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 478466901448617286L;
++
++ /**
++ * The closure to wrap
++ */
++ private final Closure<T> iClosure;
++
++ /**
++ * Factory method that performs validation.
++ *
++ * @param closure the closure to call, not null
++ * @return the <code>closure</code> transformer
++ * @throws IllegalArgumentException if the closure is null
++ */
++ public static <T> Transformer<T, T> getInstance(Closure<T> closure) {
++ if (closure == null) {
++ throw new IllegalArgumentException("Closure must not be null");
++ }
++ return new ClosureTransformer<T>(closure);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param closure the closure to call, not null
++ */
++ public ClosureTransformer(Closure<T> closure) {
++ super();
++ iClosure = closure;
++ }
++
++ /**
++ * Transforms the input to result by executing a closure.
++ *
++ * @param input the input object to transform
++ * @return the transformed result
++ */
++ public T transform(T input) {
++ iClosure.execute(input);
++ return input;
++ }
++
++ /**
++ * Gets the closure.
++ *
++ * @return the closure
++ * @since Commons Collections 3.1
++ */
++ public Closure<T> getClosure() {
++ return iClosure;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/ConstantFactory.java
+@@ -0,0 +1,94 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Factory;
++
++import java.io.Serializable;
++
++/**
++ * Factory implementation that returns the same constant each time.
++ * <p/>
++ * No check is made that the object is immutable. In general, only immutable
++ * objects should use the constant factory. Mutable objects should
++ * use the prototype factory.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class ConstantFactory <T> implements Factory<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -3520677225766901240L;
++
++ /**
++ * Returns null each time
++ */
++ public static final Factory NULL_INSTANCE = new ConstantFactory(null);
++
++ /**
++ * The closures to call in turn
++ */
++ private final T iConstant;
++
++ /**
++ * Factory method that performs validation.
++ *
++ * @param constantToReturn the constant object to return each time in the factory
++ * @return the <code>constant</code> factory.
++ */
++ public static <T> Factory<T> getInstance(T constantToReturn) {
++ if (constantToReturn == null) {
++ return NULL_INSTANCE;
++ }
++ return new ConstantFactory<T>(constantToReturn);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param constantToReturn the constant to return each time
++ */
++ public ConstantFactory(T constantToReturn) {
++ super();
++ iConstant = constantToReturn;
++ }
++
++ /**
++ * Always return constant.
++ *
++ * @return the stored constant value
++ */
++ public T create() {
++ return iConstant;
++ }
++
++ /**
++ * Gets the constant.
++ *
++ * @return the constant
++ * @since Commons Collections 3.1
++ */
++ public T getConstant() {
++ return iConstant;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/ConstantTransformer.java
+@@ -0,0 +1,95 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++
++/**
++ * Transformer implementation that returns the same constant each time.
++ * <p/>
++ * No check is made that the object is immutable. In general, only immutable
++ * objects should use the constant factory. Mutable objects should
++ * use the prototype factory.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class ConstantTransformer <T> implements Transformer<Object, T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 6374440726369055124L;
++
++ /**
++ * Returns null each time
++ */
++ public static final Transformer NULL_INSTANCE = new ConstantTransformer(null);
++
++ /**
++ * The closures to call in turn
++ */
++ private final T iConstant;
++
++ /**
++ * Transformer method that performs validation.
++ *
++ * @param constantToReturn the constant object to return each time in the factory
++ * @return the <code>constant</code> factory.
++ */
++ public static <T> Transformer<Object, T> getInstance(T constantToReturn) {
++ if (constantToReturn == null) {
++ return NULL_INSTANCE;
++ }
++ return new ConstantTransformer<T>(constantToReturn);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param constantToReturn the constant to return each time
++ */
++ public ConstantTransformer(T constantToReturn) {
++ super();
++ iConstant = constantToReturn;
++ }
++
++ /**
++ * Transforms the input by ignoring it and returning the stored constant instead.
++ *
++ * @param input the input object which is ignored
++ * @return the stored constant
++ */
++ public T transform(Object input) {
++ return iConstant;
++ }
++
++ /**
++ * Gets the constant.
++ *
++ * @return the constant
++ * @since Commons Collections 3.1
++ */
++ public T getConstant() {
++ return iConstant;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/EqualPredicate.java
+@@ -0,0 +1,88 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that returns true if the input is the same object
++ * as the one stored in this predicate by equals.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class EqualPredicate <T> implements Predicate<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 5633766978029907089L;
++
++ /**
++ * The value to compare to
++ */
++ private final T iValue;
++
++ /**
++ * Factory to create the identity predicate.
++ *
++ * @param object the object to compare to
++ * @return the predicate
++ * @throws IllegalArgumentException if the predicate is null
++ */
++ public static <T> Predicate<T> getInstance(T object) {
++ if (object == null) {
++ return NullPredicate.INSTANCE;
++ }
++ return new EqualPredicate<T>(object);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param object the object to compare to
++ */
++ public EqualPredicate(T object) {
++ super();
++ iValue = object;
++ }
++
++ /**
++ * Evaluates the predicate returning true if the input equals the stored value.
++ *
++ * @param object the input object
++ * @return true if input object equals stored value
++ */
++ public boolean evaluate(T object) {
++ return (iValue.equals(object));
++ }
++
++ /**
++ * Gets the value.
++ *
++ * @return the value
++ * @since Commons Collections 3.1
++ */
++ public T getValue() {
++ return iValue;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/ExceptionClosure.java
+@@ -0,0 +1,71 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Closure;
++import org.apache.commons.collections15.FunctorException;
++
++import java.io.Serializable;
++
++/**
++ * Closure implementation that always throws an exception.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class ExceptionClosure <T> implements Closure<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 7179106032121985545L;
++
++
++ /**
++ * Singleton predicate instance
++ */
++ public static final Closure INSTANCE = new ExceptionClosure();
++
++ /**
++ * Factory returning the singleton instance.
++ *
++ * @return the singleton instance
++ * @since Commons Collections 3.1
++ */
++ public static <T> Closure<T> getInstance() {
++ return INSTANCE;
++ }
++
++ /**
++ * Restricted constructor.
++ */
++ private ExceptionClosure() {
++ super();
++ }
++
++ /**
++ * Always throw an exception.
++ *
++ * @param input the input object
++ * @throws FunctorException always
++ */
++ public void execute(T input) {
++ throw new FunctorException("ExceptionClosure invoked");
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/ExceptionFactory.java
+@@ -0,0 +1,71 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Factory;
++import org.apache.commons.collections15.FunctorException;
++
++import java.io.Serializable;
++
++/**
++ * Factory implementation that always throws an exception.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class ExceptionFactory <T> implements Factory<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 7179106032121985545L;
++
++
++ /**
++ * Singleton predicate instance
++ */
++ public static final Factory INSTANCE = new ExceptionFactory();
++
++ /**
++ * Factory returning the singleton instance.
++ *
++ * @return the singleton instance
++ * @since Commons Collections 3.1
++ */
++ public static <T> Factory<T> getInstance() {
++ return INSTANCE;
++ }
++
++ /**
++ * Restricted constructor.
++ */
++ private ExceptionFactory() {
++ super();
++ }
++
++ /**
++ * Always throws an exception.
++ *
++ * @return never
++ * @throws FunctorException always
++ */
++ public T create() {
++ throw new FunctorException("ExceptionFactory invoked");
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/ExceptionPredicate.java
+@@ -0,0 +1,71 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.FunctorException;
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that always throws an exception.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class ExceptionPredicate <T> implements Predicate<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 7179106032121985545L;
++
++ /**
++ * Singleton predicate instance
++ */
++ public static final Predicate INSTANCE = new ExceptionPredicate();
++
++ /**
++ * Factory returning the singleton instance.
++ *
++ * @return the singleton instance
++ * @since Commons Collections 3.1
++ */
++ public static <T> Predicate<T> getInstance() {
++ return INSTANCE;
++ }
++
++ /**
++ * Restricted constructor.
++ */
++ private ExceptionPredicate() {
++ super();
++ }
++
++ /**
++ * Evaluates the predicate always throwing an exception.
++ *
++ * @param object the input object
++ * @return never
++ * @throws FunctorException always
++ */
++ public boolean evaluate(T object) {
++ throw new FunctorException("ExceptionPredicate invoked");
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/ExceptionTransformer.java
+@@ -0,0 +1,72 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.FunctorException;
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++
++/**
++ * Transformer implementation that always throws an exception.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class ExceptionTransformer <I,O> implements Transformer<I, O>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 7179106032121985545L;
++
++
++ /**
++ * Singleton predicate instance
++ */
++ public static final Transformer INSTANCE = new ExceptionTransformer();
++
++ /**
++ * Factory returning the singleton instance.
++ *
++ * @return the singleton instance
++ * @since Commons Collections 3.1
++ */
++ public static <I,O> Transformer<I,O> getInstance() {
++ return INSTANCE;
++ }
++
++ /**
++ * Restricted constructor.
++ */
++ private ExceptionTransformer() {
++ super();
++ }
++
++ /**
++ * Transforms the input to result by cloning it.
++ *
++ * @param input the input object to transform
++ * @return never
++ * @throws FunctorException always
++ */
++ public O transform(I input) {
++ throw new FunctorException("ExceptionTransformer invoked");
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/FactoryTransformer.java
+@@ -0,0 +1,89 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Factory;
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++
++/**
++ * Transformer implementation that calls a Factory and returns the result.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class FactoryTransformer <I, T> implements Transformer<I, T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -6817674502475353160L;
++
++ /**
++ * The factory to wrap
++ */
++ private final Factory<T> iFactory;
++
++ /**
++ * Factory method that performs validation.
++ *
++ * @param factory the factory to call, not null
++ * @return the <code>factory</code> transformer
++ * @throws IllegalArgumentException if the factory is null
++ */
++ public static <K,T> Transformer<K, T> getInstance(Factory<T> factory) {
++ if (factory == null) {
++ throw new IllegalArgumentException("Factory must not be null");
++ }
++ return new FactoryTransformer<K, T>(factory);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param factory the factory to call, not null
++ */
++ public FactoryTransformer(Factory<T> factory) {
++ super();
++ iFactory = factory;
++ }
++
++ /**
++ * Transforms the input by ignoring the input and returning the result of
++ * calling the decorated factory.
++ *
++ * @param input the input object to transform
++ * @return the transformed result
++ */
++ public T transform(I input) {
++ return iFactory.create();
++ }
++
++ /**
++ * Gets the factory.
++ *
++ * @return the factory
++ * @since Commons Collections 3.1
++ */
++ public Factory<T> getFactory() {
++ return iFactory;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/FalsePredicate.java
+@@ -0,0 +1,69 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that always returns false.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class FalsePredicate <T> implements Predicate<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 7533784454832764388L;
++
++ /**
++ * Singleton predicate instance
++ */
++ public static final Predicate INSTANCE = new FalsePredicate();
++
++ /**
++ * Factory returning the singleton instance.
++ *
++ * @return the singleton instance
++ * @since Commons Collections 3.1
++ */
++ public static <T> Predicate<T> getInstance() {
++ return INSTANCE;
++ }
++
++ /**
++ * Restricted constructor.
++ */
++ private FalsePredicate() {
++ super();
++ }
++
++ /**
++ * Evaluates the predicate returning false always.
++ *
++ * @param object the input object
++ * @return false always
++ */
++ public boolean evaluate(T object) {
++ return false;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/ForClosure.java
+@@ -0,0 +1,110 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Closure;
++
++import java.io.Serializable;
++
++/**
++ * Closure implementation that calls another closure n times, like a for loop.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class ForClosure <T> implements Closure<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -1190120533393621674L;
++
++ /**
++ * The number of times to loop
++ */
++ private final int iCount;
++ /**
++ * The closure to call
++ */
++ private final Closure<T> iClosure;
++
++ /**
++ * Factory method that performs validation.
++ * <p/>
++ * A null closure or zero count returns the <code>NOPClosure</code>.
++ * A count of one returns the specified closure.
++ *
++ * @param count the number of times to execute the closure
++ * @param closure the closure to execute, not null
++ * @return the <code>for</code> closure
++ */
++ public static <T> Closure<T> getInstance(int count, Closure<T> closure) {
++ if (count <= 0 || closure == null) {
++ return NOPClosure.INSTANCE;
++ }
++ if (count == 1) {
++ return closure;
++ }
++ return new ForClosure<T>(count, closure);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param count the number of times to execute the closure
++ * @param closure the closure to execute, not null
++ */
++ public ForClosure(int count, Closure<T> closure) {
++ super();
++ iCount = count;
++ iClosure = closure;
++ }
++
++ /**
++ * Executes the closure <code>count</code> times.
++ *
++ * @param input the input object
++ */
++ public void execute(T input) {
++ for (int i = 0; i < iCount; i++) {
++ iClosure.execute(input);
++ }
++ }
++
++ /**
++ * Gets the closure.
++ *
++ * @return the closure
++ * @since Commons Collections 3.1
++ */
++ public Closure<T> getClosure() {
++ return iClosure;
++ }
++
++ /**
++ * Gets the count.
++ *
++ * @return the count
++ * @since Commons Collections 3.1
++ */
++ public int getCount() {
++ return iCount;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/FunctorUtils.java
+@@ -0,0 +1,174 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Closure;
++import org.apache.commons.collections15.Predicate;
++import org.apache.commons.collections15.Transformer;
++
++import java.util.Collection;
++import java.util.Iterator;
++
++/**
++ * Internal utilities for functors.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++class FunctorUtils {
++
++ /**
++ * Restricted constructor.
++ */
++ private FunctorUtils() {
++ super();
++ }
++
++ /**
++ * Clone the predicates to ensure that the internal reference can't be messed with.
++ *
++ * @param predicates the predicates to copy
++ * @return the cloned predicates
++ */
++ static <T> Predicate<? super T>[] copy(Predicate<? super T>[] predicates) {
++ if (predicates == null) {
++ return null;
++ }
++ return (Predicate<? super T>[]) predicates.clone();
++ }
++
++ /**
++ * Validate the predicates to ensure that all is well.
++ *
++ * @param predicates the predicates to validate
++ */
++ static <T> void validate(Predicate<? super T>[] predicates) {
++ if (predicates == null) {
++ throw new IllegalArgumentException("The predicate array must not be null");
++ }
++ for (int i = 0; i < predicates.length; i++) {
++ if (predicates[i] == null) {
++ throw new IllegalArgumentException("The predicate array must not contain a null predicate, index " + i + " was null");
++ }
++ }
++ }
++
++ /**
++ * Validate the predicates to ensure that all is well.
++ *
++ * @param predicates the predicates to validate
++ */
++ static <T> void validateMin2(Predicate<? super T>[] predicates) {
++ if (predicates == null) {
++ throw new IllegalArgumentException("The predicate array must not be null");
++ }
++ if (predicates.length < 2) {
++ throw new IllegalArgumentException("At least 2 predicates must be specified in the predicate array, size was " + predicates.length);
++ }
++ for (int i = 0; i < predicates.length; i++) {
++ if (predicates[i] == null) {
++ throw new IllegalArgumentException("The predicate array must not contain a null predicate, index " + i + " was null");
++ }
++ }
++ }
++
++ /**
++ * Validate the predicates to ensure that all is well.
++ *
++ * @param predicates the predicates to validate
++ * @return predicate array
++ */
++ static <T> Predicate<? super T>[] validate(Collection<Predicate<? super T>> predicates) {
++ if (predicates == null) {
++ throw new IllegalArgumentException("The predicate collection must not be null");
++ }
++ if (predicates.size() < 2) {
++ throw new IllegalArgumentException("At least 2 predicates must be specified in the predicate collection, size was " + predicates.size());
++ }
++ // convert to array like this to guarantee iterator() ordering
++ Predicate<? super T>[] preds = new Predicate[predicates.size()];
++ int i = 0;
++ for (Iterator<Predicate<? super T>> it = predicates.iterator(); it.hasNext();) {
++ preds[i] = it.next();
++ if (preds[i] == null) {
++ throw new IllegalArgumentException("The predicate collection must not contain a null predicate, index " + i + " was null");
++ }
++ i++;
++ }
++ return preds;
++ }
++
++ /**
++ * Clone the closures to ensure that the internal reference can't be messed with.
++ *
++ * @param closures the closures to copy
++ * @return the cloned closures
++ */
++ static <T> Closure<? super T>[] copy(Closure<? super T>[] closures) {
++ if (closures == null) {
++ return null;
++ }
++ return (Closure<? super T>[]) closures.clone();
++ }
++
++ /**
++ * Validate the closures to ensure that all is well.
++ *
++ * @param closures the closures to validate
++ */
++ static <T> void validate(Closure<? super T>[] closures) {
++ if (closures == null) {
++ throw new IllegalArgumentException("The closure array must not be null");
++ }
++ for (int i = 0; i < closures.length; i++) {
++ if (closures[i] == null) {
++ throw new IllegalArgumentException("The closure array must not contain a null closure, index " + i + " was null");
++ }
++ }
++ }
++
++ /**
++ * Copy method
++ *
++ * @param transformers the transformers to copy
++ * @return a clone of the transformers
++ */
++ static <I,O> Transformer<? super I, ? extends O>[] copy(Transformer<? super I, ? extends O>[] transformers) {
++ if (transformers == null) {
++ return null;
++ }
++ return (Transformer<? super I, ? extends O>[]) transformers.clone();
++ }
++
++ /**
++ * Validate method
++ *
++ * @param transformers the transformers to validate
++ */
++ static <I,O> void validate(Transformer<? super I, ? extends O>[] transformers) {
++ if (transformers == null) {
++ throw new IllegalArgumentException("The transformer array must not be null");
++ }
++ for (int i = 0; i < transformers.length; i++) {
++ if (transformers[i] == null) {
++ throw new IllegalArgumentException("The transformer array must not contain a null transformer, index " + i + " was null");
++ }
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/IdentityPredicate.java
+@@ -0,0 +1,90 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that returns true if the input is the same object
++ * as the one stored in this predicate.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class IdentityPredicate <T> implements Predicate<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -89901658494523293L;
++
++
++ /**
++ * The value to compare to
++ */
++ private final T iValue;
++
++ /**
++ * Factory to create the identity predicate.
++ *
++ * @param object the object to compare to
++ * @return the predicate
++ * @throws IllegalArgumentException if the predicate is null
++ */
++ public static <T> Predicate<T> getInstance(T object) {
++ if (object == null) {
++ return NullPredicate.INSTANCE;
++ }
++ return new IdentityPredicate<T>(object);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param object the object to compare to
++ */
++ public IdentityPredicate(T object) {
++ super();
++ iValue = object;
++ }
++
++ /**
++ * Evaluates the predicate returning true if the input object is identical to
++ * the stored object.
++ *
++ * @param object the input object
++ * @return true if input is the same object as the stored value
++ */
++ public boolean evaluate(T object) {
++ return (iValue == object);
++ }
++
++ /**
++ * Gets the value.
++ *
++ * @return the value
++ * @since Commons Collections 3.1
++ */
++ public T getValue() {
++ return iValue;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/IfClosure.java
+@@ -0,0 +1,129 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Closure;
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Closure implementation acts as an if statement calling one or other closure
++ * based on a predicate.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class IfClosure <T> implements Closure<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 3518477308466486130L;
++
++ /**
++ * The test
++ */
++ private final Predicate<? super T> iPredicate;
++ /**
++ * The closure to use if true
++ */
++ private final Closure<? super T> iTrueClosure;
++ /**
++ * The closure to use if false
++ */
++ private final Closure<? super T> iFalseClosure;
++
++ /**
++ * Factory method that performs validation.
++ *
++ * @param predicate predicate to switch on
++ * @param trueClosure closure used if true
++ * @param falseClosure closure used if false
++ * @return the <code>if</code> closure
++ * @throws IllegalArgumentException if any argument is null
++ */
++ public static <T> Closure<T> getInstance(Predicate<? super T> predicate, Closure<? super T> trueClosure, Closure<? super T> falseClosure) {
++ if (predicate == null) {
++ throw new IllegalArgumentException("Predicate must not be null");
++ }
++ if (trueClosure == null || falseClosure == null) {
++ throw new IllegalArgumentException("Closures must not be null");
++ }
++ return new IfClosure<T>(predicate, trueClosure, falseClosure);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicate predicate to switch on, not null
++ * @param trueClosure closure used if true, not null
++ * @param falseClosure closure used if false, not null
++ */
++ public IfClosure(Predicate<? super T> predicate, Closure<? super T> trueClosure, Closure<? super T> falseClosure) {
++ super();
++ iPredicate = predicate;
++ iTrueClosure = trueClosure;
++ iFalseClosure = falseClosure;
++ }
++
++ /**
++ * Executes the true or false closure accoring to the result of the predicate.
++ *
++ * @param input the input object
++ */
++ public void execute(T input) {
++ if (iPredicate.evaluate(input) == true) {
++ iTrueClosure.execute(input);
++ } else {
++ iFalseClosure.execute(input);
++ }
++ }
++
++ /**
++ * Gets the predicate.
++ *
++ * @return the predicate
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T> getPredicate() {
++ return iPredicate;
++ }
++
++ /**
++ * Gets the closure called when true.
++ *
++ * @return the closure
++ * @since Commons Collections 3.1
++ */
++ public Closure<? super T> getTrueClosure() {
++ return iTrueClosure;
++ }
++
++ /**
++ * Gets the closure called when false.
++ *
++ * @return the closure
++ * @since Commons Collections 3.1
++ */
++ public Closure<? super T> getFalseClosure() {
++ return iFalseClosure;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/InstanceofPredicate.java
+@@ -0,0 +1,90 @@
++// GenericsNote: Converted, although perhaps this should not be templated. Not sure!
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that returns true if the input is an instanceof
++ * the type stored in this predicate.
++ *
++ * Since this predicate operates on the type of the objects passed to it, generics are not used.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class InstanceofPredicate implements Predicate, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -6682656911025165584L;
++
++ /**
++ * The type to compare to
++ */
++ private final Class iType;
++
++ /**
++ * Factory to create the identity predicate.
++ *
++ * @param type the type to check for, may not be null
++ * @return the predicate
++ * @throws IllegalArgumentException if the class is null
++ */
++ public static Predicate getInstance(Class type) {
++ if (type == null) {
++ throw new IllegalArgumentException("The type to check instanceof must not be null");
++ }
++ return new InstanceofPredicate(type);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param type the type to check for
++ */
++ public InstanceofPredicate(Class type) {
++ super();
++ iType = type;
++ }
++
++ /**
++ * Evaluates the predicate returning true if the input object is of the correct type.
++ *
++ * @param object the input object
++ * @return true if input is of stored type
++ */
++ public boolean evaluate(Object object) {
++ return (iType.isInstance(object));
++ }
++
++ /**
++ * Gets the type to compare to.
++ *
++ * @return the type
++ * @since Commons Collections 3.1
++ */
++ public Class getType() {
++ return iType;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/InstantiateFactory.java
+@@ -0,0 +1,147 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Factory;
++import org.apache.commons.collections15.FunctorException;
++
++import java.io.Serializable;
++import java.lang.reflect.Constructor;
++import java.lang.reflect.InvocationTargetException;
++
++/**
++ * Factory implementation that creates a new object instance by reflection.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class InstantiateFactory <T> implements Factory<T>, Serializable {
++
++ /**
++ * The serial version
++ */
++ static final long serialVersionUID = -7732226881069447957L;
++
++ /**
++ * The class to create
++ */
++ private final Class<T> iClassToInstantiate;
++ /**
++ * The constructor parameter types
++ */
++ private final Class[] iParamTypes;
++ /**
++ * The constructor arguments
++ */
++ private final Object[] iArgs;
++ /**
++ * The constructor
++ */
++ private transient Constructor iConstructor = null;
++
++ /**
++ * Factory method that performs validation.
++ *
++ * @param classToInstantiate the class to instantiate, not null
++ * @param paramTypes the constructor parameter types
++ * @param args the constructor arguments
++ * @return a new instantiate factory
++ */
++ public static <T> Factory<T> getInstance(Class<T> classToInstantiate, Class[] paramTypes, Object[] args) {
++ if (classToInstantiate == null) {
++ throw new IllegalArgumentException("Class to instantiate must not be null");
++ }
++ if (((paramTypes == null) && (args != null)) || ((paramTypes != null) && (args == null)) || ((paramTypes != null) && (args != null) && (paramTypes.length != args.length))) {
++ throw new IllegalArgumentException("Parameter types must match the arguments");
++ }
++
++ if (paramTypes == null || paramTypes.length == 0) {
++ return new InstantiateFactory<T>(classToInstantiate);
++ } else {
++ paramTypes = (Class[]) paramTypes.clone();
++ args = (Object[]) args.clone();
++ return new InstantiateFactory<T>(classToInstantiate, paramTypes, args);
++ }
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param classToInstantiate the class to instantiate
++ */
++ public InstantiateFactory(Class<T> classToInstantiate) {
++ super();
++ iClassToInstantiate = classToInstantiate;
++ iParamTypes = null;
++ iArgs = null;
++ findConstructor();
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param classToInstantiate the class to instantiate
++ * @param paramTypes the constructor parameter types, not cloned
++ * @param args the constructor arguments, not cloned
++ */
++ public InstantiateFactory(Class<T> classToInstantiate, Class[] paramTypes, Object[] args) {
++ super();
++ iClassToInstantiate = classToInstantiate;
++ iParamTypes = paramTypes;
++ iArgs = args;
++ findConstructor();
++ }
++
++ /**
++ * Find the Constructor for the class specified.
++ */
++ private void findConstructor() {
++ try {
++ iConstructor = iClassToInstantiate.getConstructor(iParamTypes);
++
++ } catch (NoSuchMethodException ex) {
++ throw new IllegalArgumentException("InstantiateFactory: The constructor must exist and be public ");
++ }
++ }
++
++ /**
++ * Creates an object using the stored constructor.
++ *
++ * @return the new object
++ */
++ public T create() {
++ // needed for post-serialization
++ if (iConstructor == null) {
++ findConstructor();
++ }
++
++ try {
++ return (T) iConstructor.newInstance(iArgs);
++
++ } catch (InstantiationException ex) {
++ throw new FunctorException("InstantiateFactory: InstantiationException", ex);
++ } catch (IllegalAccessException ex) {
++ throw new FunctorException("InstantiateFactory: Constructor must be public", ex);
++ } catch (InvocationTargetException ex) {
++ throw new FunctorException("InstantiateFactory: Constructor threw an exception", ex);
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/InstantiateTransformer.java
+@@ -0,0 +1,119 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.FunctorException;
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++import java.lang.reflect.Constructor;
++import java.lang.reflect.InvocationTargetException;
++
++/**
++ * Transformer implementation that creates a new object instance by reflection.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class InstantiateTransformer implements Transformer<Class, Object>, Serializable {
++
++ /**
++ * The serial version
++ */
++ static final long serialVersionUID = 3786388740793356347L;
++
++ /**
++ * Singleton instance that uses the no arg constructor
++ */
++ public static final InstantiateTransformer NO_ARG_INSTANCE = new InstantiateTransformer();
++
++ /**
++ * The constructor parameter types
++ */
++ private final Class[] iParamTypes;
++ /**
++ * The constructor arguments
++ */
++ private final Object[] iArgs;
++
++ /**
++ * Transformer method that performs validation.
++ *
++ * @param paramTypes the constructor parameter types
++ * @param args the constructor arguments
++ * @return an instantiate transformer
++ */
++ public static InstantiateTransformer getInstance(Class[] paramTypes, Object[] args) {
++ if (((paramTypes == null) && (args != null)) || ((paramTypes != null) && (args == null)) || ((paramTypes != null) && (args != null) && (paramTypes.length != args.length))) {
++ throw new IllegalArgumentException("Parameter types must match the arguments");
++ }
++
++ if (paramTypes == null || paramTypes.length == 0) {
++ return NO_ARG_INSTANCE;
++ } else {
++ paramTypes = (Class[]) paramTypes.clone();
++ args = (Object[]) args.clone();
++ }
++ return new InstantiateTransformer(paramTypes, args);
++ }
++
++ /**
++ * Constructor for no arg instance.
++ */
++ private InstantiateTransformer() {
++ super();
++ iParamTypes = null;
++ iArgs = null;
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param paramTypes the constructor parameter types, not cloned
++ * @param args the constructor arguments, not cloned
++ */
++ public InstantiateTransformer(Class[] paramTypes, Object[] args) {
++ super();
++ iParamTypes = paramTypes;
++ iArgs = args;
++ }
++
++ /**
++ * Transforms the input Class object to a result by instantiation.
++ *
++ * @param input the input object to transform
++ * @return the transformed result
++ */
++ public Object transform(Class input) {
++ try {
++ Constructor con = ((Class) input).getConstructor(iParamTypes);
++ return con.newInstance(iArgs);
++
++ } catch (NoSuchMethodException ex) {
++ throw new FunctorException("InstantiateTransformer: The constructor must exist and be public ");
++ } catch (InstantiationException ex) {
++ throw new FunctorException("InstantiateTransformer: InstantiationException", ex);
++ } catch (IllegalAccessException ex) {
++ throw new FunctorException("InstantiateTransformer: Constructor must be public", ex);
++ } catch (InvocationTargetException ex) {
++ throw new FunctorException("InstantiateTransformer: Constructor threw an exception", ex);
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/InvokerTransformer.java
+@@ -0,0 +1,142 @@
++// GenericsNote: Converted (nothing to convert).
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.FunctorException;
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++import java.lang.reflect.InvocationTargetException;
++import java.lang.reflect.Method;
++
++/**
++ * Transformer implementation that creates a new object instance by reflection.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class InvokerTransformer implements Transformer, Serializable {
++
++ /**
++ * The serial version
++ */
++ static final long serialVersionUID = -8653385846894047688L;
++
++ /**
++ * The method name to call
++ */
++ private final String iMethodName;
++ /**
++ * The array of reflection parameter types
++ */
++ private final Class[] iParamTypes;
++ /**
++ * The array of reflection arguments
++ */
++ private final Object[] iArgs;
++
++ /**
++ * Gets an instance of this transformer calling a specific method with no arguments.
++ *
++ * @param methodName the method name to call
++ * @return an invoker transformer
++ * @since Commons Collections 3.1
++ */
++ public static Transformer getInstance(String methodName) {
++ if (methodName == null) {
++ throw new IllegalArgumentException("The method to invoke must not be null");
++ }
++ return new InvokerTransformer(methodName);
++ }
++
++ /**
++ * Gets an instance of this transformer calling a specific method with specific values.
++ *
++ * @param methodName the method name to call
++ * @param paramTypes the parameter types of the method
++ * @param args the arguments to pass to the method
++ * @return an invoker transformer
++ */
++ public static Transformer getInstance(String methodName, Class[] paramTypes, Object[] args) {
++ if (methodName == null) {
++ throw new IllegalArgumentException("The method to invoke must not be null");
++ }
++ if (((paramTypes == null) && (args != null)) || ((paramTypes != null) && (args == null)) || ((paramTypes != null) && (args != null) && (paramTypes.length != args.length))) {
++ throw new IllegalArgumentException("The parameter types must match the arguments");
++ }
++ if (paramTypes == null || paramTypes.length == 0) {
++ return new InvokerTransformer(methodName);
++ } else {
++ paramTypes = (Class[]) paramTypes.clone();
++ args = (Object[]) args.clone();
++ return new InvokerTransformer(methodName, paramTypes, args);
++ }
++ }
++
++ /**
++ * Constructor for no arg instance.
++ *
++ * @param methodName the method to call
++ */
++ private InvokerTransformer(String methodName) {
++ super();
++ iMethodName = methodName;
++ iParamTypes = null;
++ iArgs = null;
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param methodName the method to call
++ * @param paramTypes the constructor parameter types, not cloned
++ * @param args the constructor arguments, not cloned
++ */
++ public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
++ super();
++ iMethodName = methodName;
++ iParamTypes = paramTypes;
++ iArgs = args;
++ }
++
++ /**
++ * Transforms the input to result by invoking a method on the input.
++ *
++ * @param input the input object to transform
++ * @return the transformed result, null if null input
++ */
++ public Object transform(Object input) {
++ if (input == null) {
++ return null;
++ }
++ try {
++ Class cls = input.getClass();
++ Method method = cls.getMethod(iMethodName, iParamTypes);
++ return method.invoke(input, iArgs);
++
++ } catch (NoSuchMethodException ex) {
++ throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' does not exist");
++ } catch (IllegalAccessException ex) {
++ throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
++ } catch (InvocationTargetException ex) {
++ throw new FunctorException("InvokerTransformer: The method '" + iMethodName + "' on '" + input.getClass() + "' threw an exception", ex);
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/MapTransformer.java
+@@ -0,0 +1,90 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++import java.util.Map;
++
++/**
++ * Transformer implementation that returns the value held in a specified map
++ * using the input parameter as a key.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class MapTransformer <I,O> implements Transformer<I, O>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 862391807045468939L;
++
++ /**
++ * The map of data to lookup in
++ */
++ private final Map<I, O> iMap;
++
++ /**
++ * Factory to create the transformer.
++ * <p/>
++ * If the map is null, a transformer that always returns null is returned.
++ *
++ * @param map the map, not cloned
++ * @return the transformer
++ */
++ public static <I,O> Transformer<I, O> getInstance(Map<I, O> map) {
++ if (map == null) {
++ return ConstantTransformer.NULL_INSTANCE;
++ }
++ return new MapTransformer<I, O>(map);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param map the map to use for lookup, not cloned
++ */
++ private MapTransformer(Map<I, O> map) {
++ super();
++ iMap = map;
++ }
++
++ /**
++ * Transforms the input to result by looking it up in a <code>Map</code>.
++ *
++ * @param input the input object to transform
++ * @return the transformed result
++ */
++ public O transform(I input) {
++ return iMap.get(input);
++ }
++
++ /**
++ * Gets the map to lookup in.
++ *
++ * @return the map
++ * @since Commons Collections 3.1
++ */
++ public Map<I, O> getMap() {
++ return iMap;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/NOPClosure.java
+@@ -0,0 +1,68 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Closure;
++
++import java.io.Serializable;
++
++/**
++ * Closure implementation that does nothing.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class NOPClosure <T> implements Closure<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 3518477308466486130L;
++
++ /**
++ * Singleton predicate instance
++ */
++ public static final Closure INSTANCE = new NOPClosure();
++
++ /**
++ * Factory returning the singleton instance.
++ *
++ * @return the singleton instance
++ * @since Commons Collections 3.1
++ */
++ public static <T> Closure<T> getInstance() {
++ return INSTANCE;
++ }
++
++ /**
++ * Constructor
++ */
++ private NOPClosure() {
++ super();
++ }
++
++ /**
++ * Do nothing.
++ *
++ * @param input the input object
++ */
++ public void execute(T input) {
++ // do nothing
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/NOPTransformer.java
+@@ -0,0 +1,69 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++
++/**
++ * Transformer implementation that does nothing.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class NOPTransformer <I> implements Transformer<I, I>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 2133891748318574490L;
++
++ /**
++ * Singleton predicate instance
++ */
++ public static final Transformer INSTANCE = new NOPTransformer();
++
++ /**
++ * Factory returning the singleton instance.
++ *
++ * @return the singleton instance
++ * @since Commons Collections 3.1
++ */
++ public static <T> Transformer<T,T> getInstance() {
++ return INSTANCE;
++ }
++
++ /**
++ * Constructor
++ */
++ private NOPTransformer() {
++ super();
++ }
++
++ /**
++ * Transforms the input to result by doing nothing.
++ *
++ * @param input the input object to transform
++ * @return the transformed result which is the input
++ */
++ public I transform(I input) {
++ return input;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/NonePredicate.java
+@@ -0,0 +1,108 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++import java.util.Collection;
++
++/**
++ * Predicate implementation that returns true if none of the predicates return true.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class NonePredicate <T> implements Predicate<T>, PredicateDecorator<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 2007613066565892961L;
++
++ /**
++ * The array of predicates to call
++ */
++ private final Predicate<? super T>[] iPredicates;
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @param predicates the predicates to check, cloned, not null
++ * @return the <code>any</code> predicate
++ * @throws IllegalArgumentException if the predicates array is null
++ * @throws IllegalArgumentException if the predicates array has less than 2 elements
++ * @throws IllegalArgumentException if any predicate in the array is null
++ */
++ public static <T> Predicate<T> getInstance(Predicate<? super T>[] predicates) {
++ FunctorUtils.validateMin2(predicates);
++ predicates = FunctorUtils.copy(predicates);
++ return new NonePredicate<T>(predicates);
++ }
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @param predicates the predicates to check, cloned, not null
++ * @return the <code>one</code> predicate
++ * @throws IllegalArgumentException if the predicates array is null
++ * @throws IllegalArgumentException if any predicate in the array is null
++ * @throws IllegalArgumentException if the predicates array has less than 2 elements
++ */
++ public static <T> Predicate<T> getInstance(Collection<Predicate<? super T>> predicates) {
++ Predicate[] preds = FunctorUtils.validate(predicates);
++ return new NonePredicate<T>(preds);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicates the predicates to check, not cloned, not null
++ */
++ public NonePredicate(Predicate[] predicates) {
++ super();
++ iPredicates = predicates;
++ }
++
++ /**
++ * Evaluates the predicate returning false if any stored predicate returns false.
++ *
++ * @param object the input object
++ * @return true if none of decorated predicates return true
++ */
++ public boolean evaluate(T object) {
++ for (int i = 0; i < iPredicates.length; i++) {
++ if (iPredicates[i].evaluate(object)) {
++ return false;
++ }
++ }
++ return true;
++ }
++
++ /**
++ * Gets the predicates, do not modify the array.
++ *
++ * @return the predicates
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T>[] getPredicates() {
++ return iPredicates;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/NotNullPredicate.java
+@@ -0,0 +1,69 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that returns true if the input is not null.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class NotNullPredicate <T> implements Predicate<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 7533784454832764388L;
++
++ /**
++ * Singleton predicate instance
++ */
++ public static final Predicate INSTANCE = new NotNullPredicate();
++
++ /**
++ * Factory returning the singleton instance.
++ *
++ * @return the singleton instance
++ * @since Commons Collections 3.1
++ */
++ public static <T> Predicate<T> getInstance() {
++ return INSTANCE;
++ }
++
++ /**
++ * Restricted constructor.
++ */
++ private NotNullPredicate() {
++ super();
++ }
++
++ /**
++ * Evaluates the predicate returning true if the object does not equal null.
++ *
++ * @param object the object to evaluate
++ * @return true if not null
++ */
++ public boolean evaluate(T object) {
++ return (object != null);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/NotPredicate.java
+@@ -0,0 +1,87 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that returns the opposite of the decorated predicate.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class NotPredicate <T> implements Predicate<T>, PredicateDecorator<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -2654603322338049674L;
++
++ /**
++ * The predicate to decorate
++ */
++ private final Predicate<T> iPredicate;
++
++ /**
++ * Factory to create the not predicate.
++ *
++ * @param predicate the predicate to decorate, not null
++ * @return the predicate
++ * @throws IllegalArgumentException if the predicate is null
++ */
++ public static <T> Predicate<T> getInstance(Predicate<T> predicate) {
++ if (predicate == null) {
++ throw new IllegalArgumentException("Predicate must not be null");
++ }
++ return new NotPredicate<T>(predicate);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicate the predicate to call after the null check
++ */
++ public NotPredicate(Predicate<T> predicate) {
++ super();
++ iPredicate = predicate;
++ }
++
++ /**
++ * Evaluates the predicate returning the opposite to the stored predicate.
++ *
++ * @param object the input object
++ * @return true if predicate returns false
++ */
++ public boolean evaluate(T object) {
++ return !(iPredicate.evaluate(object));
++ }
++
++ /**
++ * Gets the predicate being decorated.
++ *
++ * @return the predicate as the only element in an array
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T>[] getPredicates() {
++ return new Predicate[]{iPredicate};
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/NullIsExceptionPredicate.java
+@@ -0,0 +1,93 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.FunctorException;
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that throws an exception if the input is null.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class NullIsExceptionPredicate <T> implements Predicate<T>, PredicateDecorator<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 3243449850504576071L;
++
++ /**
++ * The predicate to decorate
++ */
++ private final Predicate<T> iPredicate;
++
++ /**
++ * Factory to create the null exception predicate.
++ *
++ * @param predicate the predicate to decorate, not null
++ * @return the predicate
++ * @throws IllegalArgumentException if the predicate is null
++ */
++ public static <T> Predicate<T> getInstance(Predicate<T> predicate) {
++ if (predicate == null) {
++ throw new IllegalArgumentException("Predicate must not be null");
++ }
++ return new NullIsExceptionPredicate<T>(predicate);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicate the predicate to call after the null check
++ */
++ public NullIsExceptionPredicate(Predicate<T> predicate) {
++ super();
++ iPredicate = predicate;
++ }
++
++ /**
++ * Evaluates the predicate returning the result of the decorated predicate
++ * once a null check is performed.
++ *
++ * @param object the input object
++ * @return true if decorated predicate returns true
++ * @throws FunctorException if input is null
++ */
++ public boolean evaluate(T object) {
++ if (object == null) {
++ throw new FunctorException("Input Object must not be null");
++ }
++ return iPredicate.evaluate(object);
++ }
++
++ /**
++ * Gets the predicate being decorated.
++ *
++ * @return the predicate as the only element in an array
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T>[] getPredicates() {
++ return new Predicate[]{iPredicate};
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/NullIsFalsePredicate.java
+@@ -0,0 +1,91 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that returns false if the input is null.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class NullIsFalsePredicate <T> implements Predicate<T>, PredicateDecorator<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -2997501534564735525L;
++
++ /**
++ * The predicate to decorate
++ */
++ private final Predicate<T> iPredicate;
++
++ /**
++ * Factory to create the null false predicate.
++ *
++ * @param predicate the predicate to decorate, not null
++ * @return the predicate
++ * @throws IllegalArgumentException if the predicate is null
++ */
++ public static <T> Predicate<T> getInstance(Predicate<T> predicate) {
++ if (predicate == null) {
++ throw new IllegalArgumentException("Predicate must not be null");
++ }
++ return new NullIsFalsePredicate<T>(predicate);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicate the predicate to call after the null check
++ */
++ public NullIsFalsePredicate(Predicate<T> predicate) {
++ super();
++ iPredicate = predicate;
++ }
++
++ /**
++ * Evaluates the predicate returning the result of the decorated predicate
++ * once a null check is performed.
++ *
++ * @param object the input object
++ * @return true if decorated predicate returns true, false if input is null
++ */
++ public boolean evaluate(T object) {
++ if (object == null) {
++ return false;
++ }
++ return iPredicate.evaluate(object);
++ }
++
++ /**
++ * Gets the predicate being decorated.
++ *
++ * @return the predicate as the only element in an array
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T>[] getPredicates() {
++ return new Predicate[]{iPredicate};
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/NullIsTruePredicate.java
+@@ -0,0 +1,91 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that returns true if the input is null.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class NullIsTruePredicate <T> implements Predicate<T>, PredicateDecorator<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -7625133768987126273L;
++
++ /**
++ * The predicate to decorate
++ */
++ private final Predicate<T> iPredicate;
++
++ /**
++ * Factory to create the null true predicate.
++ *
++ * @param predicate the predicate to decorate, not null
++ * @return the predicate
++ * @throws IllegalArgumentException if the predicate is null
++ */
++ public static <T> Predicate<T> getInstance(Predicate<T> predicate) {
++ if (predicate == null) {
++ throw new IllegalArgumentException("Predicate must not be null");
++ }
++ return new NullIsTruePredicate<T>(predicate);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicate the predicate to call after the null check
++ */
++ public NullIsTruePredicate(Predicate<T> predicate) {
++ super();
++ iPredicate = predicate;
++ }
++
++ /**
++ * Evaluates the predicate returning the result of the decorated predicate
++ * once a null check is performed.
++ *
++ * @param object the input object
++ * @return true if decorated predicate returns true or input is null
++ */
++ public boolean evaluate(T object) {
++ if (object == null) {
++ return true;
++ }
++ return iPredicate.evaluate(object);
++ }
++
++ /**
++ * Gets the predicate being decorated.
++ *
++ * @return the predicate as the only element in an array
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T>[] getPredicates() {
++ return new Predicate[]{iPredicate};
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/NullPredicate.java
+@@ -0,0 +1,69 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that returns true if the input is null.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class NullPredicate <T> implements Predicate<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 7533784454832764388L;
++
++ /**
++ * Singleton predicate instance
++ */
++ public static final Predicate INSTANCE = new NullPredicate();
++
++ /**
++ * Factory returning the singleton instance.
++ *
++ * @return the singleton instance
++ * @since Commons Collections 3.1
++ */
++ public static <T> Predicate<T> getInstance() {
++ return INSTANCE;
++ }
++
++ /**
++ * Restricted constructor.
++ */
++ private NullPredicate() {
++ super();
++ }
++
++ /**
++ * Evaluates the predicate returning true if the input is null.
++ *
++ * @param object the input object
++ * @return true if input is null
++ */
++ public boolean evaluate(T object) {
++ return (object == null);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/OnePredicate.java
+@@ -0,0 +1,113 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++import java.util.Collection;
++
++/**
++ * Predicate implementation that returns true if only one of the predicates return true.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class OnePredicate <T> implements Predicate<T>, PredicateDecorator<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -8125389089924745785L;
++
++ /**
++ * The array of predicates to call
++ */
++ private final Predicate<? super T>[] iPredicates;
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @param predicates the predicates to check, cloned, not null
++ * @return the <code>any</code> predicate
++ * @throws IllegalArgumentException if the predicates array is null
++ * @throws IllegalArgumentException if the predicates array has less than 2 elements
++ * @throws IllegalArgumentException if any predicate in the array is null
++ */
++ public static <T> Predicate<T> getInstance(Predicate<? super T>[] predicates) {
++ FunctorUtils.validateMin2(predicates);
++ predicates = FunctorUtils.copy(predicates);
++ return new OnePredicate<T>(predicates);
++ }
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @param predicates the predicates to check, cloned, not null
++ * @return the <code>one</code> predicate
++ * @throws IllegalArgumentException if the predicates array is null
++ * @throws IllegalArgumentException if any predicate in the array is null
++ * @throws IllegalArgumentException if the predicates array has less than 2 elements
++ */
++ public static <T> Predicate<T> getInstance(Collection<Predicate<? super T>> predicates) {
++ Predicate[] preds = FunctorUtils.validate(predicates);
++ return new OnePredicate<T>(preds);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicates the predicates to check, not cloned, not null
++ */
++ public OnePredicate(Predicate<? super T>[] predicates) {
++ super();
++ iPredicates = predicates;
++ }
++
++ /**
++ * Evaluates the predicate returning true if only one decorated predicate
++ * returns true.
++ *
++ * @param object the input object
++ * @return true if only one decorated predicate returns true
++ */
++ public boolean evaluate(T object) {
++ boolean match = false;
++ for (int i = 0; i < iPredicates.length; i++) {
++ if (iPredicates[i].evaluate(object)) {
++ if (match) {
++ return false;
++ }
++ match = true;
++ }
++ }
++ return match;
++ }
++
++ /**
++ * Gets the predicates, do not modify the array.
++ *
++ * @return the predicates
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T>[] getPredicates() {
++ return iPredicates;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/OrPredicate.java
+@@ -0,0 +1,94 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that returns true if either of the predicates return true.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class OrPredicate <T> implements Predicate<T>, PredicateDecorator<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -8791518325735182855L;
++
++ /**
++ * The array of predicates to call
++ */
++ private final Predicate<? super T> iPredicate1;
++ /**
++ * The array of predicates to call
++ */
++ private final Predicate<? super T> iPredicate2;
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @param predicate1 the first predicate to check, not null
++ * @param predicate2 the second predicate to check, not null
++ * @return the <code>and</code> predicate
++ * @throws IllegalArgumentException if either predicate is null
++ */
++ public static <T> Predicate<T> getInstance(Predicate<? super T> predicate1, Predicate<? super T> predicate2) {
++ if (predicate1 == null || predicate2 == null) {
++ throw new IllegalArgumentException("Predicate must not be null");
++ }
++ return new OrPredicate<T>(predicate1, predicate2);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicate1 the first predicate to check, not null
++ * @param predicate2 the second predicate to check, not null
++ */
++ public OrPredicate(Predicate<? super T> predicate1, Predicate<? super T> predicate2) {
++ super();
++ iPredicate1 = predicate1;
++ iPredicate2 = predicate2;
++ }
++
++ /**
++ * Evaluates the predicate returning true if either predicate returns true.
++ *
++ * @param object the input object
++ * @return true if either decorated predicate returns true
++ */
++ public boolean evaluate(T object) {
++ return (iPredicate1.evaluate(object) || iPredicate2.evaluate(object));
++ }
++
++ /**
++ * Gets the two predicates being decorated as an array.
++ *
++ * @return the predicates
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T>[] getPredicates() {
++ return new Predicate[]{iPredicate1, iPredicate2};
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/PredicateDecorator.java
+@@ -0,0 +1,42 @@
++// GenericsNote: Converted (no generics required).
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++/**
++ * Defines a predicate that decorates one or more other predicates.
++ * <p/>
++ * This interface enables tools to access the decorated predicates.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.1
++ */
++public interface PredicateDecorator <T> extends Predicate<T> {
++
++ /**
++ * Gets the predicates being decorated as an array.
++ * <p/>
++ * The array may be the internal data structure of the predicate and thus
++ * should not be altered.
++ *
++ * @return the predicates being decorated
++ */
++ Predicate<? super T>[] getPredicates();
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/PredicateTransformer.java
+@@ -0,0 +1,89 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++
++/**
++ * Transformer implementation that calls a Predicate using the input object
++ * and then returns the input.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class PredicateTransformer <T> implements Transformer<T, Boolean>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 5278818408044349346L;
++
++ /**
++ * The closure to wrap
++ */
++ private final Predicate<T> iPredicate;
++
++ /**
++ * Factory method that performs validation.
++ *
++ * @param predicate the predicate to call, not null
++ * @return the <code>predicate</code> transformer
++ * @throws IllegalArgumentException if the predicate is null
++ */
++ public static <T> Transformer<T, Boolean> getInstance(Predicate<T> predicate) {
++ if (predicate == null) {
++ throw new IllegalArgumentException("Predicate must not be null");
++ }
++ return new PredicateTransformer<T>(predicate);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicate the predicate to call, not null
++ */
++ public PredicateTransformer(Predicate<T> predicate) {
++ super();
++ iPredicate = predicate;
++ }
++
++ /**
++ * Transforms the input to result by calling a predicate.
++ *
++ * @param input the input object to transform
++ * @return the transformed result
++ */
++ public Boolean transform(T input) {
++ return (iPredicate.evaluate(input) ? Boolean.TRUE : Boolean.FALSE);
++ }
++
++ /**
++ * Gets the predicate.
++ *
++ * @return the predicate
++ * @since Commons Collections 3.1
++ */
++ public Predicate<T> getPredicate() {
++ return iPredicate;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/PrototypeFactory.java
+@@ -0,0 +1,210 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Factory;
++import org.apache.commons.collections15.FunctorException;
++
++import java.io.*;
++import java.lang.reflect.InvocationTargetException;
++import java.lang.reflect.Method;
++
++/**
++ * Factory implementation that creates a new instance each time based on a prototype.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class PrototypeFactory <T> {
++
++ /**
++ * Factory method that performs validation.
++ * <p/>
++ * Creates a Factory that will return a clone of the same prototype object
++ * each time the factory is used. The prototype will be cloned using one of these
++ * techniques (in order):
++ * <ul>
++ * <li>public clone method
++ * <li>public copy constructor
++ * <li>serialization clone
++ * <ul>
++ *
++ * @param prototype the object to clone each time in the factory
++ * @return the <code>prototype</code> factory
++ * @throws IllegalArgumentException if the prototype is null
++ * @throws IllegalArgumentException if the prototype cannot be cloned
++ */
++ public static <T> Factory<T> getInstance(T prototype) {
++ if (prototype == null) {
++ return ConstantFactory.NULL_INSTANCE;
++ }
++ try {
++ Method method = prototype.getClass().getMethod("clone", null);
++ return new PrototypeCloneFactory<T>(prototype, method);
++
++ } catch (NoSuchMethodException ex) {
++ try {
++ prototype.getClass().getConstructor(new Class[]{prototype.getClass()});
++ return new InstantiateFactory<T>((Class<T>) prototype.getClass(), new Class[]{prototype.getClass()}, new Object[]{prototype});
++
++ } catch (NoSuchMethodException ex2) {
++ if (prototype instanceof Serializable) {
++ return new PrototypeSerializationFactory((Serializable) prototype);
++ }
++ }
++ }
++ throw new IllegalArgumentException("The prototype must be cloneable via a public clone method");
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ */
++ private PrototypeFactory() {
++ super();
++ }
++
++ // PrototypeCloneFactory
++ //-----------------------------------------------------------------------
++ /**
++ * PrototypeCloneFactory creates objects by copying a prototype using the clone method.
++ */
++ static class PrototypeCloneFactory <T> implements Factory<T>, Serializable {
++
++ /**
++ * The serial version
++ */
++ static final long serialVersionUID = 5604271422565175555L;
++
++ /**
++ * The object to clone each time
++ */
++ private final T iPrototype;
++ /**
++ * The method used to clone
++ */
++ private transient Method iCloneMethod;
++
++ /**
++ * Constructor to store prototype.
++ */
++ private PrototypeCloneFactory(T prototype, Method method) {
++ super();
++ iPrototype = prototype;
++ iCloneMethod = method;
++ }
++
++ /**
++ * Find the Clone method for the class specified.
++ */
++ private void findCloneMethod() {
++ try {
++ iCloneMethod = iPrototype.getClass().getMethod("clone", null);
++
++ } catch (NoSuchMethodException ex) {
++ throw new IllegalArgumentException("PrototypeCloneFactory: The clone method must exist and be public ");
++ }
++ }
++
++ /**
++ * Creates an object by calling the clone method.
++ *
++ * @return the new object
++ */
++ public T create() {
++ // needed for post-serialization
++ if (iCloneMethod == null) {
++ findCloneMethod();
++ }
++
++ try {
++ return (T) iCloneMethod.invoke(iPrototype, null);
++
++ } catch (IllegalAccessException ex) {
++ throw new FunctorException("PrototypeCloneFactory: Clone method must be public", ex);
++ } catch (InvocationTargetException ex) {
++ throw new FunctorException("PrototypeCloneFactory: Clone method threw an exception", ex);
++ }
++ }
++ }
++
++ // PrototypeSerializationFactory
++ //-----------------------------------------------------------------------
++ /**
++ * PrototypeSerializationFactory creates objects by cloning a prototype using serialization.
++ */
++ static class PrototypeSerializationFactory <T extends Serializable> implements Factory<T>, Serializable {
++
++ /**
++ * The serial version
++ */
++ static final long serialVersionUID = -8704966966139178833L;
++
++ /**
++ * The object to clone via serialization each time
++ */
++ private final Serializable iPrototype;
++
++ /**
++ * Constructor to store prototype
++ */
++ private PrototypeSerializationFactory(Serializable prototype) {
++ super();
++ iPrototype = prototype;
++ }
++
++ /**
++ * Creates an object using serialization.
++ *
++ * @return the new object
++ */
++ public T create() {
++ ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
++ ByteArrayInputStream bais = null;
++ try {
++ ObjectOutputStream out = new ObjectOutputStream(baos);
++ out.writeObject(iPrototype);
++
++ bais = new ByteArrayInputStream(baos.toByteArray());
++ ObjectInputStream in = new ObjectInputStream(bais);
++ return (T) in.readObject();
++
++ } catch (ClassNotFoundException ex) {
++ throw new FunctorException(ex);
++ } catch (IOException ex) {
++ throw new FunctorException(ex);
++ } finally {
++ try {
++ if (bais != null) {
++ bais.close();
++ }
++ } catch (IOException ex) {
++ // ignore
++ }
++ try {
++ if (baos != null) {
++ baos.close();
++ }
++ } catch (IOException ex) {
++ // ignore
++ }
++ }
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/StringValueTransformer.java
+@@ -0,0 +1,64 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++
++/**
++ * Transformer implementation that returns the <code>String.valueOf</code>.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class StringValueTransformer <T> implements Transformer<T, String>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 7511110693171758606L;
++
++ /**
++ * Factory returning the singleton instance.
++ *
++ * @return the singleton instance
++ * @since Commons Collections 3.1
++ */
++ public static <T> Transformer<T, String> getInstance() {
++ return new StringValueTransformer<T>();
++ }
++
++ /**
++ * Restricted constructor.
++ */
++ private StringValueTransformer() {
++ super();
++ }
++
++ /**
++ * Transforms the input to result by calling <code>String.valueOf</code>.
++ *
++ * @param input the input object to transform
++ * @return the transformed result
++ */
++ public String transform(T input) {
++ return String.valueOf(input);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/SwitchClosure.java
+@@ -0,0 +1,182 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Closure;
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++import java.util.Iterator;
++import java.util.Map;
++
++/**
++ * Closure implementation calls the closure whose predicate returns true,
++ * like a switch statement.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class SwitchClosure <T> implements Closure<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 3518477308466486130L;
++
++ /**
++ * The tests to consider
++ */
++ private final Predicate<? super T>[] iPredicates;
++ /**
++ * The matching closures to call
++ */
++ private final Closure<? super T>[] iClosures;
++ /**
++ * The default closure to call if no tests match
++ */
++ private final Closure<? super T> iDefault;
++
++ /**
++ * Factory method that performs validation and copies the parameter arrays.
++ *
++ * @param predicates array of predicates, cloned, no nulls
++ * @param closures matching array of closures, cloned, no nulls
++ * @param defaultClosure the closure to use if no match, null means nop
++ * @return the <code>chained</code> closure
++ * @throws IllegalArgumentException if array is null
++ * @throws IllegalArgumentException if any element in the array is null
++ */
++ public static <T> Closure<T> getInstance(Predicate<? super T>[] predicates, Closure<? super T>[] closures, Closure<? super T> defaultClosure) {
++ FunctorUtils.validate(predicates);
++ FunctorUtils.validate(closures);
++ if (predicates.length != closures.length) {
++ throw new IllegalArgumentException("The predicate and closure arrays must be the same size");
++ }
++ if (predicates.length == 0) {
++ return (defaultClosure == null ? NOPClosure.INSTANCE : defaultClosure);
++ }
++ predicates = FunctorUtils.copy(predicates);
++ closures = FunctorUtils.copy(closures);
++ return new SwitchClosure<T>(predicates, closures, defaultClosure);
++ }
++
++ /**
++ * Create a new Closure that calls one of the closures depending
++ * on the predicates.
++ * <p/>
++ * The Map consists of Predicate keys and Closure values. A closure
++ * is called if its matching predicate returns true. Each predicate is evaluated
++ * until one returns true. If no predicates evaluate to true, the default
++ * closure is called. The default closure is set in the map with a
++ * null key. The ordering is that of the iterator() method on the entryset
++ * collection of the map.
++ *
++ * @param predicatesAndClosures a map of predicates to closures
++ * @return the <code>switch</code> closure
++ * @throws IllegalArgumentException if the map is null
++ * @throws IllegalArgumentException if any closure in the map is null
++ * @throws ClassCastException if the map elements are of the wrong type
++ */
++ public static <T> Closure<T> getInstance(Map<Predicate<? super T>, Closure<? super T>> predicatesAndClosures) {
++ Closure[] closures = null;
++ Predicate[] preds = null;
++ if (predicatesAndClosures == null) {
++ throw new IllegalArgumentException("The predicate and closure map must not be null");
++ }
++ if (predicatesAndClosures.size() == 0) {
++ return NOPClosure.INSTANCE;
++ }
++ // convert to array like this to guarantee iterator() ordering
++ Closure defaultClosure = (Closure) predicatesAndClosures.remove(null);
++ int size = predicatesAndClosures.size();
++ if (size == 0) {
++ return (defaultClosure == null ? NOPClosure.INSTANCE : defaultClosure);
++ }
++ closures = new Closure[size];
++ preds = new Predicate[size];
++ int i = 0;
++ for (Iterator it = predicatesAndClosures.entrySet().iterator(); it.hasNext();) {
++ Map.Entry entry = (Map.Entry) it.next();
++ preds[i] = (Predicate<? super T>) entry.getKey();
++ closures[i] = (Closure<? super T>) entry.getValue();
++ i++;
++ }
++ return new SwitchClosure<T>(preds, closures, defaultClosure);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicates array of predicates, not cloned, no nulls
++ * @param closures matching array of closures, not cloned, no nulls
++ * @param defaultClosure the closure to use if no match, null means nop
++ */
++ public SwitchClosure(Predicate<? super T>[] predicates, Closure<? super T>[] closures, Closure<? super T> defaultClosure) {
++ super();
++ iPredicates = predicates;
++ iClosures = closures;
++ iDefault = (defaultClosure == null ? NOPClosure.INSTANCE : defaultClosure);
++ }
++
++ /**
++ * Executes the closure whose matching predicate returns true
++ *
++ * @param input the input object
++ */
++ public void execute(T input) {
++ for (int i = 0; i < iPredicates.length; i++) {
++ if (iPredicates[i].evaluate(input) == true) {
++ iClosures[i].execute(input);
++ return;
++ }
++ }
++ iDefault.execute(input);
++ }
++
++ /**
++ * Gets the predicates, do not modify the array.
++ *
++ * @return the predicates
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T>[] getPredicates() {
++ return iPredicates;
++ }
++
++ /**
++ * Gets the closures, do not modify the array.
++ *
++ * @return the closures
++ * @since Commons Collections 3.1
++ */
++ public Closure<? super T>[] getClosures() {
++ return iClosures;
++ }
++
++ /**
++ * Gets the default closure.
++ *
++ * @return the default closure
++ * @since Commons Collections 3.1
++ */
++ public Closure<? super T> getDefaultClosure() {
++ return iDefault;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/SwitchTransformer.java
+@@ -0,0 +1,183 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++import java.util.Iterator;
++import java.util.Map;
++
++/**
++ * Transformer implementation calls the transformer whose predicate returns true,
++ * like a switch statement.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class SwitchTransformer <I,O> implements Transformer<I, O>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -6404460890903469332L;
++
++ /**
++ * The tests to consider
++ */
++ private final Predicate<? super I>[] iPredicates;
++ /**
++ * The matching transformers to call
++ */
++ private final Transformer<? super I, ? extends O>[] iTransformers;
++ /**
++ * The default transformer to call if no tests match
++ */
++ private final Transformer<? super I, ? extends O> iDefault;
++
++ /**
++ * Factory method that performs validation and copies the parameter arrays.
++ *
++ * @param predicates array of predicates, cloned, no nulls
++ * @param transformers matching array of transformers, cloned, no nulls
++ * @param defaultTransformer the transformer to use if no match, null means nop
++ * @return the <code>chained</code> transformer
++ * @throws IllegalArgumentException if array is null
++ * @throws IllegalArgumentException if any element in the array is null
++ */
++ public static <I,O> Transformer<I, O> getInstance(Predicate<? super I>[] predicates, Transformer<? super I, ? extends O>[] transformers, Transformer<? super I, ? extends O> defaultTransformer) {
++ FunctorUtils.validate(predicates);
++ FunctorUtils.validate(transformers);
++ if (predicates.length != transformers.length) {
++ throw new IllegalArgumentException("The predicate and transformer arrays must be the same size");
++ }
++ if (predicates.length == 0) {
++ return (defaultTransformer == null ? ConstantTransformer.NULL_INSTANCE : defaultTransformer);
++ }
++ predicates = FunctorUtils.copy(predicates);
++ transformers = FunctorUtils.copy(transformers);
++ return new SwitchTransformer<I, O>(predicates, transformers, defaultTransformer);
++ }
++
++ /**
++ * Create a new Transformer that calls one of the transformers depending
++ * on the predicates.
++ * <p/>
++ * The Map consists of Predicate keys and Transformer values. A transformer
++ * is called if its matching predicate returns true. Each predicate is evaluated
++ * until one returns true. If no predicates evaluate to true, the default
++ * transformer is called. The default transformer is set in the map with a
++ * null key. The ordering is that of the iterator() method on the entryset
++ * collection of the map.
++ *
++ * @param predicatesAndTransformers a map of predicates to transformers
++ * @return the <code>switch</code> transformer
++ * @throws IllegalArgumentException if the map is null
++ * @throws IllegalArgumentException if any transformer in the map is null
++ * @throws ClassCastException if the map elements are of the wrong type
++ */
++ public static <I,O> Transformer<I, O> getInstance(Map<Predicate<? super I>, Transformer<? super I, ? extends O>> predicatesAndTransformers) {
++ Transformer<? super I, ? extends O>[] transformers = null;
++ Predicate<? super I>[] preds = null;
++ if (predicatesAndTransformers == null) {
++ throw new IllegalArgumentException("The predicate and transformer map must not be null");
++ }
++ if (predicatesAndTransformers.size() == 0) {
++ return ConstantTransformer.NULL_INSTANCE;
++ }
++ // convert to array like this to guarantee iterator() ordering
++ Transformer<? super I, ? extends O> defaultTransformer = predicatesAndTransformers.remove(null);
++ int size = predicatesAndTransformers.size();
++ if (size == 0) {
++ return (defaultTransformer == null ? ConstantTransformer.NULL_INSTANCE : defaultTransformer);
++ }
++ transformers = new Transformer[size];
++ preds = new Predicate[size];
++ int i = 0;
++ for (Iterator<Map.Entry<Predicate<? super I>, Transformer<? super I, ? extends O>>> it = predicatesAndTransformers.entrySet().iterator(); it.hasNext();) {
++ Map.Entry<Predicate<? super I>, Transformer<? super I, ? extends O>> entry = it.next();
++ preds[i] = entry.getKey();
++ transformers[i] = entry.getValue();
++ i++;
++ }
++ return new SwitchTransformer<I, O>(preds, transformers, defaultTransformer);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicates array of predicates, not cloned, no nulls
++ * @param transformers matching array of transformers, not cloned, no nulls
++ * @param defaultTransformer the transformer to use if no match, null means nop
++ */
++ public SwitchTransformer(Predicate<? super I>[] predicates, Transformer<? super I, ? extends O>[] transformers, Transformer<? super I, ? extends O> defaultTransformer) {
++ super();
++ iPredicates = predicates;
++ iTransformers = transformers;
++ iDefault = (defaultTransformer == null ? ConstantTransformer.NULL_INSTANCE : defaultTransformer);
++ }
++
++ /**
++ * Transforms the input to result by calling the transformer whose matching
++ * predicate returns true.
++ *
++ * @param input the input object to transform
++ * @return the transformed result
++ */
++ public O transform(I input) {
++ for (int i = 0; i < iPredicates.length; i++) {
++ if (iPredicates[i].evaluate(input) == true) {
++ return iTransformers[i].transform(input);
++ }
++ }
++ return (O) iDefault.transform(input);
++ }
++
++ /**
++ * Gets the predicates, do not modify the array.
++ *
++ * @return the predicates
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super I>[] getPredicates() {
++ return iPredicates;
++ }
++
++ /**
++ * Gets the transformers, do not modify the array.
++ *
++ * @return the transformers
++ * @since Commons Collections 3.1
++ */
++ public Transformer<? super I, ? extends O>[] getTransformers() {
++ return iTransformers;
++ }
++
++ /**
++ * Gets the default transformer.
++ *
++ * @return the default transformer
++ * @since Commons Collections 3.1
++ */
++ public Transformer<? super I, ? extends O> getDefaultTransformer() {
++ return iDefault;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/TransformedPredicate.java
+@@ -0,0 +1,115 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that transforms the given object before invoking
++ * another <code>Predicate</code>.
++ * <p>
++ * Note: This class cannot suppport generics without breaking the {@link PredicateDecorator} interface.
++ *
++ * @author Matt Hall, John Watkinson, Alban Peignier
++ * @author Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.1
++ */
++public final class TransformedPredicate <I,O> implements Predicate<I>, PredicateDecorator<I>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -5596090919668315834L;
++
++ /**
++ * The transformer to call
++ */
++ private final Transformer<? super I, ? extends O> iTransformer;
++ /**
++ * The predicate to call
++ */
++ private final Predicate<? super O> iPredicate;
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @param transformer the transformer to call
++ * @param predicate the predicate to call with the result of the transform
++ * @return the predicate
++ * @throws IllegalArgumentException if the transformer or the predicate is null
++ */
++ public static <I,O> Predicate<I> getInstance(Transformer<? super I, ? extends O> transformer, Predicate<? super O> predicate) {
++ if (transformer == null) {
++ throw new IllegalArgumentException("The transformer to call must not be null");
++ }
++ if (predicate == null) {
++ throw new IllegalArgumentException("The predicate to call must not be null");
++ }
++ return new TransformedPredicate<I, O>(transformer, predicate);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param transformer the transformer to use
++ * @param predicate the predicate to decorate
++ */
++ public TransformedPredicate(Transformer<? super I, ? extends O> transformer, Predicate<? super O> predicate) {
++ iTransformer = transformer;
++ iPredicate = predicate;
++ }
++
++ /**
++ * Evaluates the predicate returning the result of the decorated predicate
++ * once the input has been transformed
++ *
++ * @param object the input object which will be transformed
++ * @return true if decorated predicate returns true
++ */
++ public boolean evaluate(I object) {
++ O result = iTransformer.transform(object);
++ return iPredicate.evaluate(result);
++ }
++
++ /**
++ * Gets the predicate being decorated.
++ * <p/>
++ * Not type-safe in 1.5.
++ * <p/>
++ *
++ * @return the predicate as the only element in an array
++ * @since Commons Collections 3.1
++ */
++ public Predicate[] getPredicates() {
++ return new Predicate[]{iPredicate};
++ }
++
++ /**
++ * Gets the transformer in use.
++ *
++ * @return the transformer
++ */
++ public Transformer<? super I, ? extends O> getTransformer() {
++ return iTransformer;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/TransformerClosure.java
+@@ -0,0 +1,89 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Closure;
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++
++/**
++ * Closure implementation that calls a Transformer using the input object
++ * and ignore the result.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class TransformerClosure <I,O> implements Closure<I>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -5194992589193388969L;
++
++ /**
++ * The transformer to wrap
++ */
++ private final Transformer<? super I, O> iTransformer;
++
++ /**
++ * Factory method that performs validation.
++ * <p/>
++ * A null transformer will return the <code>NOPClosure</code>.
++ *
++ * @param transformer the transformer to call, null means nop
++ * @return the <code>transformer</code> closure
++ */
++ public static <I,O> Closure<I> getInstance(Transformer<? super I, O> transformer) {
++ if (transformer == null) {
++ return NOPClosure.INSTANCE;
++ }
++ return new TransformerClosure<I, O>(transformer);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param transformer the transformer to call, not null
++ */
++ public TransformerClosure(Transformer<? super I, O> transformer) {
++ super();
++ iTransformer = transformer;
++ }
++
++ /**
++ * Executes the closure by calling the decorated transformer.
++ *
++ * @param input the input object
++ */
++ public void execute(I input) {
++ iTransformer.transform(input);
++ }
++
++ /**
++ * Gets the transformer.
++ *
++ * @return the transformer
++ * @since Commons Collections 3.1
++ */
++ public Transformer<? super I, O> getTransformer() {
++ return iTransformer;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/TransformerPredicate.java
+@@ -0,0 +1,94 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.FunctorException;
++import org.apache.commons.collections15.Predicate;
++import org.apache.commons.collections15.Transformer;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that returns the result of a transformer.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class TransformerPredicate <T> implements Predicate<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -2407966402920578741L;
++
++ /**
++ * The transformer to call
++ */
++ private final Transformer<T, Boolean> iTransformer;
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @param transformer the transformer to decorate
++ * @return the predicate
++ * @throws IllegalArgumentException if the transformer is null
++ */
++ public static <T> Predicate<T> getInstance(Transformer<T, Boolean> transformer) {
++ if (transformer == null) {
++ throw new IllegalArgumentException("The transformer to call must not be null");
++ }
++ return new TransformerPredicate<T>(transformer);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param transformer the transformer to decorate
++ */
++ public TransformerPredicate(Transformer<T, Boolean> transformer) {
++ super();
++ iTransformer = transformer;
++ }
++
++ /**
++ * Evaluates the predicate returning the result of the decorated transformer.
++ *
++ * @param object the input object
++ * @return true if decorated transformer returns Boolean.TRUE
++ * @throws FunctorException if the transformer returns an invalid type
++ */
++ public boolean evaluate(T object) {
++ Boolean result = iTransformer.transform(object);
++ if (result == null) {
++ throw new FunctorException("Transformer must return an instanceof Boolean, it was a " + (result == null ? "null object" : result.getClass().getName()));
++ }
++ return result.booleanValue();
++ }
++
++ /**
++ * Gets the transformer.
++ *
++ * @return the transformer
++ * @since Commons Collections 3.1
++ */
++ public Transformer<T, Boolean> getTransformer() {
++ return iTransformer;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/TruePredicate.java
+@@ -0,0 +1,69 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Predicate implementation that always returns true.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class TruePredicate <T> implements Predicate<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = 3374767158756189740L;
++
++ /**
++ * Singleton predicate instance
++ */
++ public static final Predicate INSTANCE = new TruePredicate();
++
++ /**
++ * Factory returning the singleton instance.
++ *
++ * @return the singleton instance
++ * @since Commons Collections 3.1
++ */
++ public static <T> Predicate<T> getInstance() {
++ return INSTANCE;
++ }
++
++ /**
++ * Restricted constructor.
++ */
++ private TruePredicate() {
++ super();
++ }
++
++ /**
++ * Evaluates the predicate returning true always.
++ *
++ * @param object the input object
++ * @return true always
++ */
++ public boolean evaluate(T object) {
++ return true;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/UniquePredicate.java
+@@ -0,0 +1,74 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++import java.util.HashSet;
++import java.util.Set;
++
++/**
++ * Predicate implementation that returns true the first time an object is
++ * passed into the predicate.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class UniquePredicate <T> implements Predicate<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -3319417438027438040L;
++
++ /**
++ * The set of previously seen objects
++ */
++ private final Set<T> iSet = new HashSet<T>();
++
++ /**
++ * Factory to create the predicate.
++ *
++ * @return the predicate
++ * @throws IllegalArgumentException if the predicate is null
++ */
++ public static <T> Predicate<T> getInstance() {
++ return new UniquePredicate<T>();
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ */
++ public UniquePredicate() {
++ super();
++ }
++
++ /**
++ * Evaluates the predicate returning true if the input object hasn't been
++ * received yet.
++ *
++ * @param object the input object
++ * @return true if this is the first time the object is seen
++ */
++ public boolean evaluate(T object) {
++ return iSet.add(object);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/WhileClosure.java
+@@ -0,0 +1,130 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.functors;
++
++import org.apache.commons.collections15.Closure;
++import org.apache.commons.collections15.Predicate;
++
++import java.io.Serializable;
++
++/**
++ * Closure implementation that executes a closure repeatedly until a condition is met,
++ * like a do-while or while loop.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class WhileClosure <T> implements Closure<T>, Serializable {
++
++ /**
++ * Serial version UID
++ */
++ static final long serialVersionUID = -3110538116913760108L;
++
++ /**
++ * The test condition
++ */
++ private final Predicate<? super T> iPredicate;
++ /**
++ * The closure to call
++ */
++ private final Closure<? super T> iClosure;
++ /**
++ * The flag, true is a do loop, false is a while
++ */
++ private final boolean iDoLoop;
++
++ /**
++ * Factory method that performs validation.
++ *
++ * @param predicate the predicate used to evaluate when the loop terminates, not null
++ * @param closure the closure the execute, not null
++ * @param doLoop true to act as a do-while loop, always executing the closure once
++ * @return the <code>while</code> closure
++ * @throws IllegalArgumentException if the predicate or closure is null
++ */
++ public static <T> Closure<T> getInstance(Predicate<? super T> predicate, Closure<? super T> closure, boolean doLoop) {
++ if (predicate == null) {
++ throw new IllegalArgumentException("Predicate must not be null");
++ }
++ if (closure == null) {
++ throw new IllegalArgumentException("Closure must not be null");
++ }
++ return new WhileClosure<T>(predicate, closure, doLoop);
++ }
++
++ /**
++ * Constructor that performs no validation.
++ * Use <code>getInstance</code> if you want that.
++ *
++ * @param predicate the predicate used to evaluate when the loop terminates, not null
++ * @param closure the closure the execute, not null
++ * @param doLoop true to act as a do-while loop, always executing the closure once
++ */
++ public WhileClosure(Predicate<? super T> predicate, Closure<? super T> closure, boolean doLoop) {
++ super();
++ iPredicate = predicate;
++ iClosure = closure;
++ iDoLoop = doLoop;
++ }
++
++ /**
++ * Executes the closure until the predicate is false.
++ *
++ * @param input the input object
++ */
++ public void execute(T input) {
++ if (iDoLoop) {
++ iClosure.execute(input);
++ }
++ while (iPredicate.evaluate(input)) {
++ iClosure.execute(input);
++ }
++ }
++
++ /**
++ * Gets the predicate in use.
++ *
++ * @return the predicate
++ * @since Commons Collections 3.1
++ */
++ public Predicate<? super T> getPredicate() {
++ return iPredicate;
++ }
++
++ /**
++ * Gets the closure.
++ *
++ * @return the closure
++ * @since Commons Collections 3.1
++ */
++ public Closure<? super T> getClosure() {
++ return iClosure;
++ }
++
++ /**
++ * Is the loop a do-while loop.
++ *
++ * @return true is do-while, false if while
++ * @since Commons Collections 3.1
++ */
++ public boolean isDoLoop() {
++ return iDoLoop;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/functors/package.html
+@@ -0,0 +1,26 @@
++<!-- $Id: package.html,v 1.1 2005/10/11 17:05:24 pents90 Exp $ -->
++ <!--
++ Copyright 2003-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<BODY>
++<p>
++This package contains implementations of the
++{@link org.apache.commons.collections.Closure Closure},
++{@link org.apache.commons.collections.Predicate Predicate},
++{@link org.apache.commons.collections.Predicate Transformer} and
++{@link org.apache.commons.collections.Predicate Factory} interfaces.
++These provide simple callbacks for processing with collections.
++</pre>
++</BODY>
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/AbstractEmptyIterator.java
+@@ -0,0 +1,89 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import java.util.NoSuchElementException;
++
++/**
++ * Provides an implementation of an empty iterator.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.1
++ */
++abstract class AbstractEmptyIterator <E> {
++
++ /**
++ * Constructor.
++ */
++ protected AbstractEmptyIterator() {
++ super();
++ }
++
++ public boolean hasNext() {
++ return false;
++ }
++
++ public E next() {
++ throw new NoSuchElementException("Iterator contains no elements");
++ }
++
++ public boolean hasPrevious() {
++ return false;
++ }
++
++ public E previous() {
++ throw new NoSuchElementException("Iterator contains no elements");
++ }
++
++ public int nextIndex() {
++ return 0;
++ }
++
++ public int previousIndex() {
++ return -1;
++ }
++
++ public void add(E obj) {
++ throw new UnsupportedOperationException("add() not supported for empty Iterator");
++ }
++
++ public void set(E obj) {
++ throw new IllegalStateException("Iterator contains no elements");
++ }
++
++ public void remove() {
++ throw new IllegalStateException("Iterator contains no elements");
++ }
++
++ public E getKey() {
++ throw new IllegalStateException("Iterator contains no elements");
++ }
++
++ public E getValue() {
++ throw new IllegalStateException("Iterator contains no elements");
++ }
++
++ public E setValue(E value) {
++ throw new IllegalStateException("Iterator contains no elements");
++ }
++
++ public void reset() {
++ // do nothing
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/AbstractIteratorDecorator.java
+@@ -0,0 +1,75 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import java.util.Iterator;
++
++/**
++ * Provides basic behaviour for decorating an iterator with extra functionality.
++ * <p/>
++ * All methods are forwarded to the decorated iterator.
++ *
++ * @author Matt Hall, John Watkinson, James Strachan
++ * @author Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class AbstractIteratorDecorator <E> implements Iterator<E> {
++
++ /**
++ * The iterator being decorated
++ */
++ protected final Iterator<E> iterator;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that decorates the specified iterator.
++ *
++ * @param iterator the iterator to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ public AbstractIteratorDecorator(Iterator<E> iterator) {
++ super();
++ if (iterator == null) {
++ throw new IllegalArgumentException("Iterator must not be null");
++ }
++ this.iterator = iterator;
++ }
++
++ /**
++ * Gets the iterator being decorated.
++ *
++ * @return the decorated iterator
++ */
++ protected Iterator<E> getIterator() {
++ return iterator;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ public E next() {
++ return iterator.next();
++ }
++
++ public void remove() {
++ iterator.remove();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/AbstractListIteratorDecorator.java
+@@ -0,0 +1,99 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import java.util.ListIterator;
++
++/**
++ * Provides basic behaviour for decorating a list iterator with extra functionality.
++ * <p/>
++ * All methods are forwarded to the decorated list iterator.
++ *
++ * @author Rodney Waldhoff
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class AbstractListIteratorDecorator <E> implements ListIterator<E> {
++
++ /**
++ * The iterator being decorated
++ */
++ protected final ListIterator<E> iterator;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that decorates the specified iterator.
++ *
++ * @param iterator the iterator to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ public AbstractListIteratorDecorator(ListIterator<E> iterator) {
++ super();
++ if (iterator == null) {
++ throw new IllegalArgumentException("ListIterator must not be null");
++ }
++ this.iterator = iterator;
++ }
++
++ /**
++ * Gets the iterator being decorated.
++ *
++ * @return the decorated iterator
++ */
++ protected ListIterator<E> getListIterator() {
++ return iterator;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ public E next() {
++ return iterator.next();
++ }
++
++ public int nextIndex() {
++ return iterator.nextIndex();
++ }
++
++ public boolean hasPrevious() {
++ return iterator.hasPrevious();
++ }
++
++ public E previous() {
++ return iterator.previous();
++ }
++
++ public int previousIndex() {
++ return iterator.previousIndex();
++ }
++
++ public void remove() {
++ iterator.remove();
++ }
++
++ public void set(E obj) {
++ iterator.set(obj);
++ }
++
++ public void add(E obj) {
++ iterator.add(obj);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/AbstractMapIteratorDecorator.java
+@@ -0,0 +1,86 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.MapIterator;
++
++/**
++ * Provides basic behaviour for decorating a map iterator with extra functionality.
++ * <p/>
++ * All methods are forwarded to the decorated map iterator.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class AbstractMapIteratorDecorator <K,V> implements MapIterator<K, V> {
++
++ /**
++ * The iterator being decorated
++ */
++ protected final MapIterator<K, V> iterator;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that decorates the specified iterator.
++ *
++ * @param iterator the iterator to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ public AbstractMapIteratorDecorator(MapIterator<K, V> iterator) {
++ super();
++ if (iterator == null) {
++ throw new IllegalArgumentException("MapIterator must not be null");
++ }
++ this.iterator = iterator;
++ }
++
++ /**
++ * Gets the iterator being decorated.
++ *
++ * @return the decorated iterator
++ */
++ protected MapIterator<K, V> getMapIterator() {
++ return iterator;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ public K next() {
++ return iterator.next();
++ }
++
++ public void remove() {
++ iterator.remove();
++ }
++
++ public K getKey() {
++ return iterator.getKey();
++ }
++
++ public V getValue() {
++ return iterator.getValue();
++ }
++
++ public V setValue(V obj) {
++ return iterator.setValue(obj);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/AbstractOrderedMapIteratorDecorator.java
+@@ -0,0 +1,94 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.OrderedMapIterator;
++
++/**
++ * Provides basic behaviour for decorating an ordered map iterator with extra functionality.
++ * <p/>
++ * All methods are forwarded to the decorated map iterator.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class AbstractOrderedMapIteratorDecorator <K,V> implements OrderedMapIterator<K, V> {
++
++ /**
++ * The iterator being decorated
++ */
++ protected final OrderedMapIterator<K, V> iterator;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that decorates the specified iterator.
++ *
++ * @param iterator the iterator to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ public AbstractOrderedMapIteratorDecorator(OrderedMapIterator<K, V> iterator) {
++ super();
++ if (iterator == null) {
++ throw new IllegalArgumentException("OrderedMapIterator must not be null");
++ }
++ this.iterator = iterator;
++ }
++
++ /**
++ * Gets the iterator being decorated.
++ *
++ * @return the decorated iterator
++ */
++ protected OrderedMapIterator<K, V> getOrderedMapIterator() {
++ return iterator;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ public K next() {
++ return iterator.next();
++ }
++
++ public boolean hasPrevious() {
++ return iterator.hasPrevious();
++ }
++
++ public K previous() {
++ return iterator.previous();
++ }
++
++ public void remove() {
++ iterator.remove();
++ }
++
++ public K getKey() {
++ return iterator.getKey();
++ }
++
++ public V getValue() {
++ return iterator.getValue();
++ }
++
++ public V setValue(V obj) {
++ return iterator.setValue(obj);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/ArrayIterator.java
+@@ -0,0 +1,224 @@
++// GenericsNote: Converted, although unsatisfying because there does not seem to be a way to generify the primitive types.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.ResettableIterator;
++
++import java.lang.reflect.Array;
++import java.util.NoSuchElementException;
++
++/**
++ * Implements an {@link java.util.Iterator Iterator} over any array.
++ * <p/>
++ * The array can be either an array of object or of primitives. If you know
++ * that you have an object array, the
++ * {@link org.apache.commons.collections15.iterators.ObjectArrayIterator ObjectArrayIterator}
++ * class is a better choice, as it will perform better.
++ * <p/>
++ * The iterator implements a {@link #reset} method, allowing the reset of
++ * the iterator back to the start if required.
++ *
++ * @author James Strachan
++ * @author Mauricio S. Moura
++ * @author Michael A. Smith
++ * @author Neil O'Toole
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 1.0
++ */
++public class ArrayIterator <E> implements ResettableIterator<E> {
++
++ /**
++ * The array to iterate over
++ */
++ protected Object array;
++ /**
++ * The start index to loop from
++ */
++ protected int startIndex = 0;
++ /**
++ * The end index to loop to
++ */
++ protected int endIndex = 0;
++ /**
++ * The current iterator index
++ */
++ protected int index = 0;
++
++ // Constructors
++ // ----------------------------------------------------------------------
++ /**
++ * Constructor for use with <code>setArray</code>.
++ * <p/>
++ * Using this constructor, the iterator is equivalent to an empty iterator
++ * until {@link #setArray(Object)} is called to establish the array to iterate over.
++ */
++ public ArrayIterator() {
++ super();
++ }
++
++ /**
++ * Constructs an ArrayIterator that will iterate over the values in the
++ * specified array.
++ *
++ * @param array the array to iterate over.
++ * @throws IllegalArgumentException if <code>array</code> is not an array.
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ */
++ public ArrayIterator(final Object array) {
++ super();
++ setArray(array);
++ }
++
++ /**
++ * Constructs an ArrayIterator that will iterate over the values in the
++ * specified array from a specific start index.
++ *
++ * @param array the array to iterate over.
++ * @param startIndex the index to start iterating at.
++ * @throws IllegalArgumentException if <code>array</code> is not an array.
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ * @throws IndexOutOfBoundsException if the index is invalid
++ */
++ public ArrayIterator(final Object array, final int startIndex) {
++ super();
++ setArray(array);
++ checkBound(startIndex, "start");
++ this.startIndex = startIndex;
++ this.index = startIndex;
++ }
++
++ /**
++ * Construct an ArrayIterator that will iterate over a range of values
++ * in the specified array.
++ *
++ * @param array the array to iterate over.
++ * @param startIndex the index to start iterating at.
++ * @param endIndex the index to finish iterating at.
++ * @throws IllegalArgumentException if <code>array</code> is not an array.
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ * @throws IndexOutOfBoundsException if either index is invalid
++ */
++ public ArrayIterator(final Object array, final int startIndex, final int endIndex) {
++ super();
++ setArray(array);
++ checkBound(startIndex, "start");
++ checkBound(endIndex, "end");
++ if (endIndex < startIndex) {
++ throw new IllegalArgumentException("End index must not be less than start index.");
++ }
++ this.startIndex = startIndex;
++ this.endIndex = endIndex;
++ this.index = startIndex;
++ }
++
++ /**
++ * Checks whether the index is valid or not.
++ *
++ * @param bound the index to check
++ * @param type the index type (for error messages)
++ * @throws IndexOutOfBoundsException if the index is invalid
++ */
++ protected void checkBound(final int bound, final String type) {
++ if (bound > this.endIndex) {
++ throw new ArrayIndexOutOfBoundsException("Attempt to make an ArrayIterator that " + type + "s beyond the end of the array. ");
++ }
++ if (bound < 0) {
++ throw new ArrayIndexOutOfBoundsException("Attempt to make an ArrayIterator that " + type + "s before the start of the array. ");
++ }
++ }
++
++ // Iterator interface
++ //-----------------------------------------------------------------------
++ /**
++ * Returns true if there are more elements to return from the array.
++ *
++ * @return true if there is a next element to return
++ */
++ public boolean hasNext() {
++ return (index < endIndex);
++ }
++
++ /**
++ * Returns the next element in the array.
++ *
++ * @return the next element in the array
++ * @throws NoSuchElementException if all the elements in the array
++ * have already been returned
++ */
++ public E next() {
++ if (hasNext() == false) {
++ throw new NoSuchElementException();
++ }
++ return (E) Array.get(array, index++);
++ }
++
++ /**
++ * Throws {@link UnsupportedOperationException}.
++ *
++ * @throws UnsupportedOperationException always
++ */
++ public void remove() {
++ throw new UnsupportedOperationException("remove() method is not supported");
++ }
++
++ // Properties
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the array that this iterator is iterating over.
++ *
++ * @return the array this iterator iterates over, or <code>null</code> if
++ * the no-arg constructor was used and {@link #setArray(Object)} has never
++ * been called with a valid array.
++ */
++ public Object getArray() {
++ return array;
++ }
++
++ /**
++ * Sets the array that the ArrayIterator should iterate over.
++ * <p/>
++ * If an array has previously been set (using the single-arg constructor
++ * or this method) then that array is discarded in favour of this one.
++ * Iteration is restarted at the start of the new array.
++ * Although this can be used to reset iteration, the {@link #reset()} method
++ * is a more effective choice.
++ *
++ * @param array the array that the iterator should iterate over.
++ * @throws IllegalArgumentException if <code>array</code> is not an array.
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ */
++ public void setArray(final Object array) {
++ // Array.getLength throws IllegalArgumentException if the object is not
++ // an array or NullPointerException if the object is null. This call
++ // is made before saving the array and resetting the index so that the
++ // array iterator remains in a consistent state if the argument is not
++ // an array or is null.
++ this.endIndex = Array.getLength(array);
++ this.startIndex = 0;
++ this.array = array;
++ this.index = 0;
++ }
++
++ /**
++ * Resets the iterator back to the start index.
++ */
++ public void reset() {
++ this.index = this.startIndex;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/ArrayListIterator.java
+@@ -0,0 +1,210 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.ResettableListIterator;
++
++import java.lang.reflect.Array;
++import java.util.ListIterator;
++import java.util.NoSuchElementException;
++
++/**
++ * Implements a {@link ListIterator} over an array.
++ * <p/>
++ * The array can be either an array of object or of primitives. If you know
++ * that you have an object array, the {@link ObjectArrayListIterator}
++ * class is a better choice, as it will perform better.
++ * <p/>
++ * <p/>
++ * This iterator does not support {@link #add(Object)} or {@link #remove()}, as the array
++ * cannot be changed in size. The {@link #set(Object)} method is supported however.
++ *
++ * @author Neil O'Toole
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Phil Steitz
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @see org.apache.commons.collections15.iterators.ArrayIterator
++ * @see java.util.Iterator
++ * @see java.util.ListIterator
++ * @since Commons Collections 3.0
++ */
++public class ArrayListIterator <E> extends ArrayIterator<E> implements ListIterator<E>, ResettableListIterator<E> {
++
++ /**
++ * Holds the index of the last item returned by a call to <code>next()</code>
++ * or <code>previous()</code>. This is set to <code>-1</code> if neither method
++ * has yet been invoked. <code>lastItemIndex</code> is used to to implement
++ * the {@link #set} method.
++ */
++ protected int lastItemIndex = -1;
++
++ // Constructors
++ // ----------------------------------------------------------------------
++ /**
++ * Constructor for use with <code>setArray</code>.
++ * <p/>
++ * Using this constructor, the iterator is equivalent to an empty iterator
++ * until {@link #setArray(Object)} is called to establish the array to iterate over.
++ */
++ public ArrayListIterator() {
++ super();
++ }
++
++ /**
++ * Constructs an ArrayListIterator that will iterate over the values in the
++ * specified array.
++ *
++ * @param array the array to iterate over
++ * @throws IllegalArgumentException if <code>array</code> is not an array.
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ */
++ public ArrayListIterator(Object array) {
++ super(array);
++ }
++
++ /**
++ * Constructs an ArrayListIterator that will iterate over the values in the
++ * specified array from a specific start index.
++ *
++ * @param array the array to iterate over
++ * @param startIndex the index to start iterating at
++ * @throws IllegalArgumentException if <code>array</code> is not an array.
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ * @throws IndexOutOfBoundsException if the start index is out of bounds
++ */
++ public ArrayListIterator(Object array, int startIndex) {
++ super(array, startIndex);
++ this.startIndex = startIndex;
++ }
++
++ /**
++ * Construct an ArrayListIterator that will iterate over a range of values
++ * in the specified array.
++ *
++ * @param array the array to iterate over
++ * @param startIndex the index to start iterating at
++ * @param endIndex the index (exclusive) to finish iterating at
++ * @throws IllegalArgumentException if <code>array</code> is not an array.
++ * @throws IndexOutOfBoundsException if the start or end index is out of bounds
++ * @throws IllegalArgumentException if end index is before the start
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ */
++ public ArrayListIterator(Object array, int startIndex, int endIndex) {
++ super(array, startIndex, endIndex);
++ this.startIndex = startIndex;
++ }
++
++ // ListIterator interface
++ //-----------------------------------------------------------------------
++ /**
++ * Returns true if there are previous elements to return from the array.
++ *
++ * @return true if there is a previous element to return
++ */
++ public boolean hasPrevious() {
++ return (this.index > this.startIndex);
++ }
++
++ /**
++ * Gets the previous element from the array.
++ *
++ * @return the previous element
++ * @throws NoSuchElementException if there is no previous element
++ */
++ public E previous() {
++ if (hasPrevious() == false) {
++ throw new NoSuchElementException();
++ }
++ this.lastItemIndex = --this.index;
++ return (E) Array.get(this.array, this.index);
++ }
++
++ /**
++ * Gets the next element from the array.
++ *
++ * @return the next element
++ * @throws NoSuchElementException if there is no next element
++ */
++ public E next() {
++ if (hasNext() == false) {
++ throw new NoSuchElementException();
++ }
++ this.lastItemIndex = this.index;
++ return (E) Array.get(this.array, this.index++);
++ }
++
++ /**
++ * Gets the next index to be retrieved.
++ *
++ * @return the index of the item to be retrieved next
++ */
++ public int nextIndex() {
++ return this.index - this.startIndex;
++ }
++
++ /**
++ * Gets the index of the item to be retrieved if {@link #previous()} is called.
++ *
++ * @return the index of the item to be retrieved next
++ */
++ public int previousIndex() {
++ return this.index - this.startIndex - 1;
++ }
++
++ /**
++ * This iterator does not support modification of its backing collection, and so will
++ * always throw an {@link UnsupportedOperationException} when this method is invoked.
++ *
++ * @throws UnsupportedOperationException always thrown.
++ * @see java.util.ListIterator#set
++ */
++ public void add(E o) {
++ throw new UnsupportedOperationException("add() method is not supported");
++ }
++
++ /**
++ * Sets the element under the cursor.
++ * <p/>
++ * This method sets the element that was returned by the last call
++ * to {@link #next()} of {@link #previous()}.
++ * <p/>
++ * <b>Note:</b> {@link ListIterator} implementations that support
++ * <code>add()</code> and <code>remove()</code> only allow <code>set()</code> to be called
++ * once per call to <code>next()</code> or <code>previous</code> (see the {@link ListIterator}
++ * javadoc for more details). Since this implementation does
++ * not support <code>add()</code> or <code>remove()</code>, <code>set()</code> may be
++ * called as often as desired.
++ *
++ * @see java.util.ListIterator#set
++ */
++ public void set(E o) {
++ if (this.lastItemIndex == -1) {
++ throw new IllegalStateException("must call next() or previous() before a call to set()");
++ }
++
++ Array.set(this.array, this.lastItemIndex, o);
++ }
++
++ /**
++ * Resets the iterator back to the start index.
++ */
++ public void reset() {
++ super.reset();
++ this.lastItemIndex = -1;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/CollatingIterator.java
+@@ -0,0 +1,374 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.list.UnmodifiableList;
++
++import java.util.*;
++
++/**
++ * Provides an ordered iteration over the elements contained in
++ * a collection of ordered Iterators.
++ * <p/>
++ * Given two ordered {@link Iterator} instances <code>A</code> and <code>B</code>,
++ * the {@link #next} method on this iterator will return the lesser of
++ * <code>A.next()</code> and <code>B.next()</code>.
++ *
++ * @author Rodney Waldhoff
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 2.1
++ */
++public class CollatingIterator <E> implements Iterator<E> {
++
++ /**
++ * The {@link Comparator} used to evaluate order.
++ */
++ private Comparator<? super E> comparator = null;
++
++ /**
++ * The list of {@link Iterator}s to evaluate.
++ */
++ private ArrayList<Iterator<? extends E>> iterators = null;
++
++ /**
++ * {@link Iterator#next Next} objects peeked from each iterator.
++ */
++ private ArrayList<E> values = null;
++
++ /**
++ * Whether or not each {@link #values} element has been set.
++ */
++ private BitSet valueSet = null;
++
++ /**
++ * Index of the {@link #iterators iterator} from whom the last returned value was obtained.
++ */
++ private int lastReturned = -1;
++
++ // Constructors
++ // ----------------------------------------------------------------------
++ /**
++ * Constructs a new <code>CollatingIterator</code>. Natural sort order
++ * will be used, and child iterators will have to be manually added
++ * using the {@link #addIterator(Iterator)} method.
++ */
++ public CollatingIterator() {
++ this(null, 2);
++ }
++
++ /**
++ * Constructs a new <code>CollatingIterator</code> that will used the
++ * specified comparator for ordering. Child iterators will have to be
++ * manually added using the {@link #addIterator(Iterator)} method.
++ *
++ * @param comp the comparator to use to sort, or null to use natural sort order
++ */
++ public CollatingIterator(final Comparator<? super E> comp) {
++ this(comp, 2);
++ }
++
++ /**
++ * Constructs a new <code>CollatingIterator</code> that will used the
++ * specified comparator for ordering and have the specified initial
++ * capacity. Child iterators will have to be
++ * manually added using the {@link #addIterator(Iterator)} method.
++ *
++ * @param comp the comparator to use to sort, or null to use natural sort order
++ * @param initIterCapacity the initial capacity for the internal list
++ * of child iterators
++ */
++ public CollatingIterator(final Comparator<? super E> comp, final int initIterCapacity) {
++ iterators = new ArrayList<Iterator<? extends E>>(initIterCapacity);
++ setComparator(comp);
++ }
++
++ /**
++ * Constructs a new <code>CollatingIterator</code> that will use the
++ * specified comparator to provide ordered iteration over the two
++ * given iterators.
++ *
++ * @param comp the comparator to use to sort, or null to use natural sort order
++ * @param a the first child ordered iterator
++ * @param b the second child ordered iterator
++ * @throws NullPointerException if either iterator is null
++ */
++ public CollatingIterator(final Comparator<? super E> comp, final Iterator<? extends E> a, final Iterator<? extends E> b) {
++ this(comp, 2);
++ addIterator(a);
++ addIterator(b);
++ }
++
++ /**
++ * Constructs a new <code>CollatingIterator</code> that will use the
++ * specified comparator to provide ordered iteration over the array
++ * of iterators.
++ *
++ * @param comp the comparator to use to sort, or null to use natural sort order
++ * @param iterators the array of iterators
++ * @throws NullPointerException if iterators array is or contains null
++ */
++ public CollatingIterator(final Comparator<? super E> comp, final Iterator<? extends E>[] iterators) {
++ this(comp, iterators.length);
++ for (int i = 0; i < iterators.length; i++) {
++ addIterator(iterators[i]);
++ }
++ }
++
++ /**
++ * Constructs a new <code>CollatingIterator</code> that will use the
++ * specified comparator to provide ordered iteration over the collection
++ * of iterators.
++ *
++ * @param comp the comparator to use to sort, or null to use natural sort order
++ * @param iterators the collection of iterators
++ * @throws NullPointerException if the iterators collection is or contains null
++ * @throws ClassCastException if the iterators collection contains an
++ * element that's not an {@link Iterator}
++ */
++ public CollatingIterator(final Comparator<? super E> comp, final Collection<Iterator<? extends E>> iterators) {
++ this(comp, iterators.size());
++ for (Iterator<Iterator<? extends E>> it = iterators.iterator(); it.hasNext();) {
++ Iterator<? extends E> item = it.next();
++ addIterator(item);
++ }
++ }
++
++ // Public Methods
++ // ----------------------------------------------------------------------
++ /**
++ * Adds the given {@link Iterator} to the iterators being collated.
++ *
++ * @param iterator the iterator to add to the collation, must not be null
++ * @throws IllegalStateException if iteration has started
++ * @throws NullPointerException if the iterator is null
++ */
++ public void addIterator(final Iterator<? extends E> iterator) {
++ checkNotStarted();
++ if (iterator == null) {
++ throw new NullPointerException("Iterator must not be null");
++ }
++ iterators.add(iterator);
++ }
++
++ /**
++ * Sets the iterator at the given index.
++ *
++ * @param index index of the Iterator to replace
++ * @param iterator Iterator to place at the given index
++ * @throws IndexOutOfBoundsException if index < 0 or index > size()
++ * @throws IllegalStateException if iteration has started
++ * @throws NullPointerException if the iterator is null
++ */
++ public void setIterator(final int index, final Iterator<? extends E> iterator) {
++ checkNotStarted();
++ if (iterator == null) {
++ throw new NullPointerException("Iterator must not be null");
++ }
++ iterators.set(index, iterator);
++ }
++
++ /**
++ * Gets the list of Iterators (unmodifiable).
++ *
++ * @return the unmodifiable list of iterators added
++ */
++ public List<Iterator<? extends E>> getIterators() {
++ return UnmodifiableList.decorate(iterators);
++ }
++
++ /**
++ * Gets the {@link Comparator} by which collatation occurs.
++ */
++ public Comparator<? super E> getComparator() {
++ return comparator;
++ }
++
++ /**
++ * Sets the {@link Comparator} by which collation occurs.
++ *
++ * @throws IllegalStateException if iteration has started
++ */
++ public void setComparator(final Comparator<? super E> comp) {
++ checkNotStarted();
++ comparator = comp;
++ }
++
++ // Iterator Methods
++ // -------------------------------------------------------------------
++ /**
++ * Returns <code>true</code> if any child iterator has remaining elements.
++ *
++ * @return true if this iterator has remaining elements
++ */
++ public boolean hasNext() {
++ start();
++ return anyValueSet(valueSet) || anyHasNext(iterators);
++ }
++
++ /**
++ * Returns the next ordered element from a child iterator.
++ *
++ * @return the next ordered element
++ * @throws NoSuchElementException if no child iterator has any more elements
++ */
++ public E next() throws NoSuchElementException {
++ if (hasNext() == false) {
++ throw new NoSuchElementException();
++ }
++ int leastIndex = least();
++ if (leastIndex == -1) {
++ throw new NoSuchElementException();
++ } else {
++ E val = values.get(leastIndex);
++ clear(leastIndex);
++ lastReturned = leastIndex;
++ return val;
++ }
++ }
++
++ /**
++ * Removes the last returned element from the child iterator that
++ * produced it.
++ *
++ * @throws IllegalStateException if there is no last returned element,
++ * or if the last returned element has already been removed
++ */
++ public void remove() {
++ if (lastReturned == -1) {
++ throw new IllegalStateException("No value can be removed at present");
++ }
++ Iterator<? extends E> it = iterators.get(lastReturned);
++ it.remove();
++ }
++
++ // Private Methods
++ // -------------------------------------------------------------------
++ /**
++ * Initializes the collating state if it hasn't been already.
++ */
++ private void start() {
++ if (values == null) {
++ values = new ArrayList<E>(iterators.size());
++ valueSet = new BitSet(iterators.size());
++ for (int i = 0; i < iterators.size(); i++) {
++ values.add(null);
++ valueSet.clear(i);
++ }
++ }
++ }
++
++ /**
++ * Sets the {@link #values} and {@link #valueSet} attributes
++ * at position <i>i</i> to the next value of the
++ * {@link #iterators iterator} at position <i>i</i>, or
++ * clear them if the <i>i</i><sup>th</sup> iterator
++ * has no next value.
++ *
++ * @return <tt>false</tt> iff there was no value to set
++ */
++ private boolean set(int i) {
++ Iterator<? extends E> it = iterators.get(i);
++ if (it.hasNext()) {
++ values.set(i, it.next());
++ valueSet.set(i);
++ return true;
++ } else {
++ values.set(i, null);
++ valueSet.clear(i);
++ return false;
++ }
++ }
++
++ /**
++ * Clears the {@link #values} and {@link #valueSet} attributes
++ * at position <i>i</i>.
++ */
++ private void clear(int i) {
++ values.set(i, null);
++ valueSet.clear(i);
++ }
++
++ /**
++ * Throws {@link IllegalStateException} if iteration has started
++ * via {@link #start}.
++ *
++ * @throws IllegalStateException if iteration started
++ */
++ private void checkNotStarted() throws IllegalStateException {
++ if (values != null) {
++ throw new IllegalStateException("Can't do that after next or hasNext has been called.");
++ }
++ }
++
++ /**
++ * Returns the index of the least element in {@link #values},
++ * {@link #set(int) setting} any uninitialized values.
++ *
++ * @throws IllegalStateException
++ */
++ private int least() {
++ int leastIndex = -1;
++ E leastObject = null;
++ for (int i = 0; i < values.size(); i++) {
++ if (valueSet.get(i) == false) {
++ set(i);
++ }
++ if (valueSet.get(i)) {
++ if (leastIndex == -1) {
++ leastIndex = i;
++ leastObject = values.get(i);
++ } else {
++ E curObject = values.get(i);
++ if (comparator.compare(curObject, leastObject) < 0) {
++ leastObject = curObject;
++ leastIndex = i;
++ }
++ }
++ }
++ }
++ return leastIndex;
++ }
++
++ /**
++ * Returns <code>true</code> iff any bit in the given set is
++ * <code>true</code>.
++ */
++ private boolean anyValueSet(BitSet set) {
++ for (int i = 0; i < set.size(); i++) {
++ if (set.get(i)) {
++ return true;
++ }
++ }
++ return false;
++ }
++
++ /**
++ * Returns <code>true</code> iff any {@link Iterator}
++ * in the given list has a next value.
++ */
++ private boolean anyHasNext(ArrayList<Iterator<? extends E>> iters) {
++ for (int i = 0; i < iters.size(); i++) {
++ Iterator<? extends E> it = iters.get(i);
++ if (it.hasNext()) {
++ return true;
++ }
++ }
++ return false;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/EmptyIterator.java
+@@ -0,0 +1,60 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.ResettableIterator;
++
++import java.util.Iterator;
++
++/**
++ * Provides an implementation of an empty iterator.
++ * <p/>
++ * This class provides an implementation of an empty iterator.
++ * This class provides for binary compatability between Commons Collections
++ * 2.1.1 and 3.1 due to issues with <code>IteratorUtils</code>.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 2.1.1 and 3.1
++ */
++public class EmptyIterator <E> extends AbstractEmptyIterator<E> implements ResettableIterator<E> {
++
++ /**
++ * Singleton instance of the iterator.
++ *
++ * @since Commons Collections 3.1
++ */
++ public static final ResettableIterator RESETTABLE_INSTANCE = new EmptyIterator();
++ /**
++ * Singleton instance of the iterator.
++ *
++ * @since Commons Collections 2.1.1 and 3.1
++ */
++ public static final Iterator INSTANCE = RESETTABLE_INSTANCE;
++
++ public static <T> Iterator<T> getInstance() {
++ return INSTANCE;
++ }
++
++ /**
++ * Constructor.
++ */
++ protected EmptyIterator() {
++ super();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/EmptyListIterator.java
+@@ -0,0 +1,56 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.ResettableListIterator;
++
++import java.util.ListIterator;
++
++/**
++ * Provides an implementation of an empty list iterator.
++ * <p/>
++ * This class provides an implementation of an empty list iterator.
++ * This class provides for binary compatability between Commons Collections
++ * 2.1.1 and 3.1 due to issues with <code>IteratorUtils</code>.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 2.1.1 and 3.1
++ */
++public class EmptyListIterator <E> extends AbstractEmptyIterator<E> implements ResettableListIterator<E> {
++
++ /**
++ * Singleton instance of the iterator.
++ *
++ * @since Commons Collections 3.1
++ */
++ public static final ResettableListIterator RESETTABLE_INSTANCE = new EmptyListIterator();
++ /**
++ * Singleton instance of the iterator.
++ *
++ * @since Commons Collections 2.1.1 and 3.1
++ */
++ public static final ListIterator INSTANCE = RESETTABLE_INSTANCE;
++
++ /**
++ * Constructor.
++ */
++ protected EmptyListIterator() {
++ super();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/EmptyMapIterator.java
+@@ -0,0 +1,45 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.ResettableIterator;
++
++/**
++ * Provides an implementation of an empty map iterator.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.1
++ */
++public class EmptyMapIterator extends AbstractEmptyIterator implements MapIterator, ResettableIterator {
++
++ /**
++ * Singleton instance of the iterator.
++ *
++ * @since Commons Collections 3.1
++ */
++ public static final MapIterator INSTANCE = new EmptyMapIterator();
++
++ /**
++ * Constructor.
++ */
++ protected EmptyMapIterator() {
++ super();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/EmptyOrderedIterator.java
+@@ -0,0 +1,45 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.OrderedIterator;
++import org.apache.commons.collections15.ResettableIterator;
++
++/**
++ * Provides an implementation of an empty ordered iterator.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.1
++ */
++public class EmptyOrderedIterator <E> extends AbstractEmptyIterator<E> implements OrderedIterator<E>, ResettableIterator<E> {
++
++ /**
++ * Singleton instance of the iterator.
++ *
++ * @since Commons Collections 3.1
++ */
++ public static final OrderedIterator INSTANCE = new EmptyOrderedIterator();
++
++ /**
++ * Constructor.
++ */
++ protected EmptyOrderedIterator() {
++ super();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/EmptyOrderedMapIterator.java
+@@ -0,0 +1,45 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.OrderedMapIterator;
++import org.apache.commons.collections15.ResettableIterator;
++
++/**
++ * Provides an implementation of an empty ordered map iterator.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.1
++ */
++public class EmptyOrderedMapIterator extends AbstractEmptyIterator implements OrderedMapIterator, ResettableIterator {
++
++ /**
++ * Singleton instance of the iterator.
++ *
++ * @since Commons Collections 3.1
++ */
++ public static final OrderedMapIterator INSTANCE = new EmptyOrderedMapIterator();
++
++ /**
++ * Constructor.
++ */
++ protected EmptyOrderedMapIterator() {
++ super();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/EntrySetMapIterator.java
+@@ -0,0 +1,171 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.ResettableIterator;
++
++import java.util.Iterator;
++import java.util.Map;
++
++/**
++ * Implements a <code>MapIterator</code> using a Map entrySet.
++ * Reverse iteration is not supported.
++ * <pre>
++ * MapIterator it = map.mapIterator();
++ * while (it.hasNext()) {
++ * Object key = it.next();
++ * Object value = it.getValue();
++ * it.setValue(newValue);
++ * }
++ * </pre>
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class EntrySetMapIterator <K,V> implements MapIterator<K, V>, ResettableIterator<K> {
++
++ private final Map<K, V> map;
++ private Iterator<Map.Entry<K, V>> iterator;
++ private Map.Entry<K, V> last;
++ private boolean canRemove = false;
++
++ /**
++ * Constructor.
++ *
++ * @param map the map to iterate over
++ */
++ public EntrySetMapIterator(Map<K, V> map) {
++ super();
++ this.map = map;
++ this.iterator = map.entrySet().iterator();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Checks to see if there are more entries still to be iterated.
++ *
++ * @return <code>true</code> if the iterator has more elements
++ */
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ /**
++ * Gets the next <em>key</em> from the <code>Map</code>.
++ *
++ * @return the next key in the iteration
++ * @throws java.util.NoSuchElementException
++ * if the iteration is finished
++ */
++ public K next() {
++ last = iterator.next();
++ canRemove = true;
++ return last.getKey();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Removes the last returned key from the underlying <code>Map</code>.
++ * <p/>
++ * This method can be called once per call to <code>next()</code>.
++ *
++ * @throws UnsupportedOperationException if remove is not supported by the map
++ * @throws IllegalStateException if <code>next()</code> has not yet been called
++ * @throws IllegalStateException if <code>remove()</code> has already been called
++ * since the last call to <code>next()</code>
++ */
++ public void remove() {
++ if (canRemove == false) {
++ throw new IllegalStateException("Iterator remove() can only be called once after next()");
++ }
++ iterator.remove();
++ last = null;
++ canRemove = false;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the current key, which is the key returned by the last call
++ * to <code>next()</code>.
++ *
++ * @return the current key
++ * @throws IllegalStateException if <code>next()</code> has not yet been called
++ */
++ public K getKey() {
++ if (last == null) {
++ throw new IllegalStateException("Iterator getKey() can only be called after next() and before remove()");
++ }
++ return last.getKey();
++ }
++
++ /**
++ * Gets the current value, which is the value associated with the last key
++ * returned by <code>next()</code>.
++ *
++ * @return the current value
++ * @throws IllegalStateException if <code>next()</code> has not yet been called
++ */
++ public V getValue() {
++ if (last == null) {
++ throw new IllegalStateException("Iterator getValue() can only be called after next() and before remove()");
++ }
++ return last.getValue();
++ }
++
++ /**
++ * Sets the value associated with the current key.
++ *
++ * @param value the new value
++ * @return the previous value
++ * @throws UnsupportedOperationException if setValue is not supported by the map
++ * @throws IllegalStateException if <code>next()</code> has not yet been called
++ * @throws IllegalStateException if <code>remove()</code> has been called since the
++ * last call to <code>next()</code>
++ */
++ public V setValue(V value) {
++ if (last == null) {
++ throw new IllegalStateException("Iterator setValue() can only be called after next() and before remove()");
++ }
++ return last.setValue(value);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Resets the state of the iterator.
++ */
++ public void reset() {
++ iterator = map.entrySet().iterator();
++ last = null;
++ canRemove = false;
++ }
++
++ /**
++ * Gets the iterator as a String.
++ *
++ * @return a string version of the iterator
++ */
++ public String toString() {
++ if (last != null) {
++ return "MapIterator[" + getKey() + "=" + getValue() + "]";
++ } else {
++ return "MapIterator[]";
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/EnumerationIterator.java
+@@ -0,0 +1,146 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import java.util.Collection;
++import java.util.Enumeration;
++import java.util.Iterator;
++
++/**
++ * Adapter to make {@link Enumeration Enumeration} instances appear
++ * to be {@link Iterator Iterator} instances.
++ *
++ * @author <a href="mailto:jstrachan at apache.org">James Strachan</a>
++ * @author Matt Hall, John Watkinson, <a href="mailto:dlr at finemaltcoding.com">Daniel Rall</a>
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 1.0
++ */
++public class EnumerationIterator <E> implements Iterator<E> {
++
++ /**
++ * The collection to remove elements from
++ */
++ private Collection<E> collection;
++ /**
++ * The enumeration being converted
++ */
++ private Enumeration<E> enumeration;
++ /**
++ * The last object retrieved
++ */
++ private E last;
++
++ // Constructors
++ //-----------------------------------------------------------------------
++ /**
++ * Constructs a new <code>EnumerationIterator</code> that will not
++ * function until {@link #setEnumeration(Enumeration)} is called.
++ */
++ public EnumerationIterator() {
++ this(null, null);
++ }
++
++ /**
++ * Constructs a new <code>EnumerationIterator</code> that provides
++ * an iterator view of the given enumeration.
++ *
++ * @param enumeration the enumeration to use
++ */
++ public EnumerationIterator(final Enumeration<E> enumeration) {
++ this(enumeration, null);
++ }
++
++ /**
++ * Constructs a new <code>EnumerationIterator</code> that will remove
++ * elements from the specified collection.
++ *
++ * @param enumeration the enumeration to use
++ * @param collection the collection to remove elements form
++ */
++ public EnumerationIterator(final Enumeration<E> enumeration, final Collection<E> collection) {
++ super();
++ this.enumeration = enumeration;
++ this.collection = collection;
++ this.last = null;
++ }
++
++ // Iterator interface
++ //-----------------------------------------------------------------------
++ /**
++ * Returns true if the underlying enumeration has more elements.
++ *
++ * @return true if the underlying enumeration has more elements
++ * @throws NullPointerException if the underlying enumeration is null
++ */
++ public boolean hasNext() {
++ return enumeration.hasMoreElements();
++ }
++
++ /**
++ * Returns the next object from the enumeration.
++ *
++ * @return the next object from the enumeration
++ * @throws NullPointerException if the enumeration is null
++ */
++ public E next() {
++ last = enumeration.nextElement();
++ return last;
++ }
++
++ /**
++ * Removes the last retrieved element if a collection is attached.
++ * <p/>
++ * Functions if an associated <code>Collection</code> is known.
++ * If so, the first occurrence of the last returned object from this
++ * iterator will be removed from the collection.
++ *
++ * @throws IllegalStateException <code>next()</code> not called.
++ * @throws UnsupportedOperationException if no associated collection
++ */
++ public void remove() {
++ if (collection != null) {
++ if (last != null) {
++ collection.remove(last);
++ } else {
++ throw new IllegalStateException("next() must have been called for remove() to function");
++ }
++ } else {
++ throw new UnsupportedOperationException("No Collection associated with this Iterator");
++ }
++ }
++
++ // Properties
++ //-----------------------------------------------------------------------
++ /**
++ * Returns the underlying enumeration.
++ *
++ * @return the underlying enumeration
++ */
++ public Enumeration<E> getEnumeration() {
++ return enumeration;
++ }
++
++ /**
++ * Sets the underlying enumeration.
++ *
++ * @param enumeration the new underlying enumeration
++ */
++ public void setEnumeration(final Enumeration<E> enumeration) {
++ this.enumeration = enumeration;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/FilterIterator.java
+@@ -0,0 +1,192 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.util.Iterator;
++import java.util.NoSuchElementException;
++
++/**
++ * Decorates an iterator such that only elements matching a predicate filter
++ * are returned.
++ *
++ * @author James Strachan
++ * @author Jan Sorensen
++ * @author Ralph Wagner
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 1.0
++ */
++public class FilterIterator <E> implements Iterator<E> {
++
++ /**
++ * The iterator being used
++ */
++ private Iterator<E> iterator;
++ /**
++ * The predicate being used
++ */
++ private Predicate<? super E> predicate;
++ /**
++ * The next object in the iteration
++ */
++ private E nextObject;
++ /**
++ * Whether the next object has been calculated yet
++ */
++ private boolean nextObjectSet = false;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructs a new <code>FilterIterator</code> that will not function
++ * until {@link #setIterator(Iterator) setIterator} is invoked.
++ */
++ public FilterIterator() {
++ super();
++ }
++
++ /**
++ * Constructs a new <code>FilterIterator</code> that will not function
++ * until {@link #setPredicate(Predicate) setPredicate} is invoked.
++ *
++ * @param iterator the iterator to use
++ */
++ public FilterIterator(Iterator<E> iterator) {
++ super();
++ this.iterator = iterator;
++ }
++
++ /**
++ * Constructs a new <code>FilterIterator</code> that will use the
++ * given iterator and predicate.
++ *
++ * @param iterator the iterator to use
++ * @param predicate the predicate to use
++ */
++ public FilterIterator(Iterator<E> iterator, Predicate<? super E> predicate) {
++ super();
++ this.iterator = iterator;
++ this.predicate = predicate;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns true if the underlying iterator contains an object that
++ * matches the predicate.
++ *
++ * @return true if there is another object that matches the predicate
++ */
++ public boolean hasNext() {
++ if (nextObjectSet) {
++ return true;
++ } else {
++ return setNextObject();
++ }
++ }
++
++ /**
++ * Returns the next object that matches the predicate.
++ *
++ * @return the next object which matches the given predicate
++ * @throws NoSuchElementException if there are no more elements that
++ * match the predicate
++ */
++ public E next() {
++ if (!nextObjectSet) {
++ if (!setNextObject()) {
++ throw new NoSuchElementException();
++ }
++ }
++ nextObjectSet = false;
++ return nextObject;
++ }
++
++ /**
++ * Removes from the underlying collection of the base iterator the last
++ * element returned by this iterator.
++ * This method can only be called
++ * if <code>next()</code> was called, but not after
++ * <code>hasNext()</code>, because the <code>hasNext()</code> call
++ * changes the base iterator.
++ *
++ * @throws IllegalStateException if <code>hasNext()</code> has already
++ * been called.
++ */
++ public void remove() {
++ if (nextObjectSet) {
++ throw new IllegalStateException("remove() cannot be called");
++ }
++ iterator.remove();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the iterator this iterator is using.
++ *
++ * @return the iterator.
++ */
++ public Iterator<E> getIterator() {
++ return iterator;
++ }
++
++ /**
++ * Sets the iterator for this iterator to use.
++ * If iteration has started, this effectively resets the iterator.
++ *
++ * @param iterator the iterator to use
++ */
++ public void setIterator(Iterator<E> iterator) {
++ this.iterator = iterator;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the predicate this iterator is using.
++ *
++ * @return the predicate.
++ */
++ public Predicate<? super E> getPredicate() {
++ return predicate;
++ }
++
++ /**
++ * Sets the predicate this the iterator to use.
++ *
++ * @param predicate the transformer to use
++ */
++ public void setPredicate(Predicate<? super E> predicate) {
++ this.predicate = predicate;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Set nextObject to the next object. If there are no more
++ * objects then return false. Otherwise, return true.
++ */
++ private boolean setNextObject() {
++ while (iterator.hasNext()) {
++ E object = iterator.next();
++ if (predicate.evaluate(object)) {
++ nextObject = object;
++ nextObjectSet = true;
++ return true;
++ }
++ }
++ return false;
++ }
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/FilterListIterator.java
+@@ -0,0 +1,290 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.util.ListIterator;
++import java.util.NoSuchElementException;
++
++/**
++ * A proxy {@link ListIterator ListIterator} which
++ * takes a {@link Predicate Predicate} instance to filter
++ * out objects from an underlying <code>ListIterator</code>
++ * instance. Only objects for which the specified
++ * <code>Predicate</code> evaluates to <code>true</code> are
++ * returned by the iterator.
++ *
++ * @author Matt Hall, John Watkinson, Rodney Waldhoff
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 2.0
++ */
++public class FilterListIterator <E> implements ListIterator<E> {
++
++ /**
++ * The iterator being used
++ */
++ private ListIterator<E> iterator;
++
++ /**
++ * The predicate being used
++ */
++ private Predicate<? super E> predicate;
++
++ /**
++ * The value of the next (matching) object, when
++ * {@link #nextObjectSet} is true.
++ */
++ private E nextObject;
++
++ /**
++ * Whether or not the {@link #nextObject} has been set
++ * (possibly to <code>null</code>).
++ */
++ private boolean nextObjectSet = false;
++
++ /**
++ * The value of the previous (matching) object, when
++ * {@link #previousObjectSet} is true.
++ */
++ private E previousObject;
++
++ /**
++ * Whether or not the {@link #previousObject} has been set
++ * (possibly to <code>null</code>).
++ */
++ private boolean previousObjectSet = false;
++
++ /**
++ * The index of the element that would be returned by {@link #next}.
++ */
++ private int nextIndex = 0;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructs a new <code>FilterListIterator</code> that will not
++ * function until
++ * {@link #setPredicate(Predicate) setPredicate} is invoked.
++ */
++ public FilterListIterator() {
++ super();
++ }
++
++ /**
++ * Constructs a new <code>FilterListIterator</code> that will not
++ * function until {@link #setPredicate(Predicate) setPredicate} is invoked.
++ *
++ * @param iterator the iterator to use
++ */
++ public FilterListIterator(ListIterator<E> iterator) {
++ super();
++ this.iterator = iterator;
++ }
++
++ /**
++ * Constructs a new <code>FilterListIterator</code>.
++ *
++ * @param iterator the iterator to use
++ * @param predicate the predicate to use
++ */
++ public FilterListIterator(ListIterator<E> iterator, Predicate<? super E> predicate) {
++ super();
++ this.iterator = iterator;
++ this.predicate = predicate;
++ }
++
++ /**
++ * Constructs a new <code>FilterListIterator</code>.
++ *
++ * @param predicate the predicate to use.
++ */
++ public FilterListIterator(Predicate<? super E> predicate) {
++ super();
++ this.predicate = predicate;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Not supported.
++ */
++ public void add(E o) {
++ throw new UnsupportedOperationException("FilterListIterator.add(Object) is not supported.");
++ }
++
++ public boolean hasNext() {
++ if (nextObjectSet) {
++ return true;
++ } else {
++ return setNextObject();
++ }
++ }
++
++ public boolean hasPrevious() {
++ if (previousObjectSet) {
++ return true;
++ } else {
++ return setPreviousObject();
++ }
++ }
++
++ public E next() {
++ if (!nextObjectSet) {
++ if (!setNextObject()) {
++ throw new NoSuchElementException();
++ }
++ }
++ nextIndex++;
++ E temp = nextObject;
++ clearNextObject();
++ return temp;
++ }
++
++ public int nextIndex() {
++ return nextIndex;
++ }
++
++ public E previous() {
++ if (!previousObjectSet) {
++ if (!setPreviousObject()) {
++ throw new NoSuchElementException();
++ }
++ }
++ nextIndex--;
++ E temp = previousObject;
++ clearPreviousObject();
++ return temp;
++ }
++
++ public int previousIndex() {
++ return (nextIndex - 1);
++ }
++
++ /**
++ * Not supported.
++ */
++ public void remove() {
++ throw new UnsupportedOperationException("FilterListIterator.remove() is not supported.");
++ }
++
++ /**
++ * Not supported.
++ */
++ public void set(E o) {
++ throw new UnsupportedOperationException("FilterListIterator.set(Object) is not supported.");
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the iterator this iterator is using.
++ *
++ * @return the iterator.
++ */
++ public ListIterator<E> getListIterator() {
++ return iterator;
++ }
++
++ /**
++ * Sets the iterator for this iterator to use.
++ * If iteration has started, this effectively resets the iterator.
++ *
++ * @param iterator the iterator to use
++ */
++ public void setListIterator(ListIterator<E> iterator) {
++ this.iterator = iterator;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the predicate this iterator is using.
++ *
++ * @return the predicate.
++ */
++ public Predicate<? super E> getPredicate() {
++ return predicate;
++ }
++
++ /**
++ * Sets the predicate this the iterator to use.
++ *
++ * @param predicate the transformer to use
++ */
++ public void setPredicate(Predicate<? super E> predicate) {
++ this.predicate = predicate;
++ }
++
++ //-----------------------------------------------------------------------
++ private void clearNextObject() {
++ nextObject = null;
++ nextObjectSet = false;
++ }
++
++ private boolean setNextObject() {
++ // if previousObjectSet,
++ // then we've walked back one step in the
++ // underlying list (due to a hasPrevious() call)
++ // so skip ahead one matching object
++ if (previousObjectSet) {
++ clearPreviousObject();
++ if (!setNextObject()) {
++ return false;
++ } else {
++ clearNextObject();
++ }
++ }
++
++ while (iterator.hasNext()) {
++ E object = iterator.next();
++ if (predicate.evaluate(object)) {
++ nextObject = object;
++ nextObjectSet = true;
++ return true;
++ }
++ }
++ return false;
++ }
++
++ private void clearPreviousObject() {
++ previousObject = null;
++ previousObjectSet = false;
++ }
++
++ private boolean setPreviousObject() {
++ // if nextObjectSet,
++ // then we've walked back one step in the
++ // underlying list (due to a hasNext() call)
++ // so skip ahead one matching object
++ if (nextObjectSet) {
++ clearNextObject();
++ if (!setPreviousObject()) {
++ return false;
++ } else {
++ clearPreviousObject();
++ }
++ }
++
++ while (iterator.hasPrevious()) {
++ E object = iterator.previous();
++ if (predicate.evaluate(object)) {
++ previousObject = object;
++ previousObjectSet = true;
++ return true;
++ }
++ }
++ return false;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/IteratorChain.java
+@@ -0,0 +1,293 @@
++// GenericsNote: Converted.
++// GenericsNote: Some questions about things like UnmodifiableList.decorate(iteratorChain); and so on
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.list.UnmodifiableList;
++
++import java.util.ArrayList;
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.List;
++
++/**
++ * An IteratorChain is an Iterator that wraps a number of Iterators.
++ * <p/>
++ * This class makes multiple iterators look like one to the caller
++ * When any method from the Iterator interface is called, the IteratorChain
++ * will delegate to a single underlying Iterator. The IteratorChain will
++ * invoke the Iterators in sequence until all Iterators are exhausted.
++ * <p/>
++ * Under many circumstances, linking Iterators together in this manner is
++ * more efficient (and convenient) than reading out the contents of each
++ * Iterator into a List and creating a new Iterator.
++ * <p/>
++ * Calling a method that adds new Iterator<i>after a method in the Iterator
++ * interface has been called</i> will result in an UnsupportedOperationException.
++ * Subclasses should <i>take care</i> to not alter the underlying List of Iterators.
++ * <p/>
++ * NOTE: As from version 3.0, the IteratorChain may contain no
++ * iterators. In this case the class will function as an empty iterator.
++ *
++ * @author Morgan Delagrange
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 2.1
++ */
++public class IteratorChain <E> implements Iterator<E> {
++
++ /**
++ * The chain of iterators
++ */
++ protected final List<Iterator<? extends E>> iteratorChain = new ArrayList<Iterator<? extends E>>();
++ /**
++ * The index of the current iterator
++ */
++ protected int currentIteratorIndex = 0;
++ /**
++ * The current iterator
++ */
++ protected Iterator<? extends E> currentIterator = null;
++ /**
++ * The "last used" Iterator is the Iterator upon which
++ * next() or hasNext() was most recently called
++ * used for the remove() operation only
++ */
++ protected Iterator<? extends E> lastUsedIterator = null;
++ /**
++ * ComparatorChain is "locked" after the first time
++ * compare(Object,Object) is called
++ */
++ protected boolean isLocked = false;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Construct an IteratorChain with no Iterators.
++ * <p/>
++ * You will normally use {@link #addIterator(Iterator)} to add
++ * some iterators after using this constructor.
++ */
++ public IteratorChain() {
++ super();
++ }
++
++ /**
++ * Construct an IteratorChain with a single Iterator.
++ *
++ * @param iterator first Iterator in the IteratorChain
++ * @throws NullPointerException if the iterator is null
++ */
++ public IteratorChain(Iterator<? extends E> iterator) {
++ super();
++ addIterator(iterator);
++ }
++
++ /**
++ * Constructs a new <code>IteratorChain</code> over the two
++ * given iterators.
++ *
++ * @param a the first child iterator
++ * @param b the second child iterator
++ * @throws NullPointerException if either iterator is null
++ */
++ public IteratorChain(Iterator<? extends E> a, Iterator<? extends E> b) {
++ super();
++ addIterator(a);
++ addIterator(b);
++ }
++
++ /**
++ * Constructs a new <code>IteratorChain</code> over the array
++ * of iterators.
++ *
++ * @param iterators the array of iterators
++ * @throws NullPointerException if iterators array is or contains null
++ */
++ public IteratorChain(Iterator<? extends E>[] iterators) {
++ super();
++ for (int i = 0; i < iterators.length; i++) {
++ addIterator(iterators[i]);
++ }
++ }
++
++ /**
++ * Constructs a new <code>IteratorChain</code> over the collection
++ * of iterators.
++ *
++ * @param iterators the collection of iterators
++ * @throws NullPointerException if iterators collection is or contains null
++ * @throws ClassCastException if iterators collection doesn't contain an iterator
++ */
++ public IteratorChain(Collection<Iterator<? extends E>> iterators) {
++ super();
++ for (Iterator<? extends E> iterator : iterators) {
++ addIterator(iterator);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Add an Iterator to the end of the chain
++ *
++ * @param iterator Iterator to add
++ * @throws IllegalStateException if I've already started iterating
++ * @throws NullPointerException if the iterator is null
++ */
++ public void addIterator(Iterator<? extends E> iterator) {
++ checkLocked();
++ if (iterator == null) {
++ throw new NullPointerException("Iterator must not be null");
++ }
++ iteratorChain.add(iterator);
++ }
++
++ /**
++ * Set the Iterator at the given index
++ *
++ * @param index index of the Iterator to replace
++ * @param iterator Iterator to place at the given index
++ * @throws IndexOutOfBoundsException if index < 0 or index > size()
++ * @throws IllegalStateException if I've already started iterating
++ * @throws NullPointerException if the iterator is null
++ */
++ public void setIterator(int index, Iterator<? extends E> iterator) throws IndexOutOfBoundsException {
++ checkLocked();
++ if (iterator == null) {
++ throw new NullPointerException("Iterator must not be null");
++ }
++ iteratorChain.set(index, iterator);
++ }
++
++ /**
++ * Get the list of Iterators (unmodifiable)
++ *
++ * @return the unmodifiable list of iterators added
++ */
++ public List<Iterator<? extends E>> getIterators() {
++ return UnmodifiableList.decorate(iteratorChain);
++ }
++
++ /**
++ * Number of Iterators in the current IteratorChain.
++ *
++ * @return Iterator count
++ */
++ public int size() {
++ return iteratorChain.size();
++ }
++
++ /**
++ * Determine if modifications can still be made to the IteratorChain.
++ * IteratorChains cannot be modified once they have executed a method
++ * from the Iterator interface.
++ *
++ * @return true if IteratorChain cannot be modified, false if it can
++ */
++ public boolean isLocked() {
++ return isLocked;
++ }
++
++ /**
++ * Checks whether the iterator chain is now locked and in use.
++ */
++ private void checkLocked() {
++ if (isLocked == true) {
++ throw new UnsupportedOperationException("IteratorChain cannot be changed after the first use of a method from the Iterator interface");
++ }
++ }
++
++ /**
++ * Lock the chain so no more iterators can be added.
++ * This must be called from all Iterator interface methods.
++ */
++ private void lockChain() {
++ if (isLocked == false) {
++ isLocked = true;
++ }
++ }
++
++ /**
++ * Updates the current iterator field to ensure that the current Iterator
++ * is not exhausted
++ */
++ protected void updateCurrentIterator() {
++ if (currentIterator == null) {
++ if (iteratorChain.isEmpty()) {
++ currentIterator = EmptyIterator.INSTANCE;
++ } else {
++ currentIterator = iteratorChain.get(0);
++ }
++ // set last used iterator here, in case the user calls remove
++ // before calling hasNext() or next() (although they shouldn't)
++ lastUsedIterator = currentIterator;
++ }
++
++ while (currentIterator.hasNext() == false && currentIteratorIndex < iteratorChain.size() - 1) {
++ currentIteratorIndex++;
++ currentIterator = iteratorChain.get(currentIteratorIndex);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Return true if any Iterator in the IteratorChain has a remaining element.
++ *
++ * @return true if elements remain
++ */
++ public boolean hasNext() {
++ lockChain();
++ updateCurrentIterator();
++ lastUsedIterator = currentIterator;
++
++ return currentIterator.hasNext();
++ }
++
++ /**
++ * Returns the next Object of the current Iterator
++ *
++ * @return Object from the current Iterator
++ * @throws java.util.NoSuchElementException
++ * if all the Iterators are exhausted
++ */
++ public E next() {
++ lockChain();
++ updateCurrentIterator();
++ lastUsedIterator = currentIterator;
++
++ return currentIterator.next();
++ }
++
++ /**
++ * Removes from the underlying collection the last element
++ * returned by the Iterator. As with next() and hasNext(),
++ * this method calls remove() on the underlying Iterator.
++ * Therefore, this method may throw an
++ * UnsupportedOperationException if the underlying
++ * Iterator does not support this method.
++ *
++ * @throws UnsupportedOperationException if the remove operator is not supported by the underlying Iterator
++ * @throws IllegalStateException if the next method has not yet been called, or the remove method has
++ * already been called after the last call to the next method.
++ */
++ public void remove() {
++ lockChain();
++ updateCurrentIterator();
++
++ lastUsedIterator.remove();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/IteratorEnumeration.java
+@@ -0,0 +1,102 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import java.util.Enumeration;
++import java.util.Iterator;
++
++/**
++ * Adapter to make an {@link Iterator Iterator} instance appear to be
++ * an {@link Enumeration Enumeration} instance.
++ *
++ * @author Matt Hall, John Watkinson, <a href="mailto:jstrachan at apache.org">James Strachan</a>
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 1.0
++ */
++public class IteratorEnumeration <E> implements Enumeration<E> {
++
++ /**
++ * The iterator being decorated.
++ */
++ private Iterator<E> iterator;
++
++ /**
++ * Constructs a new <code>IteratorEnumeration</code> that will not
++ * function until {@link #setIterator(Iterator) setIterator} is
++ * invoked.
++ */
++ public IteratorEnumeration() {
++ super();
++ }
++
++ /**
++ * Constructs a new <code>IteratorEnumeration</code> that will use
++ * the given iterator.
++ *
++ * @param iterator the iterator to use
++ */
++ public IteratorEnumeration(Iterator<E> 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 hasMoreElements() {
++ return iterator.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 has no
++ * more elements
++ */
++ public E nextElement() {
++ return iterator.next();
++ }
++
++ // Properties
++ //-------------------------------------------------------------------------
++
++ /**
++ * Returns the underlying iterator.
++ *
++ * @return the underlying iterator
++ */
++ public Iterator<E> getIterator() {
++ return iterator;
++ }
++
++ /**
++ * Sets the underlying iterator.
++ *
++ * @param iterator the new underlying iterator
++ */
++ public void setIterator(Iterator<E> iterator) {
++ this.iterator = iterator;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/ListIteratorWrapper.java
+@@ -0,0 +1,180 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import java.util.Iterator;
++import java.util.LinkedList;
++import java.util.ListIterator;
++import java.util.NoSuchElementException;
++
++/**
++ * As the wrapped Iterator is traversed, ListIteratorWrapper
++ * builds a LinkedList of its values, permitting all required
++ * operations of ListIterator.
++ *
++ * @author Morgan Delagrange
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 2.1
++ */
++public class ListIteratorWrapper <E> implements ListIterator<E> {
++
++ /**
++ * Holds value of property "iterator"
++ */
++ private final Iterator<E> iterator;
++ private final LinkedList<E> list = new LinkedList<E>();
++
++ // position of this iterator
++ private int currentIndex = 0;
++ // position of the wrapped iterator
++ // this Iterator should only be used to populate the list
++ private int wrappedIteratorIndex = 0;
++
++ private static final String UNSUPPORTED_OPERATION_MESSAGE = "ListIteratorWrapper does not support optional operations of ListIterator.";
++
++ // Constructor
++ //-------------------------------------------------------------------------
++
++ /**
++ * Constructs a new <code>ListIteratorWrapper</code> that will wrap
++ * the given iterator.
++ *
++ * @param iterator the iterator to wrap
++ * @throws NullPointerException if the iterator is null
++ */
++ public ListIteratorWrapper(Iterator<E> iterator) {
++ super();
++ if (iterator == null) {
++ throw new NullPointerException("Iterator must not be null");
++ }
++ this.iterator = iterator;
++ }
++
++ // ListIterator interface
++ //-------------------------------------------------------------------------
++
++ /**
++ * Throws {@link UnsupportedOperationException}.
++ *
++ * @param o ignored
++ * @throws UnsupportedOperationException always
++ */
++ public void add(E o) throws UnsupportedOperationException {
++ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_MESSAGE);
++ }
++
++
++ /**
++ * Returns true if there are more elements in the iterator.
++ *
++ * @return true if there are more elements
++ */
++ public boolean hasNext() {
++ if (currentIndex == wrappedIteratorIndex) {
++ return iterator.hasNext();
++ }
++
++ return true;
++ }
++
++ /**
++ * Returns true if there are previous elements in the iterator.
++ *
++ * @return true if there are previous elements
++ */
++ public boolean hasPrevious() {
++ if (currentIndex == 0) {
++ return false;
++ }
++
++ return true;
++ }
++
++ /**
++ * Returns the next element from the iterator.
++ *
++ * @return the next element from the iterator
++ * @throws NoSuchElementException if there are no more elements
++ */
++ public E next() throws NoSuchElementException {
++ if (currentIndex < wrappedIteratorIndex) {
++ ++currentIndex;
++ return list.get(currentIndex - 1);
++ }
++
++ E retval = iterator.next();
++ list.add(retval);
++ ++currentIndex;
++ ++wrappedIteratorIndex;
++ return retval;
++ }
++
++ /**
++ * Returns in the index of the next element.
++ *
++ * @return the index of the next element
++ */
++ public int nextIndex() {
++ return currentIndex;
++ }
++
++ /**
++ * Returns the the previous element.
++ *
++ * @return the previous element
++ * @throws NoSuchElementException if there are no previous elements
++ */
++ public E previous() throws NoSuchElementException {
++ if (currentIndex == 0) {
++ throw new NoSuchElementException();
++ }
++
++ --currentIndex;
++ return list.get(currentIndex);
++ }
++
++ /**
++ * Returns the index of the previous element.
++ *
++ * @return the index of the previous element
++ */
++ public int previousIndex() {
++ return currentIndex - 1;
++ }
++
++ /**
++ * Throws {@link UnsupportedOperationException}.
++ *
++ * @throws UnsupportedOperationException always
++ */
++ public void remove() throws UnsupportedOperationException {
++ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_MESSAGE);
++ }
++
++ /**
++ * Throws {@link UnsupportedOperationException}.
++ *
++ * @param o ignored
++ * @throws UnsupportedOperationException always
++ */
++ public void set(E o) throws UnsupportedOperationException {
++ throw new UnsupportedOperationException(UNSUPPORTED_OPERATION_MESSAGE);
++ }
++
++}
++
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/LoopingIterator.java
+@@ -0,0 +1,130 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.ResettableIterator;
++
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.NoSuchElementException;
++
++/**
++ * An Iterator that restarts when it reaches the end.
++ * <p/>
++ * The iterator will loop continuously around the provided elements, unless
++ * there are no elements in the collection to begin with, or all the elements
++ * have been {@link #remove removed}.
++ * <p/>
++ * Concurrent modifications are not directly supported, and for most collection
++ * implementations will throw a ConcurrentModificationException.
++ *
++ * @author <a href="mailto:joncrlsn at users.sf.net">Jonathan Carlson</a>
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class LoopingIterator <E> implements ResettableIterator<E> {
++
++ /**
++ * The collection to base the iterator on
++ */
++ private Collection<E> collection;
++ /**
++ * The current iterator
++ */
++ private Iterator<E> iterator;
++
++ /**
++ * Constructor that wraps a collection.
++ * <p/>
++ * There is no way to reset an Iterator instance without recreating it from
++ * the original source, so the Collection must be passed in.
++ *
++ * @param coll the collection to wrap
++ * @throws NullPointerException if the collection is null
++ */
++ public LoopingIterator(Collection<E> coll) {
++ if (coll == null) {
++ throw new NullPointerException("The collection must not be null");
++ }
++ collection = coll;
++ reset();
++ }
++
++ /**
++ * Has the iterator any more elements.
++ * <p/>
++ * Returns false only if the collection originally had zero elements, or
++ * all the elements have been {@link #remove removed}.
++ *
++ * @return <code>true</code> if there are more elements
++ */
++ public boolean hasNext() {
++ return (collection.size() > 0);
++ }
++
++ /**
++ * Returns the next object in the collection.
++ * <p/>
++ * If at the end of the collection, return the first element.
++ *
++ * @throws NoSuchElementException if there are no elements
++ * at all. Use {@link #hasNext} to avoid this error.
++ */
++ public E next() {
++ if (collection.size() == 0) {
++ throw new NoSuchElementException("There are no elements for this iterator to loop on");
++ }
++ if (iterator.hasNext() == false) {
++ reset();
++ }
++ return iterator.next();
++ }
++
++ /**
++ * Removes the previously retrieved item from the underlying collection.
++ * <p/>
++ * This feature is only supported if the underlying collection's
++ * {@link Collection#iterator iterator} method returns an implementation
++ * that supports it.
++ * <p/>
++ * This method can only be called after at least one {@link #next} method call.
++ * After a removal, the remove method may not be called again until another
++ * next has been performed. If the {@link #reset} is called, then remove may
++ * not be called until {@link #next} is called again.
++ */
++ public void remove() {
++ iterator.remove();
++ }
++
++ /**
++ * Resets the iterator back to the start of the collection.
++ */
++ public void reset() {
++ iterator = collection.iterator();
++ }
++
++ /**
++ * Gets the size of the collection underlying the iterator.
++ *
++ * @return the current collection size
++ */
++ public int size() {
++ return collection.size();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/ObjectArrayIterator.java
+@@ -0,0 +1,222 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.ResettableIterator;
++
++import java.util.Iterator;
++import java.util.NoSuchElementException;
++
++/**
++ * An {@link Iterator} over an array of objects.
++ * <p/>
++ * This iterator does not support {@link #remove}, as the object array cannot be
++ * structurally modified.
++ * <p/>
++ * The iterator implements a {@link #reset} method, allowing the reset of the iterator
++ * back to the start if required.
++ *
++ * @author James Strachan
++ * @author Mauricio S. Moura
++ * @author Michael A. Smith
++ * @author Neil O'Toole
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Phil Steitz
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public class ObjectArrayIterator <E> implements Iterator<E>, ResettableIterator<E> {
++
++ /**
++ * The array
++ */
++ protected E[] array = null;
++ /**
++ * The start index to loop from
++ */
++ protected int startIndex = 0;
++ /**
++ * The end index to loop to
++ */
++ protected int endIndex = 0;
++ /**
++ * The current iterator index
++ */
++ protected int index = 0;
++
++ /**
++ * Constructor for use with <code>setArray</code>.
++ * <p/>
++ * Using this constructor, the iterator is equivalent to an empty iterator
++ * until {@link #setArray} is called to establish the array to iterate over.
++ */
++ public ObjectArrayIterator() {
++ super();
++ }
++
++ /**
++ * Constructs an ObjectArrayIterator that will iterate over the values in the
++ * specified array.
++ *
++ * @param array the array to iterate over
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ */
++ public ObjectArrayIterator(E[] array) {
++ this(array, 0, array.length);
++ }
++
++ /**
++ * Constructs an ObjectArrayIterator that will iterate over the values in the
++ * specified array from a specific start index.
++ *
++ * @param array the array to iterate over
++ * @param start the index to start iterating at
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ * @throws IndexOutOfBoundsException if the start index is out of bounds
++ */
++ public ObjectArrayIterator(E[] array, int start) {
++ this(array, start, array.length);
++ }
++
++ /**
++ * Construct an ObjectArrayIterator that will iterate over a range of values
++ * in the specified array.
++ *
++ * @param array the array to iterate over
++ * @param start the index to start iterating at
++ * @param end the index (exclusive) to finish iterating at
++ * @throws IndexOutOfBoundsException if the start or end index is out of bounds
++ * @throws IllegalArgumentException if end index is before the start
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ */
++ public ObjectArrayIterator(E[] array, int start, int end) {
++ super();
++ if (start < 0) {
++ throw new ArrayIndexOutOfBoundsException("Start index must not be less than zero");
++ }
++ if (end > array.length) {
++ throw new ArrayIndexOutOfBoundsException("End index must not be greater than the array length");
++ }
++ if (start > array.length) {
++ throw new ArrayIndexOutOfBoundsException("Start index must not be greater than the array length");
++ }
++ if (end < start) {
++ throw new IllegalArgumentException("End index must not be less than start index");
++ }
++ this.array = array;
++ this.startIndex = start;
++ this.endIndex = end;
++ this.index = start;
++ }
++
++ // Iterator interface
++ //-------------------------------------------------------------------------
++
++ /**
++ * Returns true if there are more elements to return from the array.
++ *
++ * @return true if there is a next element to return
++ */
++ public boolean hasNext() {
++ return (this.index < this.endIndex);
++ }
++
++ /**
++ * Returns the next element in the array.
++ *
++ * @return the next element in the array
++ * @throws NoSuchElementException if all the elements in the array
++ * have already been returned
++ */
++ public E next() {
++ if (hasNext() == false) {
++ throw new NoSuchElementException();
++ }
++ return this.array[this.index++];
++ }
++
++ /**
++ * Throws {@link UnsupportedOperationException}.
++ *
++ * @throws UnsupportedOperationException always
++ */
++ public void remove() {
++ throw new UnsupportedOperationException("remove() method is not supported for an ObjectArrayIterator");
++ }
++
++ // Properties
++ //-------------------------------------------------------------------------
++
++ /**
++ * Gets the array that this iterator is iterating over.
++ *
++ * @return the array this iterator iterates over, or <code>null</code> if
++ * the no-arg constructor was used and {@link #setArray} has never
++ * been called with a valid array.
++ */
++ public E[] getArray() {
++ return this.array;
++ }
++
++ /**
++ * Sets the array that the ArrayIterator should iterate over.
++ * <p/>
++ * This method may only be called once, otherwise an IllegalStateException
++ * will occur.
++ * <p/>
++ * The {@link #reset} method can be used to reset the iterator if required.
++ *
++ * @param array the array that the iterator should iterate over
++ * @throws IllegalStateException if the <code>array</code> was set in the constructor
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ */
++ public void setArray(E[] array) {
++ if (this.array != null) {
++ throw new IllegalStateException("The array to iterate over has already been set");
++ }
++ this.array = array;
++ this.startIndex = 0;
++ this.endIndex = array.length;
++ this.index = 0;
++ }
++
++ /**
++ * Gets the start index to loop from.
++ *
++ * @return the start index
++ */
++ public int getStartIndex() {
++ return this.startIndex;
++ }
++
++ /**
++ * Gets the end index to loop to.
++ *
++ * @return the end index
++ */
++ public int getEndIndex() {
++ return this.endIndex;
++ }
++
++ /**
++ * Resets the iterator back to the start index.
++ */
++ public void reset() {
++ this.index = this.startIndex;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/ObjectArrayListIterator.java
+@@ -0,0 +1,203 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.ResettableListIterator;
++
++import java.util.ListIterator;
++import java.util.NoSuchElementException;
++
++/**
++ * Implements a {@link ListIterator} over an array of objects.
++ * <p/>
++ * This iterator does not support {@link #add} or {@link #remove}, as the object array
++ * cannot be structurally modified. The {@link #set} method is supported however.
++ * <p/>
++ * The iterator implements a {@link #reset} method, allowing the reset of the iterator
++ * back to the start if required.
++ *
++ * @author Neil O'Toole
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Phil Steitz
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @see org.apache.commons.collections15.iterators.ObjectArrayIterator
++ * @see java.util.Iterator
++ * @see java.util.ListIterator
++ * @since Commons Collections 3.0
++ */
++public class ObjectArrayListIterator <E> extends ObjectArrayIterator<E> implements ListIterator<E>, ResettableListIterator<E> {
++
++ /**
++ * Holds the index of the last item returned by a call to <code>next()</code>
++ * or <code>previous()</code>. This is set to <code>-1</code> if neither method
++ * has yet been invoked. <code>lastItemIndex</code> is used to to implement the
++ * {@link #set} method.
++ */
++ protected int lastItemIndex = -1;
++
++ /**
++ * Constructor for use with <code>setArray</code>.
++ * <p/>
++ * Using this constructor, the iterator is equivalent to an empty iterator
++ * until {@link #setArray} is called to establish the array to iterate over.
++ */
++ public ObjectArrayListIterator() {
++ super();
++ }
++
++ /**
++ * Constructs an ObjectArrayListIterator that will iterate over the values in the
++ * specified array.
++ *
++ * @param array the array to iterate over
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ */
++ public ObjectArrayListIterator(E[] array) {
++ super(array);
++ }
++
++ /**
++ * Constructs an ObjectArrayListIterator that will iterate over the values in the
++ * specified array from a specific start index.
++ *
++ * @param array the array to iterate over
++ * @param start the index to start iterating at
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ * @throws IndexOutOfBoundsException if the start index is out of bounds
++ */
++ public ObjectArrayListIterator(E[] array, int start) {
++ super(array, start);
++ }
++
++ /**
++ * Construct an ObjectArrayListIterator that will iterate over a range of values
++ * in the specified array.
++ *
++ * @param array the array to iterate over
++ * @param start the index to start iterating at
++ * @param end the index (exclusive) to finish iterating at
++ * @throws IndexOutOfBoundsException if the start or end index is out of bounds
++ * @throws IllegalArgumentException if end index is before the start
++ * @throws NullPointerException if <code>array</code> is <code>null</code>
++ */
++ public ObjectArrayListIterator(E[] array, int start, int end) {
++ super(array, start, end);
++ }
++
++ // ListIterator interface
++ //-------------------------------------------------------------------------
++
++ /**
++ * Returns true if there are previous elements to return from the array.
++ *
++ * @return true if there is a previous element to return
++ */
++ public boolean hasPrevious() {
++ return (this.index > this.startIndex);
++ }
++
++ /**
++ * Gets the previous element from the array.
++ *
++ * @return the previous element
++ * @throws NoSuchElementException if there is no previous element
++ */
++ public E previous() {
++ if (hasPrevious() == false) {
++ throw new NoSuchElementException();
++ }
++ this.lastItemIndex = --this.index;
++ return this.array[this.index];
++ }
++
++ /**
++ * Gets the next element from the array.
++ *
++ * @return the next element
++ * @throws NoSuchElementException if there is no next element
++ */
++ public E next() {
++ if (hasNext() == false) {
++ throw new NoSuchElementException();
++ }
++ this.lastItemIndex = this.index;
++ return this.array[this.index++];
++ }
++
++ /**
++ * Gets the next index to be retrieved.
++ *
++ * @return the index of the item to be retrieved next
++ */
++ public int nextIndex() {
++ return this.index - this.startIndex;
++ }
++
++ /**
++ * Gets the index of the item to be retrieved if {@link #previous()} is called.
++ *
++ * @return the index of the item to be retrieved next
++ */
++ public int previousIndex() {
++ return this.index - this.startIndex - 1;
++ }
++
++ /**
++ * This iterator does not support modification of its backing array's size, and so will
++ * always throw an {@link UnsupportedOperationException} when this method is invoked.
++ *
++ * @param obj the object to add
++ * @throws UnsupportedOperationException always thrown.
++ */
++ public void add(E obj) {
++ throw new UnsupportedOperationException("add() method is not supported");
++ }
++
++ /**
++ * Sets the element under the cursor.
++ * <p/>
++ * This method sets the element that was returned by the last call
++ * to {@link #next()} of {@link #previous()}.
++ * <p/>
++ * <b>Note:</b> {@link ListIterator} implementations that support <code>add()</code>
++ * and <code>remove()</code> only allow <code>set()</code> to be called once per call
++ * to <code>next()</code> or <code>previous</code> (see the {@link ListIterator}
++ * javadoc for more details). Since this implementation does not support
++ * <code>add()</code> or <code>remove()</code>, <code>set()</code> may be
++ * called as often as desired.
++ *
++ * @param obj the object to set into the array
++ * @throws IllegalStateException if next() has not yet been called.
++ * @throws ClassCastException if the object type is unsuitable for the array
++ */
++ public void set(E obj) {
++ if (this.lastItemIndex == -1) {
++ throw new IllegalStateException("must call next() or previous() before a call to set()");
++ }
++
++ this.array[this.lastItemIndex] = obj;
++ }
++
++ /**
++ * Resets the iterator back to the start index.
++ */
++ public void reset() {
++ super.reset();
++ this.lastItemIndex = -1;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/ObjectGraphIterator.java
+@@ -0,0 +1,268 @@
++// GenericsNote: Won't be converted, not type safe.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.ArrayStack;
++import org.apache.commons.collections15.Transformer;
++
++import java.util.Iterator;
++import java.util.NoSuchElementException;
++
++/**
++ * An Iterator that can traverse multiple iterators down an object graph.
++ * <p/>
++ * This iterator can extract multiple objects from a complex tree-like object graph.
++ * The iteration starts from a single root object.
++ * It uses a <code>Transformer</code> to extract the iterators and elements.
++ * Its main benefit is that no intermediate <code>List</code> is created.
++ * <p/>
++ * For example, consider an object graph:
++ * <pre>
++ * |- Branch -- Leaf
++ * | \- Leaf
++ * |- Tree | /- Leaf
++ * | |- Branch -- Leaf
++ * Forest | \- Leaf
++ * | |- Branch -- Leaf
++ * | | \- Leaf
++ * |- Tree | /- Leaf
++ * |- Branch -- Leaf
++ * |- Branch -- Leaf</pre>
++ * The following <code>Transformer</code>, used in this class, will extract all
++ * the Leaf objects without creating a combined intermediate list:
++ * <pre>
++ * public Object transform(Object input) {
++ * if (input instanceof Forest) {
++ * return ((Forest) input).treeIterator();
++ * }
++ * if (input instanceof Tree) {
++ * return ((Tree) input).branchIterator();
++ * }
++ * if (input instanceof Branch) {
++ * return ((Branch) input).leafIterator();
++ * }
++ * if (input instanceof Leaf) {
++ * return input;
++ * }
++ * throw new ClassCastException();
++ * }</pre>
++ * <p/>
++ * Internally, iteration starts from the root object. When next is called,
++ * the transformer is called to examine the object. The transformer will return
++ * either an iterator or an object. If the object is an Iterator, the next element
++ * from that iterator is obtained and the process repeats. If the element is an object
++ * it is returned.
++ * <p/>
++ * Under many circumstances, linking Iterators together in this manner is
++ * more efficient (and convenient) than using nested for loops to extract a list.
++ * <p/>
++ * Note: this class is not type-safe in Java 1.5 (no generics).
++ * <p/>
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.1
++ */
++public class ObjectGraphIterator implements Iterator {
++
++ /**
++ * The stack of iterators
++ */
++ protected final ArrayStack stack = new ArrayStack(8);
++ /**
++ * The root object in the tree
++ */
++ protected Object root;
++ /**
++ * The transformer to use
++ */
++ protected Transformer transformer;
++
++ /**
++ * Whether there is another element in the iteration
++ */
++ protected boolean hasNext = false;
++ /**
++ * The current iterator
++ */
++ protected Iterator currentIterator;
++ /**
++ * The current value
++ */
++ protected Object currentValue;
++ /**
++ * The last used iterator, needed for remove()
++ */
++ protected Iterator lastUsedIterator;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructs an ObjectGraphIterator using a root object and transformer.
++ * <p/>
++ * The root object can be an iterator, in which case it will be immediately
++ * looped around.
++ *
++ * @param root the root object, null will result in an empty iterator
++ * @param transformer the transformer to use, null will use a no effect transformer
++ */
++ public ObjectGraphIterator(Object root, Transformer transformer) {
++ super();
++ if (root instanceof Iterator) {
++ this.currentIterator = (Iterator) root;
++ } else {
++ this.root = root;
++ }
++ this.transformer = transformer;
++ }
++
++ /**
++ * Constructs a ObjectGraphIterator that will handle an iterator of iterators.
++ * <p/>
++ * This constructor exists for convenience to emphasise that this class can
++ * be used to iterate over nested iterators. That is to say that the iterator
++ * passed in here contains other iterators, which may in turn contain further
++ * iterators.
++ *
++ * @param rootIterator the root iterator, null will result in an empty iterator
++ */
++ public ObjectGraphIterator(Iterator rootIterator) {
++ super();
++ this.currentIterator = rootIterator;
++ this.transformer = null;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Loops around the iterators to find the next value to return.
++ */
++ protected void updateCurrentIterator() {
++ if (hasNext) {
++ return;
++ }
++ if (currentIterator == null) {
++ if (root == null) {
++ // do nothing, hasNext will be false
++ } else {
++ if (transformer == null) {
++ findNext(root);
++ } else {
++ findNext(transformer.transform(root));
++ }
++ root = null;
++ }
++ } else {
++ findNextByIterator(currentIterator);
++ }
++ }
++
++ /**
++ * Finds the next object in the iteration given any start object.
++ *
++ * @param value the value to start from
++ */
++ protected void findNext(Object value) {
++ if (value instanceof Iterator) {
++ // need to examine this iterator
++ findNextByIterator((Iterator) value);
++ } else {
++ // next value found
++ currentValue = value;
++ hasNext = true;
++ }
++ }
++
++ /**
++ * Finds the next object in the iteration given an iterator.
++ *
++ * @param iterator the iterator to start from
++ */
++ protected void findNextByIterator(Iterator iterator) {
++ if (iterator != currentIterator) {
++ // recurse a level
++ if (currentIterator != null) {
++ stack.push(currentIterator);
++ }
++ currentIterator = iterator;
++ }
++
++ while (currentIterator.hasNext() && hasNext == false) {
++ Object next = currentIterator.next();
++ if (transformer != null) {
++ next = transformer.transform(next);
++ }
++ findNext(next);
++ }
++ if (hasNext) {
++ // next value found
++ } else if (stack.isEmpty()) {
++ // all iterators exhausted
++ } else {
++ // current iterator exhausted, go up a level
++ currentIterator = (Iterator) stack.pop();
++ findNextByIterator(currentIterator);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Checks whether there are any more elements in the iteration to obtain.
++ *
++ * @return true if elements remain in the iteration
++ */
++ public boolean hasNext() {
++ updateCurrentIterator();
++ return hasNext;
++ }
++
++ /**
++ * Gets the next element of the iteration.
++ *
++ * @return the next element from the iteration
++ * @throws NoSuchElementException if all the Iterators are exhausted
++ */
++ public Object next() {
++ updateCurrentIterator();
++ if (hasNext == false) {
++ throw new NoSuchElementException("No more elements in the iteration");
++ }
++ lastUsedIterator = currentIterator;
++ Object result = currentValue;
++ currentValue = null;
++ hasNext = false;
++ return result;
++ }
++
++ /**
++ * Removes from the underlying collection the last element returned.
++ * <p/>
++ * This method calls remove() on the underlying Iterator and it may
++ * throw an UnsupportedOperationException if the underlying Iterator
++ * does not support this method.
++ *
++ * @throws UnsupportedOperationException if the remove operator is not supported by the underlying Iterator
++ * @throws IllegalStateException if the next method has not yet been called, or the remove method has
++ * already been called after the last call to the next method.
++ */
++ public void remove() {
++ if (lastUsedIterator == null) {
++ throw new IllegalStateException("Iterator remove() cannot be called at this time");
++ }
++ lastUsedIterator.remove();
++ lastUsedIterator = null;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/SingletonIterator.java
+@@ -0,0 +1,135 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.ResettableIterator;
++
++import java.util.Iterator;
++import java.util.NoSuchElementException;
++
++/**
++ * <code>SingletonIterator</code> is an {@link Iterator} over a single
++ * object instance.
++ *
++ * @author James Strachan
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Rodney Waldhoff
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 2.0
++ */
++public class SingletonIterator <E> implements Iterator<E>, ResettableIterator<E> {
++
++ /**
++ * Whether remove is allowed
++ */
++ private final boolean removeAllowed;
++ /**
++ * Is the cursor before the first element
++ */
++ private boolean beforeFirst = true;
++ /**
++ * Has the element been removed
++ */
++ private boolean removed = false;
++ /**
++ * The object
++ */
++ private E object;
++
++ /**
++ * Constructs a new <code>SingletonIterator</code> where <code>remove</code>
++ * is a permitted operation.
++ *
++ * @param object the single object to return from the iterator
++ */
++ public SingletonIterator(E object) {
++ this(object, true);
++ }
++
++ /**
++ * Constructs a new <code>SingletonIterator</code> optionally choosing if
++ * <code>remove</code> is a permitted operation.
++ *
++ * @param object the single object to return from the iterator
++ * @param removeAllowed true if remove is allowed
++ * @since Commons Collections 3.1
++ */
++ public SingletonIterator(E object, boolean removeAllowed) {
++ super();
++ this.object = object;
++ this.removeAllowed = removeAllowed;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Is another object available from the iterator?
++ * <p/>
++ * This returns true if the single object hasn't been returned yet.
++ *
++ * @return true if the single object hasn't been returned yet
++ */
++ public boolean hasNext() {
++ return (beforeFirst && !removed);
++ }
++
++ /**
++ * Get the next object from the iterator.
++ * <p/>
++ * This returns the single object if it hasn't been returned yet.
++ *
++ * @return the single object
++ * @throws NoSuchElementException if the single object has already
++ * been returned
++ */
++ public E next() {
++ if (!beforeFirst || removed) {
++ throw new NoSuchElementException();
++ }
++ beforeFirst = false;
++ return object;
++ }
++
++ /**
++ * Remove the object from this iterator.
++ *
++ * @throws IllegalStateException if the <tt>next</tt> method has not
++ * yet been called, or the <tt>remove</tt> method has already
++ * been called after the last call to the <tt>next</tt>
++ * method.
++ * @throws UnsupportedOperationException if remove is not supported
++ */
++ public void remove() {
++ if (removeAllowed) {
++ if (removed || beforeFirst) {
++ throw new IllegalStateException();
++ } else {
++ object = null;
++ removed = true;
++ }
++ } else {
++ throw new UnsupportedOperationException();
++ }
++ }
++
++ /**
++ * Reset the iterator to the start.
++ */
++ public void reset() {
++ beforeFirst = true;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/SingletonListIterator.java
+@@ -0,0 +1,176 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.ResettableListIterator;
++
++import java.util.ListIterator;
++import java.util.NoSuchElementException;
++
++/**
++ * <code>SingletonIterator</code> is an {@link ListIterator} over a single
++ * object instance.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Rodney Waldhoff
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 2.1
++ */
++public class SingletonListIterator <E> implements ListIterator<E>, ResettableListIterator<E> {
++
++ private boolean beforeFirst = true;
++ private boolean nextCalled = false;
++ private boolean removed = false;
++ private E object;
++
++ /**
++ * Constructs a new <code>SingletonListIterator</code>.
++ *
++ * @param object the single object to return from the iterator
++ */
++ public SingletonListIterator(E object) {
++ super();
++ this.object = object;
++ }
++
++ /**
++ * Is another object available from the iterator?
++ * <p/>
++ * This returns true if the single object hasn't been returned yet.
++ *
++ * @return true if the single object hasn't been returned yet
++ */
++ public boolean hasNext() {
++ return beforeFirst && !removed;
++ }
++
++ /**
++ * Is a previous object available from the iterator?
++ * <p/>
++ * This returns true if the single object has been returned.
++ *
++ * @return true if the single object has been returned
++ */
++ public boolean hasPrevious() {
++ return !beforeFirst && !removed;
++ }
++
++ /**
++ * Returns the index of the element that would be returned by a subsequent
++ * call to <tt>next</tt>.
++ *
++ * @return 0 or 1 depending on current state.
++ */
++ public int nextIndex() {
++ return (beforeFirst ? 0 : 1);
++ }
++
++ /**
++ * Returns the index of the element that would be returned by a subsequent
++ * call to <tt>previous</tt>. A return value of -1 indicates that the iterator is currently at
++ * the start.
++ *
++ * @return 0 or -1 depending on current state.
++ */
++ public int previousIndex() {
++ return (beforeFirst ? -1 : 0);
++ }
++
++ /**
++ * Get the next object from the iterator.
++ * <p/>
++ * This returns the single object if it hasn't been returned yet.
++ *
++ * @return the single object
++ * @throws NoSuchElementException if the single object has already
++ * been returned
++ */
++ public E next() {
++ if (!beforeFirst || removed) {
++ throw new NoSuchElementException();
++ }
++ beforeFirst = false;
++ nextCalled = true;
++ return object;
++ }
++
++ /**
++ * Get the previous object from the iterator.
++ * <p/>
++ * This returns the single object if it has been returned.
++ *
++ * @return the single object
++ * @throws NoSuchElementException if the single object has not already
++ * been returned
++ */
++ public E previous() {
++ if (beforeFirst || removed) {
++ throw new NoSuchElementException();
++ }
++ beforeFirst = true;
++ return object;
++ }
++
++ /**
++ * Remove the object from this iterator.
++ *
++ * @throws IllegalStateException if the <tt>next</tt> or <tt>previous</tt>
++ * method has not yet been called, or the <tt>remove</tt> method
++ * has already been called after the last call to <tt>next</tt>
++ * or <tt>previous</tt>.
++ */
++ public void remove() {
++ if (!nextCalled || removed) {
++ throw new IllegalStateException();
++ } else {
++ object = null;
++ removed = true;
++ }
++ }
++
++ /**
++ * Add always throws {@link UnsupportedOperationException}.
++ *
++ * @throws UnsupportedOperationException always
++ */
++ public void add(E obj) {
++ throw new UnsupportedOperationException("add() is not supported by this iterator");
++ }
++
++ /**
++ * Set sets the value of the singleton.
++ *
++ * @param obj the object to set
++ * @throws IllegalStateException if <tt>next</tt> has not been called
++ * or the object has been removed
++ */
++ public void set(E obj) {
++ if (!nextCalled || removed) {
++ throw new IllegalStateException();
++ }
++ this.object = obj;
++ }
++
++ /**
++ * Reset the iterator back to the start.
++ */
++ public void reset() {
++ beforeFirst = true;
++ nextCalled = false;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/TransformIterator.java
+@@ -0,0 +1,155 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.Transformer;
++
++import java.util.Iterator;
++
++/**
++ * Decorates an iterator such that each element returned is transformed.
++ *
++ * @author James Strachan
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 1.0
++ */
++public class TransformIterator <I,O> implements Iterator<O> {
++
++ /**
++ * The iterator being used
++ */
++ private Iterator<I> iterator;
++ /**
++ * The transformer being used
++ */
++ private Transformer<I, O> transformer;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructs a new <code>TransformIterator</code> that will not function
++ * until the {@link #setIterator(Iterator) setIterator} method is
++ * invoked.
++ */
++ public TransformIterator() {
++ super();
++ }
++
++ /**
++ * Constructs a new <code>TransformIterator</code> that won't transform
++ * elements from the given iterator.
++ *
++ * @param iterator the iterator to use
++ */
++ public TransformIterator(Iterator<I> iterator) {
++ super();
++ this.iterator = iterator;
++ }
++
++ /**
++ * Constructs a new <code>TransformIterator</code> that will use the
++ * given iterator and transformer. If the given transformer is null,
++ * then objects will not be transformed.
++ *
++ * @param iterator the iterator to use
++ * @param transformer the transformer to use
++ */
++ public TransformIterator(Iterator<I> iterator, Transformer<I, O> transformer) {
++ super();
++ this.iterator = iterator;
++ this.transformer = transformer;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ /**
++ * Gets the next object from the iteration, transforming it using the
++ * current transformer. If the transformer is null, no transformation
++ * occurs and the object from the iterator is returned directly.
++ *
++ * @return the next object
++ * @throws java.util.NoSuchElementException
++ * if there are no more elements
++ */
++ public O next() {
++ return transform(iterator.next());
++ }
++
++ public void remove() {
++ iterator.remove();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the iterator this iterator is using.
++ *
++ * @return the iterator.
++ */
++ public Iterator<I> getIterator() {
++ return iterator;
++ }
++
++ /**
++ * Sets the iterator for this iterator to use.
++ * If iteration has started, this effectively resets the iterator.
++ *
++ * @param iterator the iterator to use
++ */
++ public void setIterator(Iterator<I> iterator) {
++ this.iterator = iterator;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the transformer this iterator is using.
++ *
++ * @return the transformer.
++ */
++ public Transformer<I, O> getTransformer() {
++ return transformer;
++ }
++
++ /**
++ * Sets the transformer this the iterator to use.
++ * A null transformer is a no-op transformer.
++ *
++ * @param transformer the transformer to use
++ */
++ public void setTransformer(Transformer<I, O> transformer) {
++ this.transformer = transformer;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Transforms the given object using the transformer.
++ * If the transformer is null, the original object is returned as-is.
++ *
++ * @param source the object to transform
++ * @return the transformed object
++ */
++ protected O transform(I source) {
++ if (transformer != null) {
++ return transformer.transform(source);
++ }
++ // Generics hack
++ Object sourceObj = source;
++ return (O) sourceObj;
++ }
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/UniqueFilterIterator.java
+@@ -0,0 +1,45 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.functors.UniquePredicate;
++
++import java.util.Iterator;
++
++/**
++ * A FilterIterator which only returns "unique" Objects. Internally,
++ * the Iterator maintains a Set of objects it has already encountered,
++ * and duplicate Objects are skipped.
++ *
++ * @author Matt Hall, John Watkinson, Morgan Delagrange
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 2.1
++ */
++public class UniqueFilterIterator <E> extends FilterIterator<E> {
++
++ //-------------------------------------------------------------------------
++
++ /**
++ * Constructs a new <code>UniqueFilterIterator</code>.
++ *
++ * @param iterator the iterator to use
++ */
++ public UniqueFilterIterator(Iterator<E> iterator) {
++ super(iterator, UniquePredicate.getInstance());
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/UnmodifiableIterator.java
+@@ -0,0 +1,80 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.Unmodifiable;
++
++import java.util.Iterator;
++
++/**
++ * Decorates an iterator such that it cannot be modified.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableIterator <E> implements Iterator<E>, Unmodifiable {
++
++ /**
++ * The iterator being decorated
++ */
++ private Iterator<E> iterator;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Decorates the specified iterator such that it cannot be modified.
++ * <p/>
++ * If the iterator is already unmodifiable it is returned directly.
++ *
++ * @param iterator the iterator to decorate
++ * @throws IllegalArgumentException if the iterator is null
++ */
++ public static <E> Iterator<E> decorate(Iterator<E> iterator) {
++ if (iterator == null) {
++ throw new IllegalArgumentException("Iterator must not be null");
++ }
++ if (iterator instanceof Unmodifiable) {
++ return iterator;
++ }
++ return new UnmodifiableIterator<E>(iterator);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor.
++ *
++ * @param iterator the iterator to decorate
++ */
++ private UnmodifiableIterator(Iterator<E> iterator) {
++ super();
++ this.iterator = iterator;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ public E next() {
++ return iterator.next();
++ }
++
++ public void remove() {
++ throw new UnsupportedOperationException("remove() is not supported");
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/UnmodifiableListIterator.java
+@@ -0,0 +1,102 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.Unmodifiable;
++
++import java.util.ListIterator;
++
++/**
++ * Decorates a list iterator such that it cannot be modified.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableListIterator <E> implements ListIterator<E>, Unmodifiable {
++
++ /**
++ * The iterator being decorated
++ */
++ private ListIterator<E> iterator;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Decorates the specified iterator such that it cannot be modified.
++ *
++ * @param iterator the iterator to decorate
++ * @throws IllegalArgumentException if the iterator is null
++ */
++ public static <E> ListIterator<E> decorate(ListIterator<E> iterator) {
++ if (iterator == null) {
++ throw new IllegalArgumentException("ListIterator must not be null");
++ }
++ if (iterator instanceof Unmodifiable) {
++ return iterator;
++ }
++ return new UnmodifiableListIterator<E>(iterator);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor.
++ *
++ * @param iterator the iterator to decorate
++ */
++ private UnmodifiableListIterator(ListIterator<E> iterator) {
++ super();
++ this.iterator = iterator;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ public E next() {
++ return iterator.next();
++ }
++
++ public int nextIndex() {
++ return iterator.nextIndex();
++ }
++
++ public boolean hasPrevious() {
++ return iterator.hasPrevious();
++ }
++
++ public E previous() {
++ return iterator.previous();
++ }
++
++ public int previousIndex() {
++ return iterator.previousIndex();
++ }
++
++ public void remove() {
++ throw new UnsupportedOperationException("remove() is not supported");
++ }
++
++ public void set(E obj) {
++ throw new UnsupportedOperationException("set() is not supported");
++ }
++
++ public void add(E obj) {
++ throw new UnsupportedOperationException("add() is not supported");
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/UnmodifiableMapIterator.java
+@@ -0,0 +1,89 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.Unmodifiable;
++
++/**
++ * Decorates a map iterator such that it cannot be modified.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableMapIterator <K,V> implements MapIterator<K, V>, Unmodifiable {
++
++ /**
++ * The iterator being decorated
++ */
++ private MapIterator<K, V> iterator;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Decorates the specified iterator such that it cannot be modified.
++ *
++ * @param iterator the iterator to decorate
++ * @throws IllegalArgumentException if the iterator is null
++ */
++ public static <K,V> MapIterator<K, V> decorate(MapIterator<K, V> iterator) {
++ if (iterator == null) {
++ throw new IllegalArgumentException("MapIterator must not be null");
++ }
++ if (iterator instanceof Unmodifiable) {
++ return iterator;
++ }
++ return new UnmodifiableMapIterator<K, V>(iterator);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor.
++ *
++ * @param iterator the iterator to decorate
++ */
++ private UnmodifiableMapIterator(MapIterator<K, V> iterator) {
++ super();
++ this.iterator = iterator;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ public K next() {
++ return iterator.next();
++ }
++
++ public K getKey() {
++ return iterator.getKey();
++ }
++
++ public V getValue() {
++ return iterator.getValue();
++ }
++
++ public V setValue(V value) {
++ throw new UnsupportedOperationException("setValue() is not supported");
++ }
++
++ public void remove() {
++ throw new UnsupportedOperationException("remove() is not supported");
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/UnmodifiableOrderedMapIterator.java
+@@ -0,0 +1,97 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 1999-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.iterators;
++
++import org.apache.commons.collections15.OrderedMapIterator;
++import org.apache.commons.collections15.Unmodifiable;
++
++/**
++ * Decorates an ordered map iterator such that it cannot be modified.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableOrderedMapIterator <K,V> implements OrderedMapIterator<K, V>, Unmodifiable {
++
++ /**
++ * The iterator being decorated
++ */
++ private OrderedMapIterator<K, V> iterator;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Decorates the specified iterator such that it cannot be modified.
++ *
++ * @param iterator the iterator to decorate
++ * @throws IllegalArgumentException if the iterator is null
++ */
++ public static <K,V> OrderedMapIterator<K, V> decorate(OrderedMapIterator<K, V> iterator) {
++ if (iterator == null) {
++ throw new IllegalArgumentException("OrderedMapIterator must not be null");
++ }
++ if (iterator instanceof Unmodifiable) {
++ return iterator;
++ }
++ return new UnmodifiableOrderedMapIterator<K, V>(iterator);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor.
++ *
++ * @param iterator the iterator to decorate
++ */
++ private UnmodifiableOrderedMapIterator(OrderedMapIterator<K, V> iterator) {
++ super();
++ this.iterator = iterator;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ public K next() {
++ return iterator.next();
++ }
++
++ public boolean hasPrevious() {
++ return iterator.hasPrevious();
++ }
++
++ public K previous() {
++ return iterator.previous();
++ }
++
++ public K getKey() {
++ return iterator.getKey();
++ }
++
++ public V getValue() {
++ return iterator.getValue();
++ }
++
++ public V setValue(V value) {
++ throw new UnsupportedOperationException("setValue() is not supported");
++ }
++
++ public void remove() {
++ throw new UnsupportedOperationException("remove() is not supported");
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/iterators/package.html
+@@ -0,0 +1,26 @@
++<!-- $Id: package.html,v 1.1 2005/10/11 17:05:24 pents90 Exp $ -->
++ <!--
++ Copyright 2002-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<body>
++<p>
++This package contains implementations of the
++{@link java.util.Iterator Iterator} interface.
++<p>
++You may also consider using
++{@link org.apache.commons.collections.IteratorUtils IteratorUtils},
++which is a single class that uses static methods to construct instances
++of the classes in this package.
++</body>
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/keyvalue/AbstractKeyValue.java
+@@ -0,0 +1,81 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.keyvalue;
++
++import org.apache.commons.collections15.KeyValue;
++
++/**
++ * Abstract pair class to assist with creating KeyValue and MapEntry implementations.
++ *
++ * @author James Strachan
++ * @author Michael A. Smith
++ * @author Neil O'Toole
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractKeyValue <K,V> implements KeyValue<K, V> {
++
++ /**
++ * The key
++ */
++ protected K key;
++ /**
++ * The value
++ */
++ protected V value;
++
++ /**
++ * Constructs a new pair with the specified key and given value.
++ *
++ * @param key the key for the entry, may be null
++ * @param value the value for the entry, may be null
++ */
++ protected AbstractKeyValue(K key, V value) {
++ super();
++ this.key = key;
++ this.value = value;
++ }
++
++ /**
++ * Gets the key from the pair.
++ *
++ * @return the key
++ */
++ public K getKey() {
++ return key;
++ }
++
++ /**
++ * Gets the value from the pair.
++ *
++ * @return the value
++ */
++ public V getValue() {
++ return value;
++ }
++
++ /**
++ * Gets a debugging String view of the pair.
++ *
++ * @return a String view of the entry
++ */
++ public String toString() {
++ return new StringBuffer().append(getKey()).append('=').append(getValue()).toString();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/keyvalue/AbstractMapEntry.java
+@@ -0,0 +1,89 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.keyvalue;
++
++import java.util.Map;
++
++/**
++ * Abstract Pair class to assist with creating correct Map Entry implementations.
++ *
++ * @author James Strachan
++ * @author Michael A. Smith
++ * @author Neil O'Toole
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractMapEntry <K,V> extends AbstractKeyValue<K, V> implements Map.Entry<K, V> {
++
++ /**
++ * Constructs a new entry 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
++ */
++ protected AbstractMapEntry(K key, V value) {
++ super(key, value);
++ }
++
++ // Map.Entry interface
++ //-------------------------------------------------------------------------
++ /**
++ * 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 V setValue(V value) {
++ V answer = this.value;
++ this.value = value;
++ return answer;
++ }
++
++ /**
++ * 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());
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/keyvalue/AbstractMapEntryDecorator.java
+@@ -0,0 +1,88 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.keyvalue;
++
++import org.apache.commons.collections15.KeyValue;
++
++import java.util.Map;
++
++/**
++ * Provides a base decorator that allows additional functionality to be added
++ * to a Map Entry.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractMapEntryDecorator <K,V> implements Map.Entry<K, V>, KeyValue<K, V> {
++
++ /**
++ * The <code>Map.Entry</code> to decorate
++ */
++ protected final Map.Entry<K, V> entry;
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param entry the <code>Map.Entry</code> to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ public AbstractMapEntryDecorator(Map.Entry<K, V> entry) {
++ if (entry == null) {
++ throw new IllegalArgumentException("Map Entry must not be null");
++ }
++ this.entry = entry;
++ }
++
++ /**
++ * Gets the map being decorated.
++ *
++ * @return the decorated map
++ */
++ protected Map.Entry<K, V> getMapEntry() {
++ return entry;
++ }
++
++ //-----------------------------------------------------------------------
++ public K getKey() {
++ return entry.getKey();
++ }
++
++ public V getValue() {
++ return entry.getValue();
++ }
++
++ public V setValue(V object) {
++ return entry.setValue(object);
++ }
++
++ public boolean equals(Object object) {
++ if (object == this) {
++ return true;
++ }
++ return entry.equals(object);
++ }
++
++ public int hashCode() {
++ return entry.hashCode();
++ }
++
++ public String toString() {
++ return entry.toString();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/keyvalue/DefaultKeyValue.java
+@@ -0,0 +1,154 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.keyvalue;
++
++import org.apache.commons.collections15.KeyValue;
++
++import java.util.Map;
++
++/**
++ * A mutable KeyValue pair that does not implement MapEntry.
++ * <p/>
++ * Note that a <code>DefaultKeyValue</code> instance may not contain
++ * itself as a key or value.
++ *
++ * @author James Strachan
++ * @author Michael A. Smith
++ * @author Neil O'Toole
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class DefaultKeyValue <K,V> extends AbstractKeyValue<K, V> {
++
++ /**
++ * Constructs a new pair with a null key and null value.
++ */
++ public DefaultKeyValue() {
++ super(null, null);
++ }
++
++ /**
++ * Constructs a new pair with the specified 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 DefaultKeyValue(final K key, final V value) {
++ super(key, value);
++ }
++
++ /**
++ * Constructs a new pair from the specified KeyValue.
++ *
++ * @param pair the pair to copy, must not be null
++ * @throws NullPointerException if the entry is null
++ */
++ public DefaultKeyValue(final KeyValue<K, V> pair) {
++ super(pair.getKey(), pair.getValue());
++ }
++
++ /**
++ * Constructs a new pair from the specified MapEntry.
++ *
++ * @param entry the entry to copy, must not be null
++ * @throws NullPointerException if the entry is null
++ */
++ public DefaultKeyValue(final Map.Entry<K, V> entry) {
++ super(entry.getKey(), entry.getValue());
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Sets the key.
++ *
++ * @param key the new key
++ * @return the old key
++ * @throws IllegalArgumentException if key is this object
++ */
++ public K setKey(final K key) {
++ if ((Object) key == this) {
++ throw new IllegalArgumentException("DefaultKeyValue may not contain itself as a key.");
++ }
++
++ final K old = this.key;
++ this.key = key;
++ return old;
++ }
++
++ /**
++ * Sets the value.
++ *
++ * @param value the new value
++ * @return the old value of the value
++ * @throws IllegalArgumentException if value is this object
++ */
++ public V setValue(final V value) {
++ if ((Object) value == this) {
++ throw new IllegalArgumentException("DefaultKeyValue may not contain itself as a value.");
++ }
++
++ final V old = this.value;
++ this.value = value;
++ return old;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns a new <code>Map.Entry</code> object with key and value from this pair.
++ *
++ * @return a MapEntry instance
++ */
++ public Map.Entry<K, V> toMapEntry() {
++ return new DefaultMapEntry<K, V>(this);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Compares this Map Entry with another Map Entry.
++ * <p/>
++ * Returns true if the compared object is also a <code>DefaultKeyValue</code>,
++ * and its key and value are equal to this object's key and value.
++ *
++ * @param obj the object to compare to
++ * @return true if equal key and value
++ */
++ public boolean equals(final Object obj) {
++ if (obj == this) {
++ return true;
++ }
++ if (obj instanceof DefaultKeyValue == false) {
++ return false;
++ }
++
++ DefaultKeyValue other = (DefaultKeyValue) 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()},
++ * however subclasses may override this.
++ *
++ * @return a suitable hash code
++ */
++ public int hashCode() {
++ return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode());
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/keyvalue/DefaultMapEntry.java
+@@ -0,0 +1,66 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.keyvalue;
++
++import org.apache.commons.collections15.KeyValue;
++
++import java.util.Map;
++
++/**
++ * A restricted implementation of {@link java.util.Map.Entry} that prevents
++ * the MapEntry contract from being broken.
++ *
++ * @author James Strachan
++ * @author Michael A. Smith
++ * @author Neil O'Toole
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public final class DefaultMapEntry <K,V> extends AbstractMapEntry<K, V> {
++
++ /**
++ * Constructs a new entry with the specified 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(final K key, final V value) {
++ super(key, value);
++ }
++
++ /**
++ * Constructs a new entry from the specified KeyValue.
++ *
++ * @param pair the pair to copy, must not be null
++ * @throws NullPointerException if the entry is null
++ */
++ public DefaultMapEntry(final KeyValue<K, V> pair) {
++ super(pair.getKey(), pair.getValue());
++ }
++
++ /**
++ * Constructs a new entry from the specified MapEntry.
++ *
++ * @param entry the entry to copy, must not be null
++ * @throws NullPointerException if the entry is null
++ */
++ public DefaultMapEntry(final Map.Entry<K, V> entry) {
++ super(entry.getKey(), entry.getValue());
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/keyvalue/MultiKey.java
+@@ -0,0 +1,202 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.keyvalue;
++
++import java.io.Serializable;
++import java.util.Arrays;
++
++/**
++ * A <code>MultiKey</code> allows multiple map keys to be merged together.
++ * <p/>
++ * The purpose of this class is to avoid the need to write code to handle
++ * maps of maps. An example might be the need to lookup a filename by
++ * key and locale. The typical solution might be nested maps. This class
++ * can be used instead by creating an instance passing in the key and locale.
++ * <p/>
++ * Example usage:
++ * <pre>
++ * // populate map with data mapping key+locale to localizedText
++ * Map map = new HashMap();
++ * MultiKey multiKey = new MultiKey(key, locale);
++ * map.put(multiKey, localizedText);
++ * <p/>
++ * // later retireve the localized text
++ * MultiKey multiKey = new MultiKey(key, locale);
++ * String localizedText = (String) map.get(multiKey);
++ * </pre>
++ *
++ * @author Howard Lewis Ship
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class MultiKey <K> implements Serializable {
++ // This class could implement List, but that would confuse it's purpose
++
++ /**
++ * Serialisation version
++ */
++ private static final long serialVersionUID = 4465448607415788805L;
++
++ /**
++ * The individual keys
++ */
++ private final K[] keys;
++ /**
++ * The cached hashCode
++ */
++ private final int hashCode;
++
++ /**
++ * Constructor taking two keys.
++ * <p/>
++ * The keys should be immutable
++ * If they are not then they must not be changed after adding to the MultiKey.
++ *
++ * @param keys the keys
++ */
++ public MultiKey(K... keys) {
++ this(keys, true);
++ }
++
++ /**
++ * Constructor taking an array of keys, optionally choosing whether to clone.
++ * <p/>
++ * <b>If the array is not cloned, then it must not be modified.</b>
++ * <p/>
++ * This method is public for performance reasons only, to avoid a clone.
++ * The hashcode is calculated once here in this method.
++ * Therefore, changing the array passed in would not change the hashcode but
++ * would change the equals method, which is a bug.
++ * <p/>
++ * This is the only fully safe usage of this constructor, as the object array
++ * is never made available in a variable:
++ * <pre>
++ * new MultiKey(new Object[] {...}, false);
++ * </pre>
++ * <p/>
++ * The keys should be immutable
++ * If they are not then they must not be changed after adding to the MultiKey.
++ *
++ * @param keys the array of keys, not null
++ * @param makeClone true to clone the array, false to assign it
++ * @throws IllegalArgumentException if the key array is null
++ * @since Commons Collections 3.1
++ */
++ public MultiKey(K[] keys, boolean makeClone) {
++ super();
++ if (keys == null) {
++ throw new IllegalArgumentException("The array of keys must not be null");
++ }
++ if (makeClone) {
++ this.keys = (K[]) keys.clone();
++ } else {
++ this.keys = keys;
++ }
++
++ int total = 0;
++ for (int i = 0; i < keys.length; i++) {
++ if (keys[i] != null) {
++ total ^= keys[i].hashCode();
++ }
++ }
++ hashCode = total;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets a clone of the array of keys.
++ * <p/>
++ * The keys should be immutable
++ * If they are not then they must not be changed.
++ *
++ * @return the individual keys
++ */
++ public K[] getKeys() {
++ return keys.clone();
++ }
++
++ /**
++ * Gets the key at the specified index.
++ * <p/>
++ * The key should be immutable.
++ * If it is not then it must not be changed.
++ *
++ * @param index the index to retrieve
++ * @return the key at the index
++ * @throws IndexOutOfBoundsException if the index is invalid
++ * @since Commons Collections 3.1
++ */
++ public K getKey(int index) {
++ return keys[index];
++ }
++
++ /**
++ * Gets the size of the list of keys.
++ *
++ * @return the size of the list of keys
++ * @since Commons Collections 3.1
++ */
++ public int size() {
++ return keys.length;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Compares this object to another.
++ * <p/>
++ * To be equal, the other object must be a <code>MultiKey</code> with the
++ * same number of keys which are also equal.
++ *
++ * @param other the other object to compare to
++ * @return true if equal
++ */
++ public boolean equals(Object other) {
++ if (other == this) {
++ return true;
++ }
++ if (other instanceof MultiKey) {
++ MultiKey otherMulti = (MultiKey) other;
++ return Arrays.equals(keys, otherMulti.keys);
++ }
++ return false;
++ }
++
++ /**
++ * Gets the combined hash code that is computed from all the keys.
++ * <p/>
++ * This value is computed once and then cached, so elements should not
++ * change their hash codes once created (note that this is the same
++ * constraint that would be used if the individual keys elements were
++ * themselves {@link java.util.Map Map} keys.
++ *
++ * @return the hash code
++ */
++ public int hashCode() {
++ return hashCode;
++ }
++
++ /**
++ * Gets a debugging string version of the key.
++ *
++ * @return a debugging string
++ */
++ public String toString() {
++ return "MultiKey" + Arrays.asList(keys).toString();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/keyvalue/TiedMapEntry.java
+@@ -0,0 +1,138 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.keyvalue;
++
++import org.apache.commons.collections15.KeyValue;
++
++import java.io.Serializable;
++import java.util.Map;
++
++/**
++ * A Map Entry tied to a map underneath.
++ * <p/>
++ * This can be used to enable a map entry to make changes on the underlying
++ * map, however this will probably mess up any iterators.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class TiedMapEntry <K,V> implements Map.Entry<K, V>, KeyValue<K, V>, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -8453869361373831205L;
++
++ /**
++ * The map underlying the entry/iterator
++ */
++ private final Map<K, V> map;
++ /**
++ * The key
++ */
++ private final K key;
++
++ /**
++ * Constructs a new entry with the given Map and key.
++ *
++ * @param map the map
++ * @param key the key
++ */
++ public TiedMapEntry(Map<K, V> map, K key) {
++ super();
++ this.map = map;
++ this.key = key;
++ }
++
++ // Map.Entry interface
++ //-------------------------------------------------------------------------
++ /**
++ * Gets the key of this entry
++ *
++ * @return the key
++ */
++ public K getKey() {
++ return key;
++ }
++
++ /**
++ * Gets the value of this entry direct from the map.
++ *
++ * @return the value
++ */
++ public V getValue() {
++ return map.get(key);
++ }
++
++ /**
++ * Sets the value associated with the key direct onto the map.
++ *
++ * @param value the new value
++ * @return the old value
++ * @throws IllegalArgumentException if the value is set to this map entry
++ */
++ public V setValue(V value) {
++ if ((Object) value == this) {
++ throw new IllegalArgumentException("Cannot set value to this map entry");
++ }
++
++ return map.put(key, value);
++ }
++
++ /**
++ * 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;
++ Object value = getValue();
++ return (key == null ? other.getKey() == null : key.equals(other.getKey())) && (value == null ? other.getValue() == null : value.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() {
++ Object value = getValue();
++ return (getKey() == null ? 0 : getKey().hashCode()) ^ (value == null ? 0 : value.hashCode());
++ }
++
++ /**
++ * Gets a string version of the entry.
++ *
++ * @return entry as a string
++ */
++ public String toString() {
++ return getKey() + "=" + getValue();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/keyvalue/UnmodifiableMapEntry.java
+@@ -0,0 +1,75 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.keyvalue;
++
++import org.apache.commons.collections15.KeyValue;
++import org.apache.commons.collections15.Unmodifiable;
++
++import java.util.Map;
++
++/**
++ * A {@link java.util.Map.Entry} that throws UnsupportedOperationException
++ * when <code>setValue</code> is called.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableMapEntry <K,V> extends AbstractMapEntry<K, V> implements Unmodifiable {
++
++ /**
++ * Constructs a new entry with the specified 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 UnmodifiableMapEntry(final K key, final V value) {
++ super(key, value);
++ }
++
++ /**
++ * Constructs a new entry from the specified KeyValue.
++ *
++ * @param pair the pair to copy, must not be null
++ * @throws NullPointerException if the entry is null
++ */
++ public UnmodifiableMapEntry(final KeyValue<K, V> pair) {
++ super(pair.getKey(), pair.getValue());
++ }
++
++ /**
++ * Constructs a new entry from the specified MapEntry.
++ *
++ * @param entry the entry to copy, must not be null
++ * @throws NullPointerException if the entry is null
++ */
++ public UnmodifiableMapEntry(final Map.Entry<K, V> entry) {
++ super(entry.getKey(), entry.getValue());
++ }
++
++ /**
++ * Throws UnsupportedOperationException.
++ *
++ * @param value the new value
++ * @return the previous value
++ * @throws UnsupportedOperationException always
++ */
++ public V setValue(V value) {
++ throw new UnsupportedOperationException("setValue() is not supported");
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/keyvalue/package.html
+@@ -0,0 +1,29 @@
++<!-- $Id: package.html,v 1.1 2005/10/11 17:05:32 pents90 Exp $ -->
++ <!--
++ Copyright 2003-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<BODY>
++<p>
++This package contains implementations of collection and map related key/value classes.
++These are usually used in maps, however they can be used as data holders in any collection.
++<p>
++The following key/value designs are included:
++<ul>
++<li>Map Entry - various map entry implementations
++<li>KeyValue - a key and value pair, without map entry semantics
++<li>MultiKey - a holder of multiple keys tied together
++</ul>
++</pre>
++</BODY>
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/AbstractLinkedList.java
+@@ -0,0 +1,1018 @@
++// GenericsNote: Converted with possible improvements noted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import org.apache.commons.collections15.OrderedIterator;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.lang.reflect.Array;
++import java.util.*;
++
++/**
++ * An abstract implementation of a linked list which provides numerous points for
++ * subclasses to override.
++ * <p/>
++ * Overridable methods are provided to change the storage node and to change how
++ * nodes are added to and removed. Hopefully, all you need for unusual subclasses
++ * is here.
++ *
++ * @author Rich Dougherty
++ * @author Phil Steitz
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractLinkedList <E> implements List<E> {
++
++ /*
++ * Implementation notes:
++ * - a standard circular doubly-linked list
++ * - a marker node is stored to mark the start and the end of the list
++ * - node creation and removal always occurs through createNode() and
++ * removeNode().
++ * - a modification count is kept, with the same semantics as
++ * {@link java.util.LinkedList}.
++ * - respects {@link AbstractList#modCount}
++ */
++
++ /**
++ * A {@link Node} which indicates the start and end of the list and does not
++ * hold a value. The value of <code>next</code> is the first item in the
++ * list. The value of of <code>previous</code> is the last item in the list.
++ */
++ protected transient Node<E> header;
++ /**
++ * The size of the list
++ */
++ protected transient int size;
++ /**
++ * Modification count for iterators
++ */
++ protected transient int modCount;
++
++ /**
++ * Constructor that does nothing intended for deserialization.
++ * <p/>
++ * If this constructor is used by a serializable subclass then the init()
++ * method must be called.
++ */
++ protected AbstractLinkedList() {
++ super();
++ }
++
++ /**
++ * Constructs a list copying data from the specified collection.
++ *
++ * @param coll the collection to copy
++ */
++ protected AbstractLinkedList(Collection<E> coll) {
++ super();
++ init();
++ addAll(coll);
++ }
++
++ /**
++ * The equivalent of a default constructor, broken out so it can be called
++ * by any constructor and by <code>readObject</code>.
++ * Subclasses which override this method should make sure they call super,
++ * so the list is initialised properly.
++ */
++ protected void init() {
++ header = createHeaderNode();
++ }
++
++ //-----------------------------------------------------------------------
++ public int size() {
++ return size;
++ }
++
++ public boolean isEmpty() {
++ return (size() == 0);
++ }
++
++ public E get(int index) {
++ Node<E> node = getNode(index, false);
++ return node.getValue();
++ }
++
++ //-----------------------------------------------------------------------
++ public Iterator<E> iterator() {
++ return listIterator();
++ }
++
++ public ListIterator<E> listIterator() {
++ return new LinkedListIterator<E>(this, 0);
++ }
++
++ public ListIterator<E> listIterator(int fromIndex) {
++ return new LinkedListIterator<E>(this, fromIndex);
++ }
++
++ //-----------------------------------------------------------------------
++ public int indexOf(Object value) {
++ int i = 0;
++ for (Node<E> node = header.next; node != header; node = node.next) {
++ if (isEqualValue(node.getValue(), (E) value)) {
++ return i;
++ }
++ i++;
++ }
++ return -1;
++ }
++
++ public int lastIndexOf(Object value) {
++ int i = size - 1;
++ for (Node<E> node = header.previous; node != header; node = node.previous) {
++ if (isEqualValue(node.getValue(), (E) value)) {
++ return i;
++ }
++ i--;
++ }
++ return -1;
++ }
++
++ public boolean contains(Object value) {
++ return indexOf(value) != -1;
++ }
++
++ public boolean containsAll(Collection<?> coll) {
++ Iterator it = coll.iterator();
++ while (it.hasNext()) {
++ if (contains(it.next()) == false) {
++ return false;
++ }
++ }
++ return true;
++ }
++
++ //-----------------------------------------------------------------------
++ public Object[] toArray() {
++ return toArray(new Object[size]);
++ }
++
++ public <T> T[] toArray(T[] array) {
++ // Extend the array if needed
++ if (array.length < size) {
++ Class componentType = array.getClass().getComponentType();
++ array = (T[]) Array.newInstance(componentType, size);
++ }
++ // Copy the values into the array
++ int i = 0;
++ for (Node<E> node = header.next; node != header; node = node.next, i++) {
++ // Can do no better than cast through Object here.
++ array[i] = (T) (Object) node.getValue();
++ }
++ // Set the value after the last value to null
++ if (array.length > size) {
++ array[size] = null;
++ }
++ return array;
++ }
++
++ /**
++ * Gets a sublist of the main list.
++ *
++ * @param fromIndexInclusive the index to start from
++ * @param toIndexExclusive the index to end at
++ * @return the new sublist
++ */
++ public List<E> subList(int fromIndexInclusive, int toIndexExclusive) {
++ return new LinkedSubList<E>(this, fromIndexInclusive, toIndexExclusive);
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean add(E value) {
++ addLast(value);
++ return true;
++ }
++
++ public void add(int index, E value) {
++ Node<E> node = getNode(index, true);
++ addNodeBefore(node, value);
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ return addAll(size, coll);
++ }
++
++ public boolean addAll(int index, Collection<? extends E> coll) {
++ Node<E> node = getNode(index, true);
++ for (Iterator itr = coll.iterator(); itr.hasNext();) {
++ Object value = itr.next();
++ addNodeBefore(node, (E) value);
++ }
++ return true;
++ }
++
++ //-----------------------------------------------------------------------
++ public E remove(int index) {
++ Node<E> node = getNode(index, false);
++ E oldValue = node.getValue();
++ removeNode(node);
++ return oldValue;
++ }
++
++ public boolean remove(Object value) {
++ for (Node<E> node = header.next; node != header; node = node.next) {
++ if (isEqualValue(node.getValue(), (E) value)) {
++ removeNode(node);
++ return true;
++ }
++ }
++ return false;
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ boolean modified = false;
++ Iterator it = iterator();
++ while (it.hasNext()) {
++ if (coll.contains(it.next())) {
++ it.remove();
++ modified = true;
++ }
++ }
++ return modified;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean retainAll(Collection<?> coll) {
++ boolean modified = false;
++ Iterator it = iterator();
++ while (it.hasNext()) {
++ if (coll.contains(it.next()) == false) {
++ it.remove();
++ modified = true;
++ }
++ }
++ return modified;
++ }
++
++ public E set(int index, E value) {
++ Node<E> node = getNode(index, false);
++ E oldValue = node.getValue();
++ updateNode(node, value);
++ return oldValue;
++ }
++
++ public void clear() {
++ removeAllNodes();
++ }
++
++ //-----------------------------------------------------------------------
++ public E getFirst() {
++ Node<E> node = header.next;
++ if (node == header) {
++ throw new NoSuchElementException();
++ }
++ return node.getValue();
++ }
++
++ public E getLast() {
++ Node<E> node = header.previous;
++ if (node == header) {
++ throw new NoSuchElementException();
++ }
++ return node.getValue();
++ }
++
++ public boolean addFirst(E o) {
++ addNodeAfter(header, o);
++ return true;
++ }
++
++ public boolean addLast(E o) {
++ addNodeBefore(header, o);
++ return true;
++ }
++
++ public E removeFirst() {
++ Node<E> node = header.next;
++ if (node == header) {
++ throw new NoSuchElementException();
++ }
++ E oldValue = node.getValue();
++ removeNode(node);
++ return oldValue;
++ }
++
++ public E removeLast() {
++ Node<E> node = header.previous;
++ if (node == header) {
++ throw new NoSuchElementException();
++ }
++ E oldValue = node.getValue();
++ removeNode(node);
++ return oldValue;
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean equals(Object obj) {
++ if (obj == this) {
++ return true;
++ }
++ if (obj instanceof List == false) {
++ return false;
++ }
++ List other = (List) obj;
++ if (other.size() != size()) {
++ return false;
++ }
++ ListIterator it1 = listIterator();
++ ListIterator it2 = other.listIterator();
++ while (it1.hasNext() && it2.hasNext()) {
++ Object o1 = it1.next();
++ Object o2 = it2.next();
++ if (!(o1 == null ? o2 == null : o1.equals(o2)))
++ return false;
++ }
++ return !(it1.hasNext() || it2.hasNext());
++ }
++
++ public int hashCode() {
++ int hashCode = 1;
++ Iterator it = iterator();
++ while (it.hasNext()) {
++ Object obj = it.next();
++ hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
++ }
++ return hashCode;
++ }
++
++ public String toString() {
++ if (size() == 0) {
++ return "[]";
++ }
++ StringBuffer buf = new StringBuffer(16 * size());
++ buf.append("[");
++
++ Iterator it = iterator();
++ boolean hasNext = it.hasNext();
++ while (hasNext) {
++ Object value = it.next();
++ buf.append(value == this ? "(this Collection)" : value);
++ hasNext = it.hasNext();
++ if (hasNext) {
++ buf.append(", ");
++ }
++ }
++ buf.append("]");
++ return buf.toString();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Compares two values for equals.
++ * This implementation uses the equals method.
++ * Subclasses can override this to match differently.
++ *
++ * @param value1 the first value to compare, may be null
++ * @param value2 the second value to compare, may be null
++ * @return true if equal
++ */
++ protected boolean isEqualValue(E value1, E value2) {
++ return (value1 == value2 || (value1 == null ? false : value1.equals(value2)));
++ }
++
++ /**
++ * Updates the node with a new value.
++ * This implementation sets the value on the node.
++ * Subclasses can override this to record the change.
++ *
++ * @param node node to update
++ * @param value new value of the node
++ */
++ protected void updateNode(Node<E> node, E value) {
++ node.setValue(value);
++ }
++
++ /**
++ * Creates a new node with previous, next and element all set to null.
++ * This implementation creates a new empty Node.
++ * Subclasses can override this to create a different class.
++ *
++ * @return newly created node
++ */
++ protected Node<E> createHeaderNode() {
++ return new Node<E>();
++ }
++
++ /**
++ * Creates a new node with the specified properties.
++ * This implementation creates a new Node with data.
++ * Subclasses can override this to create a different class.
++ *
++ * @param value value of the new node
++ */
++ protected Node<E> createNode(E value) {
++ return new Node<E>(value);
++ }
++
++ /**
++ * Creates a new node with the specified object as its
++ * <code>value</code> and inserts it before <code>node</code>.
++ * <p/>
++ * This implementation uses {@link #createNode(Object)} and
++ * {@link #addNode(AbstractLinkedList.Node,AbstractLinkedList.Node)}.
++ *
++ * @param node node to insert before
++ * @param value value of the newly added node
++ * @throws NullPointerException if <code>node</code> is null
++ */
++ protected void addNodeBefore(Node<E> node, E value) {
++ Node newNode = createNode(value);
++ addNode(newNode, node);
++ }
++
++ /**
++ * Creates a new node with the specified object as its
++ * <code>value</code> and inserts it after <code>node</code>.
++ * <p/>
++ * This implementation uses {@link #createNode(Object)} and
++ * {@link #addNode(AbstractLinkedList.Node,AbstractLinkedList.Node)}.
++ *
++ * @param node node to insert after
++ * @param value value of the newly added node
++ * @throws NullPointerException if <code>node</code> is null
++ */
++ protected void addNodeAfter(Node<E> node, E value) {
++ Node<E> newNode = createNode(value);
++ addNode(newNode, node.next);
++ }
++
++ /**
++ * Inserts a new node into the list.
++ *
++ * @param nodeToInsert new node to insert
++ * @param insertBeforeNode node to insert before
++ * @throws NullPointerException if either node is null
++ */
++ protected void addNode(Node<E> nodeToInsert, Node<E> insertBeforeNode) {
++ nodeToInsert.next = insertBeforeNode;
++ nodeToInsert.previous = insertBeforeNode.previous;
++ insertBeforeNode.previous.next = nodeToInsert;
++ insertBeforeNode.previous = nodeToInsert;
++ size++;
++ modCount++;
++ }
++
++ /**
++ * Removes the specified node from the list.
++ *
++ * @param node the node to remove
++ * @throws NullPointerException if <code>node</code> is null
++ */
++ protected void removeNode(Node<E> node) {
++ node.previous.next = node.next;
++ node.next.previous = node.previous;
++ size--;
++ modCount++;
++ }
++
++ /**
++ * Removes all nodes by resetting the circular list marker.
++ */
++ protected void removeAllNodes() {
++ header.next = header;
++ header.previous = header;
++ size = 0;
++ modCount++;
++ }
++
++ /**
++ * Gets the node at a particular index.
++ *
++ * @param index the index, starting from 0
++ * @param endMarkerAllowed whether or not the end marker can be returned if
++ * startIndex is set to the list's size
++ * @throws IndexOutOfBoundsException if the index is less than 0; equal to
++ * the size of the list and endMakerAllowed is false; or greater than the
++ * size of the list
++ */
++ protected Node<E> getNode(int index, boolean endMarkerAllowed) throws IndexOutOfBoundsException {
++ // Check the index is within the bounds
++ if (index < 0) {
++ throw new IndexOutOfBoundsException("Couldn't get the node: " + "index (" + index + ") less than zero.");
++ }
++ if (!endMarkerAllowed && index == size) {
++ throw new IndexOutOfBoundsException("Couldn't get the node: " + "index (" + index + ") is the size of the list.");
++ }
++ if (index > size) {
++ throw new IndexOutOfBoundsException("Couldn't get the node: " + "index (" + index + ") greater than the size of the " + "list (" + size + ").");
++ }
++ // Search the list and get the node
++ Node<E> node;
++ if (index < (size / 2)) {
++ // Search forwards
++ node = header.next;
++ for (int currentIndex = 0; currentIndex < index; currentIndex++) {
++ node = node.next;
++ }
++ } else {
++ // Search backwards
++ node = header;
++ for (int currentIndex = size; currentIndex > index; currentIndex--) {
++ node = node.previous;
++ }
++ }
++ return node;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Creates an iterator for the sublist.
++ *
++ * @param subList the sublist to get an iterator for
++ */
++ protected Iterator<E> createSubListIterator(LinkedSubList<E> subList) {
++ return createSubListListIterator(subList, 0);
++ }
++
++ /**
++ * Creates a list iterator for the sublist.
++ *
++ * @param subList the sublist to get an iterator for
++ * @param fromIndex the index to start from, relative to the sublist
++ */
++ protected ListIterator<E> createSubListListIterator(LinkedSubList<E> subList, int fromIndex) {
++ return new LinkedSubListIterator(subList, fromIndex);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Serializes the data held in this object to the stream specified.
++ * <p/>
++ * The first serializable subclass must call this method from
++ * <code>writeObject</code>.
++ */
++ protected void doWriteObject(ObjectOutputStream outputStream) throws IOException {
++ // Write the size so we know how many nodes to read back
++ outputStream.writeInt(size());
++ for (Iterator itr = iterator(); itr.hasNext();) {
++ outputStream.writeObject(itr.next());
++ }
++ }
++
++ /**
++ * Deserializes the data held in this object to the stream specified.
++ * <p/>
++ * The first serializable subclass must call this method from
++ * <code>readObject</code>.
++ */
++ protected void doReadObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
++ init();
++ int size = inputStream.readInt();
++ for (int i = 0; i < size; i++) {
++ add((E) inputStream.readObject());
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * A node within the linked list.
++ * <p/>
++ * From Commons Collections 3.1, all access to the <code>value</code> property
++ * is via the methods on this class.
++ */
++ protected static class Node <T> {
++
++ /**
++ * A pointer to the node before this node
++ */
++ protected Node<T> previous;
++ /**
++ * A pointer to the node after this node
++ */
++ protected Node<T> next;
++ /**
++ * The object contained within this node
++ */
++ protected T value;
++
++ /**
++ * Constructs a new header node.
++ */
++ protected Node() {
++ super();
++ previous = this;
++ next = this;
++ }
++
++ /**
++ * Constructs a new node.
++ *
++ * @param value the value to store
++ */
++ protected Node(T value) {
++ super();
++ this.value = value;
++ }
++
++ /**
++ * Constructs a new node.
++ *
++ * @param previous the previous node in the list
++ * @param next the next node in the list
++ * @param value the value to store
++ */
++ protected Node(Node<T> previous, Node<T> next, T value) {
++ super();
++ this.previous = previous;
++ this.next = next;
++ this.value = value;
++ }
++
++ /**
++ * Gets the value of the node.
++ *
++ * @return the value
++ * @since Commons Collections 3.1
++ */
++ protected T getValue() {
++ return value;
++ }
++
++ /**
++ * Sets the value of the node.
++ *
++ * @param value the value
++ * @since Commons Collections 3.1
++ */
++ protected void setValue(T value) {
++ this.value = value;
++ }
++
++ /**
++ * Gets the previous node.
++ *
++ * @return the previous node
++ * @since Commons Collections 3.1
++ */
++ protected Node<T> getPreviousNode() {
++ return previous;
++ }
++
++ /**
++ * Sets the previous node.
++ *
++ * @param previous the previous node
++ * @since Commons Collections 3.1
++ */
++ protected void setPreviousNode(Node<T> previous) {
++ this.previous = previous;
++ }
++
++ /**
++ * Gets the next node.
++ *
++ * @return the next node
++ * @since Commons Collections 3.1
++ */
++ protected Node<T> getNextNode() {
++ return next;
++ }
++
++ /**
++ * Sets the next node.
++ *
++ * @param next the next node
++ * @since Commons Collections 3.1
++ */
++ protected void setNextNode(Node<T> next) {
++ this.next = next;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * A list iterator over the linked list.
++ */
++ protected static class LinkedListIterator <E> implements ListIterator<E>, OrderedIterator<E> {
++
++ /**
++ * The parent list
++ */
++ protected final AbstractLinkedList<E> parent;
++
++ /**
++ * The node that will be returned by {@link #next()}. If this is equal
++ * to {@link AbstractLinkedList#header} then there are no more values to return.
++ */
++ protected Node<E> next;
++
++ /**
++ * The index of {@link #next}.
++ */
++ protected int nextIndex;
++
++ /**
++ * The last node that was returned by {@link #next()} or {@link
++ * #previous()}. Set to <code>null</code> if {@link #next()} or {@link
++ * #previous()} haven't been called, or if the node has been removed
++ * with {@link #remove()} or a new node added with {@link #add(Object)}.
++ * Should be accessed through {@link #getLastNodeReturned()} to enforce
++ * this behaviour.
++ */
++ protected Node<E> current;
++
++ /**
++ * The modification count that the list is expected to have. If the list
++ * doesn't have this count, then a
++ * {@link java.util.ConcurrentModificationException} may be thrown by
++ * the operations.
++ */
++ protected int expectedModCount;
++
++ /**
++ * Create a ListIterator for a list.
++ *
++ * @param parent the parent list
++ * @param fromIndex the index to start at
++ */
++ protected LinkedListIterator(AbstractLinkedList<E> parent, int fromIndex) throws IndexOutOfBoundsException {
++ super();
++ this.parent = parent;
++ this.expectedModCount = parent.modCount;
++ this.next = parent.getNode(fromIndex, true);
++ this.nextIndex = fromIndex;
++ }
++
++ /**
++ * Checks the modification count of the list is the value that this
++ * object expects.
++ *
++ * @throws ConcurrentModificationException
++ * If the list's modification
++ * count isn't the value that was expected.
++ */
++ protected void checkModCount() {
++ if (parent.modCount != expectedModCount) {
++ throw new ConcurrentModificationException();
++ }
++ }
++
++ /**
++ * Gets the last node returned.
++ *
++ * @throws IllegalStateException If {@link #next()} or
++ * {@link #previous()} haven't been called, or if the node has been removed
++ * with {@link #remove()} or a new node added with {@link #add(Object)}.
++ */
++ protected Node<E> getLastNodeReturned() throws IllegalStateException {
++ if (current == null) {
++ throw new IllegalStateException();
++ }
++ return current;
++ }
++
++ public boolean hasNext() {
++ return next != parent.header;
++ }
++
++ public E next() {
++ checkModCount();
++ if (!hasNext()) {
++ throw new NoSuchElementException("No element at index " + nextIndex + ".");
++ }
++ E value = next.getValue();
++ current = next;
++ next = next.next;
++ nextIndex++;
++ return value;
++ }
++
++ public boolean hasPrevious() {
++ return next.previous != parent.header;
++ }
++
++ public E previous() {
++ checkModCount();
++ if (!hasPrevious()) {
++ throw new NoSuchElementException("Already at start of list.");
++ }
++ next = next.previous;
++ E value = next.getValue();
++ current = next;
++ nextIndex--;
++ return value;
++ }
++
++ public int nextIndex() {
++ return nextIndex;
++ }
++
++ public int previousIndex() {
++ // not normally overridden, as relative to nextIndex()
++ return nextIndex() - 1;
++ }
++
++ public void remove() {
++ checkModCount();
++ parent.removeNode(getLastNodeReturned());
++ current = null;
++ nextIndex--;
++ expectedModCount++;
++ }
++
++ public void set(E obj) {
++ checkModCount();
++ getLastNodeReturned().setValue(obj);
++ }
++
++ public void add(E obj) {
++ checkModCount();
++ parent.addNodeBefore(next, obj);
++ current = null;
++ nextIndex++;
++ expectedModCount++;
++ }
++
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * A list iterator over the linked sub list.
++ */
++ protected static class LinkedSubListIterator <E> extends LinkedListIterator<E> {
++
++ /**
++ * The parent list
++ */
++ protected final LinkedSubList<E> sub;
++
++ protected LinkedSubListIterator(LinkedSubList<E> sub, int startIndex) {
++ super(sub.parent, startIndex + sub.offset);
++ this.sub = sub;
++ }
++
++ public boolean hasNext() {
++ return (nextIndex() < sub.size);
++ }
++
++ public boolean hasPrevious() {
++ return (previousIndex() >= 0);
++ }
++
++ public int nextIndex() {
++ return (super.nextIndex() - sub.offset);
++ }
++
++ public void add(E obj) {
++ super.add(obj);
++ sub.expectedModCount = parent.modCount;
++ sub.size++;
++ }
++
++ public void remove() {
++ super.remove();
++ sub.expectedModCount = parent.modCount;
++ sub.size--;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * The sublist implementation for AbstractLinkedList.
++ */
++ protected static class LinkedSubList <E> extends AbstractList<E> {
++ /**
++ * The main list
++ */
++ private AbstractLinkedList<E> parent;
++ /**
++ * Offset from the main list
++ */
++ private int offset;
++ /**
++ * Sublist size
++ */
++ private int size;
++ /**
++ * Sublist modCount
++ */
++ private int expectedModCount;
++
++ protected LinkedSubList(AbstractLinkedList<E> parent, int fromIndex, int toIndex) {
++ if (fromIndex < 0) {
++ throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
++ }
++ if (toIndex > parent.size()) {
++ throw new IndexOutOfBoundsException("toIndex = " + toIndex);
++ }
++ if (fromIndex > toIndex) {
++ throw new IllegalArgumentException("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
++ }
++ this.parent = parent;
++ this.offset = fromIndex;
++ this.size = toIndex - fromIndex;
++ this.expectedModCount = parent.modCount;
++ }
++
++ public int size() {
++ checkModCount();
++ return size;
++ }
++
++ public E get(int index) {
++ rangeCheck(index, size);
++ checkModCount();
++ return parent.get(index + offset);
++ }
++
++ public void add(int index, E obj) {
++ rangeCheck(index, size + 1);
++ checkModCount();
++ parent.add(index + offset, obj);
++ expectedModCount = parent.modCount;
++ size++;
++ LinkedSubList.this.modCount++;
++ }
++
++ public E remove(int index) {
++ rangeCheck(index, size);
++ checkModCount();
++ E result = parent.remove(index + offset);
++ expectedModCount = parent.modCount;
++ size--;
++ LinkedSubList.this.modCount++;
++ return result;
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ return addAll(size, coll);
++ }
++
++ public boolean addAll(int index, Collection<? extends E> coll) {
++ rangeCheck(index, size + 1);
++ int cSize = coll.size();
++ if (cSize == 0) {
++ return false;
++ }
++
++ checkModCount();
++ parent.addAll(offset + index, coll);
++ expectedModCount = parent.modCount;
++ size += cSize;
++ LinkedSubList.this.modCount++;
++ return true;
++ }
++
++ public E set(int index, E obj) {
++ rangeCheck(index, size);
++ checkModCount();
++ return parent.set(index + offset, obj);
++ }
++
++ public void clear() {
++ checkModCount();
++ Iterator it = iterator();
++ while (it.hasNext()) {
++ it.next();
++ it.remove();
++ }
++ }
++
++ public Iterator<E> iterator() {
++ checkModCount();
++ return parent.createSubListIterator(this);
++ }
++
++ public ListIterator<E> listIterator(final int index) {
++ rangeCheck(index, size + 1);
++ checkModCount();
++ return parent.createSubListListIterator(this, index);
++ }
++
++ public List subList(int fromIndexInclusive, int toIndexExclusive) {
++ return new LinkedSubList(parent, fromIndexInclusive + offset, toIndexExclusive + offset);
++ }
++
++ protected void rangeCheck(int index, int beyond) {
++ if (index < 0 || index >= beyond) {
++ throw new IndexOutOfBoundsException("Index '" + index + "' out of bounds for size '" + size + "'");
++ }
++ }
++
++ protected void checkModCount() {
++ if (parent.modCount != expectedModCount) {
++ throw new ConcurrentModificationException();
++ }
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/AbstractListDecorator.java
+@@ -0,0 +1,105 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import org.apache.commons.collections15.collection.AbstractCollectionDecorator;
++
++import java.util.Collection;
++import java.util.List;
++import java.util.ListIterator;
++
++/**
++ * Decorates another <code>List</code> to provide additional behaviour.
++ * <p/>
++ * Methods are forwarded directly to the decorated list.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractListDecorator <E> extends AbstractCollectionDecorator<E> implements List<E> {
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ *
++ * @since Commons Collections 3.1
++ */
++ protected AbstractListDecorator() {
++ super();
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param list the list to decorate, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ protected AbstractListDecorator(List<E> list) {
++ super(list);
++ }
++
++ /**
++ * Gets the list being decorated.
++ *
++ * @return the decorated list
++ */
++ protected List<E> getList() {
++ return (List<E>) getCollection();
++ }
++
++ //-----------------------------------------------------------------------
++ public void add(int index, E object) {
++ getList().add(index, object);
++ }
++
++ public boolean addAll(int index, Collection<? extends E> coll) {
++ return getList().addAll(index, coll);
++ }
++
++ public E get(int index) {
++ return getList().get(index);
++ }
++
++ public int indexOf(Object object) {
++ return getList().indexOf(object);
++ }
++
++ public int lastIndexOf(Object object) {
++ return getList().lastIndexOf(object);
++ }
++
++ public ListIterator<E> listIterator() {
++ return getList().listIterator();
++ }
++
++ public ListIterator<E> listIterator(int index) {
++ return getList().listIterator(index);
++ }
++
++ public E remove(int index) {
++ return getList().remove(index);
++ }
++
++ public E set(int index, E object) {
++ return getList().set(index, object);
++ }
++
++ public List<E> subList(int fromIndex, int toIndex) {
++ return getList().subList(fromIndex, toIndex);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/AbstractSerializableListDecorator.java
+@@ -0,0 +1,70 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.List;
++
++/**
++ * Serializable subclass of AbstractListDecorator.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @since Commons Collections 3.1
++ */
++public abstract class AbstractSerializableListDecorator <E> extends AbstractListDecorator<E> implements Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 2684959196747496299L;
++
++ /**
++ * Constructor.
++ */
++ protected AbstractSerializableListDecorator(List<E> list) {
++ super(list);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the list out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(collection);
++ }
++
++ /**
++ * Read the list in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ collection = (Collection<E>) in.readObject();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/CursorableLinkedList.java
+@@ -0,0 +1,500 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.lang.ref.WeakReference;
++import java.util.*;
++
++/**
++ * A <code>List</code> implementation with a <code>ListIterator</code> that
++ * allows concurrent modifications to the underlying list.
++ * <p/>
++ * This implementation supports all of the optional {@link List} operations.
++ * It extends <code>AbstractLinkedList</code> and thus provides the
++ * stack/queue/dequeue operations available in {@link java.util.LinkedList}.
++ * <p/>
++ * The main feature of this class is the ability to modify the list and the
++ * iterator at the same time. Both the {@link #listIterator()} and {@link #cursor()}
++ * methods provides access to a <code>Cursor</code> instance which extends
++ * <code>ListIterator</code>. The cursor allows changes to the list concurrent
++ * with changes to the iterator. Note that the {@link #iterator()} method and
++ * sublists do <b>not</b> provide this cursor behaviour.
++ * <p/>
++ * The <code>Cursor</code> class is provided partly for backwards compatibility
++ * and partly because it allows the cursor to be directly closed. Closing the
++ * cursor is optional because references are held via a <code>WeakReference</code>.
++ * For most purposes, simply modify the iterator and list at will, and then let
++ * the garbage collector to the rest.
++ * <p/>
++ * <b>Note that this implementation is not synchronized.</b>
++ *
++ * @author Rodney Waldhoff
++ * @author Janek Bogucki
++ * @author Simon Kitching
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @see java.util.LinkedList
++ * @since Commons Collections 1.0
++ */
++public class CursorableLinkedList <E> extends AbstractLinkedList<E> implements Serializable {
++
++ /**
++ * Ensure serialization compatibility
++ */
++ private static final long serialVersionUID = 8836393098519411393L;
++
++ /**
++ * A list of the cursor currently open on this list
++ */
++ protected transient List<WeakReference<Cursor<E>>> cursors = new ArrayList<WeakReference<Cursor<E>>>();
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that creates.
++ */
++ public CursorableLinkedList() {
++ super();
++ init(); // must call init() as use super();
++ }
++
++ /**
++ * Constructor that copies the specified collection
++ *
++ * @param coll the collection to copy
++ */
++ public CursorableLinkedList(Collection<E> coll) {
++ super(coll);
++ }
++
++ /**
++ * The equivalent of a default constructor called
++ * by any constructor and by <code>readObject</code>.
++ */
++ protected void init() {
++ super.init();
++ cursors = new ArrayList<WeakReference<Cursor<E>>>();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns an iterator that does <b>not</b> support concurrent modification.
++ * <p/>
++ * If the underlying list is modified while iterating using this iterator
++ * a ConcurrentModificationException will occur.
++ * The cursor behaviour is available via {@link #listIterator()}.
++ *
++ * @return a new iterator that does <b>not</b> support concurrent modification
++ */
++ public Iterator<E> iterator() {
++ return super.listIterator(0);
++ }
++
++ /**
++ * Returns a cursor iterator that allows changes to the underlying list in parallel.
++ * <p/>
++ * The cursor enables iteration and list changes to occur in any order without
++ * invalidating the iterator (from one thread). When elements are added to the
++ * list, an event is fired to all active cursors enabling them to adjust to the
++ * change in the list.
++ * <p/>
++ * When the "current" (i.e., last returned by {@link ListIterator#next}
++ * or {@link ListIterator#previous}) element of the list is removed,
++ * the cursor automatically adjusts to the change (invalidating the
++ * last returned value such that it cannot be removed).
++ *
++ * @return a new cursor iterator
++ */
++ public ListIterator<E> listIterator() {
++ return cursor(0);
++ }
++
++ /**
++ * Returns a cursor iterator that allows changes to the underlying list in parallel.
++ * <p/>
++ * The cursor enables iteration and list changes to occur in any order without
++ * invalidating the iterator (from one thread). When elements are added to the
++ * list, an event is fired to all active cursors enabling them to adjust to the
++ * change in the list.
++ * <p/>
++ * When the "current" (i.e., last returned by {@link ListIterator#next}
++ * or {@link ListIterator#previous}) element of the list is removed,
++ * the cursor automatically adjusts to the change (invalidating the
++ * last returned value such that it cannot be removed).
++ *
++ * @param fromIndex the index to start from
++ * @return a new cursor iterator
++ */
++ public ListIterator<E> listIterator(int fromIndex) {
++ return cursor(fromIndex);
++ }
++
++ /**
++ * Returns a {@link Cursor} for iterating through the elements of this list.
++ * <p/>
++ * A <code>Cursor</code> is a <code>ListIterator</code> with an additional
++ * <code>close()</code> method. Calling this method immediately discards the
++ * references to the cursor. If it is not called, then the garbage collector
++ * will still remove the reference as it is held via a <code>WeakReference</code>.
++ * <p/>
++ * The cursor enables iteration and list changes to occur in any order without
++ * invalidating the iterator (from one thread). When elements are added to the
++ * list, an event is fired to all active cursors enabling them to adjust to the
++ * change in the list.
++ * <p/>
++ * When the "current" (i.e., last returned by {@link ListIterator#next}
++ * or {@link ListIterator#previous}) element of the list is removed,
++ * the cursor automatically adjusts to the change (invalidating the
++ * last returned value such that it cannot be removed).
++ * <p/>
++ * The {@link #listIterator()} method returns the same as this method, and can
++ * be cast to a <code>Cursor</code> if the <code>close</code> method is required.
++ *
++ * @return a new cursor iterator
++ */
++ public CursorableLinkedList.Cursor<E> cursor() {
++ return cursor(0);
++ }
++
++ /**
++ * Returns a {@link Cursor} for iterating through the elements of this list
++ * starting from a specified index.
++ * <p/>
++ * A <code>Cursor</code> is a <code>ListIterator</code> with an additional
++ * <code>close()</code> method. Calling this method immediately discards the
++ * references to the cursor. If it is not called, then the garbage collector
++ * will still remove the reference as it is held via a <code>WeakReference</code>.
++ * <p/>
++ * The cursor enables iteration and list changes to occur in any order without
++ * invalidating the iterator (from one thread). When elements are added to the
++ * list, an event is fired to all active cursors enabling them to adjust to the
++ * change in the list.
++ * <p/>
++ * When the "current" (i.e., last returned by {@link ListIterator#next}
++ * or {@link ListIterator#previous}) element of the list is removed,
++ * the cursor automatically adjusts to the change (invalidating the
++ * last returned value such that it cannot be removed).
++ * <p/>
++ * The {@link #listIterator(int)} method returns the same as this method, and can
++ * be cast to a <code>Cursor</code> if the <code>close</code> method is required.
++ *
++ * @param fromIndex the index to start from
++ * @return a new cursor iterator
++ * @throws IndexOutOfBoundsException if the index is out of range
++ * (index < 0 || index > size()).
++ */
++ public CursorableLinkedList.Cursor<E> cursor(int fromIndex) {
++ Cursor<E> cursor = new Cursor<E>(this, fromIndex);
++ registerCursor(cursor);
++ return cursor;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Updates the node with a new value.
++ * This implementation sets the value on the node.
++ * Subclasses can override this to record the change.
++ *
++ * @param node node to update
++ * @param value new value of the node
++ */
++ protected void updateNode(Node<E> node, E value) {
++ super.updateNode(node, value);
++ broadcastNodeChanged(node);
++ }
++
++ /**
++ * Inserts a new node into the list.
++ *
++ * @param nodeToInsert new node to insert
++ * @param insertBeforeNode node to insert before
++ * @throws NullPointerException if either node is null
++ */
++ protected void addNode(Node<E> nodeToInsert, Node<E> insertBeforeNode) {
++ super.addNode(nodeToInsert, insertBeforeNode);
++ broadcastNodeInserted(nodeToInsert);
++ }
++
++ /**
++ * Removes the specified node from the list.
++ *
++ * @param node the node to remove
++ * @throws NullPointerException if <code>node</code> is null
++ */
++ protected void removeNode(Node<E> node) {
++ super.removeNode(node);
++ broadcastNodeRemoved(node);
++ }
++
++ /**
++ * Removes all nodes by iteration.
++ */
++ protected void removeAllNodes() {
++ if (size() > 0) {
++ // superclass implementation would break all the iterators
++ Iterator it = iterator();
++ while (it.hasNext()) {
++ it.next();
++ it.remove();
++ }
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Registers a cursor to be notified of changes to this list.
++ *
++ * @param cursor the cursor to register
++ */
++ protected void registerCursor(Cursor<E> cursor) {
++ // We take this opportunity to clean the cursors list
++ // of WeakReference objects to garbage-collected cursors.
++ for (Iterator<WeakReference<Cursor<E>>> it = cursors.iterator(); it.hasNext();) {
++ WeakReference<Cursor<E>> ref = it.next();
++ if (ref.get() == null) {
++ it.remove();
++ }
++ }
++ cursors.add(new WeakReference<Cursor<E>>(cursor));
++ }
++
++ /**
++ * Deregisters a cursor from the list to be notified of changes.
++ *
++ * @param cursor the cursor to deregister
++ */
++ protected void unregisterCursor(Cursor<E> cursor) {
++ for (Iterator it = cursors.iterator(); it.hasNext();) {
++ WeakReference ref = (WeakReference) it.next();
++ Cursor cur = (Cursor) ref.get();
++ if (cur == null) {
++ // some other unrelated cursor object has been
++ // garbage-collected; let's take the opportunity to
++ // clean up the cursors list anyway..
++ it.remove();
++
++ } else if (cur == cursor) {
++ ref.clear();
++ it.remove();
++ break;
++ }
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Informs all of my registered cursors that the specified
++ * element was changed.
++ *
++ * @param node the node that was changed
++ */
++ protected void broadcastNodeChanged(Node<E> node) {
++ Iterator it = cursors.iterator();
++ while (it.hasNext()) {
++ WeakReference ref = (WeakReference) it.next();
++ Cursor cursor = (Cursor) ref.get();
++ if (cursor == null) {
++ it.remove(); // clean up list
++ } else {
++ cursor.nodeChanged(node);
++ }
++ }
++ }
++
++ /**
++ * Informs all of my registered cursors that the specified
++ * element was just removed from my list.
++ *
++ * @param node the node that was changed
++ */
++ protected void broadcastNodeRemoved(Node<E> node) {
++ Iterator it = cursors.iterator();
++ while (it.hasNext()) {
++ WeakReference ref = (WeakReference) it.next();
++ Cursor cursor = (Cursor) ref.get();
++ if (cursor == null) {
++ it.remove(); // clean up list
++ } else {
++ cursor.nodeRemoved(node);
++ }
++ }
++ }
++
++ /**
++ * Informs all of my registered cursors that the specified
++ * element was just added to my list.
++ *
++ * @param node the node that was changed
++ */
++ protected void broadcastNodeInserted(Node<E> node) {
++ Iterator it = cursors.iterator();
++ while (it.hasNext()) {
++ WeakReference ref = (WeakReference) it.next();
++ Cursor cursor = (Cursor) ref.get();
++ if (cursor == null) {
++ it.remove(); // clean up list
++ } else {
++ cursor.nodeInserted(node);
++ }
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Serializes the data held in this object to the stream specified.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ doWriteObject(out);
++ }
++
++ /**
++ * Deserializes the data held in this object to the stream specified.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ doReadObject(in);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * An extended <code>ListIterator</code> that allows concurrent changes to
++ * the underlying list.
++ */
++ public static class Cursor <E> extends AbstractLinkedList.LinkedListIterator<E> {
++ /**
++ * Is the cursor valid (not closed)
++ */
++ boolean valid = true;
++ /**
++ * Is the next index valid
++ */
++ boolean nextIndexValid = true;
++
++ /**
++ * Constructs a new cursor.
++ *
++ * @param index the index to start from
++ */
++ protected Cursor(CursorableLinkedList<E> parent, int index) {
++ super(parent, index);
++ valid = true;
++ }
++
++ /**
++ * Adds an object to the list.
++ * The object added here will be the new 'previous' in the iterator.
++ *
++ * @param obj the object to add
++ */
++ public void add(E obj) {
++ super.add(obj);
++ // add on iterator does not return the added element
++ next = next.next;
++ }
++
++ /**
++ * Gets the index of the next element to be returned.
++ *
++ * @return the next index
++ */
++ public int nextIndex() {
++ if (nextIndexValid == false) {
++ if (next == parent.header) {
++ nextIndex = parent.size();
++ } else {
++ int pos = 0;
++ Node temp = parent.header.next;
++ while (temp != next) {
++ pos++;
++ temp = temp.next;
++ }
++ nextIndex = pos;
++ }
++ nextIndexValid = true;
++ }
++ return nextIndex;
++ }
++
++ /**
++ * Handle event from the list when a node has changed.
++ *
++ * @param node the node that changed
++ */
++ protected void nodeChanged(Node<E> node) {
++ // do nothing
++ }
++
++ /**
++ * Handle event from the list when a node has been removed.
++ *
++ * @param node the node that was removed
++ */
++ protected void nodeRemoved(Node<E> node) {
++ if (node == next) {
++ next = node.next;
++ } else if (node == current) {
++ current = null;
++ nextIndex--;
++ } else {
++ nextIndexValid = false;
++ }
++ }
++
++ /**
++ * Handle event from the list when a node has been added.
++ *
++ * @param node the node that was added
++ */
++ protected void nodeInserted(Node<E> node) {
++ if (node.previous == current) {
++ next = node;
++ } else if (next.previous == node) {
++ next = node;
++ } else {
++ nextIndexValid = false;
++ }
++ }
++
++ /**
++ * Override superclass modCount check, and replace it with our valid flag.
++ */
++ protected void checkModCount() {
++ if (!valid) {
++ throw new ConcurrentModificationException("Cursor closed");
++ }
++ }
++
++ /**
++ * Mark this cursor as no longer being needed. Any resources
++ * associated with this cursor are immediately released.
++ * In previous versions of this class, it was mandatory to close
++ * all cursor objects to avoid memory leaks. It is <i>no longer</i>
++ * necessary to call this close method; an instance of this class
++ * can now be treated exactly like a normal iterator.
++ */
++ public void close() {
++ if (valid) {
++ ((CursorableLinkedList) parent).unregisterCursor(this);
++ valid = false;
++ }
++ }
++ }
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/FastArrayList.java
+@@ -0,0 +1,1286 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import java.util.*;
++
++/**
++ * <p>A customized implementation of <code>java.util.ArrayList</code> designed
++ * to operate in a multithreaded environment where the large majority of
++ * method calls are read-only, instead of structural changes. When operating
++ * in "fast" mode, read calls are non-synchronized and write calls perform the
++ * following steps:</p>
++ * <ul>
++ * <li>Clone the existing collection
++ * <li>Perform the modification on the clone
++ * <li>Replace the existing collection with the (modified) clone
++ * </ul>
++ * <p>When first created, objects of this class default to "slow" mode, where
++ * all accesses of any type are synchronized but no cloning takes place. This
++ * is appropriate for initially populating the collection, followed by a switch
++ * to "fast" mode (by calling <code>setFast(true)</code>) after initialization
++ * is complete.</p>
++ * <p/>
++ * <p><strong>NOTE</strong>: If you are creating and accessing an
++ * <code>ArrayList</code> only within a single thread, you should use
++ * <code>java.util.ArrayList</code> directly (with no synchronization), for
++ * maximum performance.</p>
++ * <p/>
++ * <p><strong>NOTE</strong>: <i>This class is not cross-platform.
++ * Using it may cause unexpected failures on some architectures.</i>
++ * It suffers from the same problems as the double-checked locking idiom.
++ * In particular, the instruction that clones the internal collection and the
++ * instruction that sets the internal reference to the clone can be executed
++ * or perceived out-of-order. This means that any read operation might fail
++ * unexpectedly, as it may be reading the state of the internal collection
++ * before the internal collection is fully formed.
++ * For more information on the double-checked locking idiom, see the
++ * <a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">
++ * Double-Checked Locking Idiom Is Broken Declaration</a>.</p>
++ *
++ * @author Matt Hall, John Watkinson, Craig R. McClanahan
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 1.0
++ */
++public class FastArrayList <E> extends ArrayList<E> {
++
++
++ // ----------------------------------------------------------- Constructors
++
++
++ /**
++ * Construct a an empty list.
++ */
++ public FastArrayList() {
++
++ super();
++ this.list = new ArrayList<E>();
++
++ }
++
++
++ /**
++ * Construct an empty list with the specified capacity.
++ *
++ * @param capacity The initial capacity of the empty list
++ */
++ public FastArrayList(int capacity) {
++
++ super();
++ this.list = new ArrayList<E>(capacity);
++
++ }
++
++
++ /**
++ * Construct a list containing the elements of the specified collection,
++ * in the order they are returned by the collection's iterator.
++ *
++ * @param collection The collection whose elements initialize the contents
++ * of this list
++ */
++ public FastArrayList(Collection<E> collection) {
++
++ super();
++ this.list = new ArrayList<E>(collection);
++
++ }
++
++
++ // ----------------------------------------------------- Instance Variables
++
++
++ /**
++ * The underlying list we are managing.
++ */
++ protected ArrayList<E> list = null;
++
++
++ // ------------------------------------------------------------- Properties
++
++
++ /**
++ * Are we operating in "fast" mode?
++ */
++ protected boolean fast = false;
++
++
++ /**
++ * Returns true if this list is operating in fast mode.
++ *
++ * @return true if this list is operating in fast mode
++ */
++ public boolean getFast() {
++ return (this.fast);
++ }
++
++ /**
++ * Sets whether this list will operate in fast mode.
++ *
++ * @param fast true if the list should operate in fast mode
++ */
++ public void setFast(boolean fast) {
++ this.fast = fast;
++ }
++
++
++ // --------------------------------------------------------- Public Methods
++
++
++ /**
++ * Appends the specified element to the end of this list.
++ *
++ * @param element The element to be appended
++ */
++ public boolean add(E element) {
++
++ if (fast) {
++ synchronized (this) {
++ ArrayList<E> temp = (ArrayList<E>) list.clone();
++ boolean result = temp.add(element);
++ list = temp;
++ return (result);
++ }
++ } else {
++ synchronized (list) {
++ return (list.add(element));
++ }
++ }
++
++ }
++
++
++ /**
++ * Insert the specified element at the specified position in this list,
++ * and shift all remaining elements up one position.
++ *
++ * @param index Index at which to insert this element
++ * @param element The element to be inserted
++ * @throws IndexOutOfBoundsException if the index is out of range
++ */
++ public void add(int index, E element) {
++
++ if (fast) {
++ synchronized (this) {
++ ArrayList<E> temp = (ArrayList<E>) list.clone();
++ temp.add(index, element);
++ list = temp;
++ }
++ } else {
++ synchronized (list) {
++ list.add(index, element);
++ }
++ }
++
++ }
++
++
++ /**
++ * Append all of the elements in the specified Collection to the end
++ * of this list, in the order that they are returned by the specified
++ * Collection's Iterator.
++ *
++ * @param collection The collection to be appended
++ */
++ public boolean addAll(Collection<? extends E> collection) {
++
++ if (fast) {
++ synchronized (this) {
++ ArrayList<E> temp = (ArrayList<E>) list.clone();
++ boolean result = temp.addAll(collection);
++ list = temp;
++ return (result);
++ }
++ } else {
++ synchronized (list) {
++ return (list.addAll(collection));
++ }
++ }
++
++ }
++
++
++ /**
++ * Insert all of the elements in the specified Collection at the specified
++ * position in this list, and shift any previous elements upwards as
++ * needed.
++ *
++ * @param index Index at which insertion takes place
++ * @param collection The collection to be added
++ * @throws IndexOutOfBoundsException if the index is out of range
++ */
++ public boolean addAll(int index, Collection<? extends E> collection) {
++
++ if (fast) {
++ synchronized (this) {
++ ArrayList<E> temp = (ArrayList<E>) list.clone();
++ boolean result = temp.addAll(index, collection);
++ list = temp;
++ return (result);
++ }
++ } else {
++ synchronized (list) {
++ return (list.addAll(index, collection));
++ }
++ }
++
++ }
++
++
++ /**
++ * Remove all of the elements from this list. The list will be empty
++ * after this call returns.
++ *
++ * @throws UnsupportedOperationException if <code>clear()</code>
++ * is not supported by this list
++ */
++ public void clear() {
++
++ if (fast) {
++ synchronized (this) {
++ ArrayList<E> temp = (ArrayList<E>) list.clone();
++ temp.clear();
++ list = temp;
++ }
++ } else {
++ synchronized (list) {
++ list.clear();
++ }
++ }
++
++ }
++
++
++ /**
++ * Return a shallow copy of this <code>FastArrayList</code> instance.
++ * The elements themselves are not copied.
++ */
++ public Object clone() {
++
++ FastArrayList<E> results = null;
++ if (fast) {
++ results = new FastArrayList<E>(list);
++ } else {
++ synchronized (list) {
++ results = new FastArrayList<E>(list);
++ }
++ }
++ results.setFast(getFast());
++ return (results);
++
++ }
++
++
++ /**
++ * Return <code>true</code> if this list contains the specified element.
++ *
++ * @param element The element to test for
++ */
++ public boolean contains(Object element) {
++
++ if (fast) {
++ return (list.contains(element));
++ } else {
++ synchronized (list) {
++ return (list.contains(element));
++ }
++ }
++
++ }
++
++
++ /**
++ * Return <code>true</code> if this list contains all of the elements
++ * in the specified Collection.
++ *
++ * @param collection Collection whose elements are to be checked
++ */
++ public boolean containsAll(Collection<?> collection) {
++
++ if (fast) {
++ return (list.containsAll(collection));
++ } else {
++ synchronized (list) {
++ return (list.containsAll(collection));
++ }
++ }
++
++ }
++
++
++ /**
++ * Increase the capacity of this <code>ArrayList</code> instance, if
++ * necessary, to ensure that it can hold at least the number of elements
++ * specified by the minimum capacity argument.
++ *
++ * @param capacity The new minimum capacity
++ */
++ public void ensureCapacity(int capacity) {
++
++ if (fast) {
++ synchronized (this) {
++ ArrayList<E> temp = (ArrayList<E>) list.clone();
++ temp.ensureCapacity(capacity);
++ list = temp;
++ }
++ } else {
++ synchronized (list) {
++ list.ensureCapacity(capacity);
++ }
++ }
++
++ }
++
++
++ /**
++ * Compare the specified object with this list for equality. This
++ * implementation uses exactly the code that is used to define the
++ * list equals function in the documentation for the
++ * <code>List.equals</code> method.
++ *
++ * @param o Object to be compared to this list
++ */
++ public boolean equals(Object o) {
++
++ // Simple tests that require no synchronization
++ if (o == this)
++ return (true);
++ else if (!(o instanceof List))
++ return (false);
++ List lo = (List) o;
++
++ // Compare the sets of elements for equality
++ if (fast) {
++ ListIterator li1 = list.listIterator();
++ ListIterator li2 = lo.listIterator();
++ while (li1.hasNext() && li2.hasNext()) {
++ Object o1 = li1.next();
++ Object o2 = li2.next();
++ if (!(o1 == null ? o2 == null : o1.equals(o2)))
++ return (false);
++ }
++ return (!(li1.hasNext() || li2.hasNext()));
++ } else {
++ synchronized (list) {
++ ListIterator li1 = list.listIterator();
++ ListIterator li2 = lo.listIterator();
++ while (li1.hasNext() && li2.hasNext()) {
++ Object o1 = li1.next();
++ Object o2 = li2.next();
++ if (!(o1 == null ? o2 == null : o1.equals(o2)))
++ return (false);
++ }
++ return (!(li1.hasNext() || li2.hasNext()));
++ }
++ }
++
++ }
++
++
++ /**
++ * Return the element at the specified position in the list.
++ *
++ * @param index The index of the element to return
++ * @throws IndexOutOfBoundsException if the index is out of range
++ */
++ public E get(int index) {
++
++ if (fast) {
++ return (list.get(index));
++ } else {
++ synchronized (list) {
++ return (list.get(index));
++ }
++ }
++
++ }
++
++
++ /**
++ * Return the hash code value for this list. This implementation uses
++ * exactly the code that is used to define the list hash function in the
++ * documentation for the <code>List.hashCode</code> method.
++ */
++ public int hashCode() {
++
++ if (fast) {
++ int hashCode = 1;
++ java.util.Iterator i = list.iterator();
++ while (i.hasNext()) {
++ Object o = i.next();
++ hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
++ }
++ return (hashCode);
++ } else {
++ synchronized (list) {
++ int hashCode = 1;
++ java.util.Iterator i = list.iterator();
++ while (i.hasNext()) {
++ Object o = i.next();
++ hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
++ }
++ return (hashCode);
++ }
++ }
++
++ }
++
++
++ /**
++ * Search for the first occurrence of the given argument, testing
++ * for equality using the <code>equals()</code> method, and return
++ * the corresponding index, or -1 if the object is not found.
++ *
++ * @param element The element to search for
++ */
++ public int indexOf(Object element) {
++
++ if (fast) {
++ return (list.indexOf(element));
++ } else {
++ synchronized (list) {
++ return (list.indexOf(element));
++ }
++ }
++
++ }
++
++
++ /**
++ * Test if this list has no elements.
++ */
++ public boolean isEmpty() {
++
++ if (fast) {
++ return (list.isEmpty());
++ } else {
++ synchronized (list) {
++ return (list.isEmpty());
++ }
++ }
++
++ }
++
++
++ /**
++ * Return an iterator over the elements in this list in proper sequence.
++ * <br><br>
++ * <strong>IMPLEMENTATION NOTE</strong> - If the list is operating in fast
++ * mode, an Iterator is returned, and a structural modification to the
++ * list is made, then the Iterator will continue over the previous contents
++ * of the list (at the time that the Iterator was created), rather than
++ * failing due to concurrent modifications.
++ */
++ public Iterator<E> iterator() {
++ if (fast) {
++ return new ListIter(0);
++ } else {
++ return list.iterator();
++ }
++ }
++
++
++ /**
++ * Search for the last occurrence of the given argument, testing
++ * for equality using the <code>equals()</code> method, and return
++ * the corresponding index, or -1 if the object is not found.
++ *
++ * @param element The element to search for
++ */
++ public int lastIndexOf(Object element) {
++
++ if (fast) {
++ return (list.lastIndexOf(element));
++ } else {
++ synchronized (list) {
++ return (list.lastIndexOf(element));
++ }
++ }
++
++ }
++
++
++ /**
++ * Return an iterator of the elements of this list, in proper sequence.
++ * See the implementation note on <code>iterator()</code>.
++ */
++ public ListIterator<E> listIterator() {
++ if (fast) {
++ return new ListIter(0);
++ } else {
++ return list.listIterator();
++ }
++ }
++
++
++ /**
++ * Return an iterator of the elements of this list, in proper sequence,
++ * starting at the specified position.
++ * See the implementation note on <code>iterator()</code>.
++ *
++ * @param index The starting position of the iterator to return
++ * @throws IndexOutOfBoundsException if the index is out of range
++ */
++ public ListIterator<E> listIterator(int index) {
++ if (fast) {
++ return new ListIter(index);
++ } else {
++ return list.listIterator(index);
++ }
++ }
++
++
++ /**
++ * Remove the element at the specified position in the list, and shift
++ * any subsequent elements down one position.
++ *
++ * @param index Index of the element to be removed
++ * @throws IndexOutOfBoundsException if the index is out of range
++ */
++ public E remove(int index) {
++
++ if (fast) {
++ synchronized (this) {
++ ArrayList<E> temp = (ArrayList<E>) list.clone();
++ E result = temp.remove(index);
++ list = temp;
++ return (result);
++ }
++ } else {
++ synchronized (list) {
++ return (list.remove(index));
++ }
++ }
++
++ }
++
++
++ /**
++ * Remove the first occurrence of the specified element from the list,
++ * and shift any subsequent elements down one position.
++ *
++ * @param element Element to be removed
++ */
++ public boolean remove(Object element) {
++
++ if (fast) {
++ synchronized (this) {
++ ArrayList temp = (ArrayList) list.clone();
++ boolean result = temp.remove(element);
++ list = temp;
++ return (result);
++ }
++ } else {
++ synchronized (list) {
++ return (list.remove(element));
++ }
++ }
++
++ }
++
++
++ /**
++ * Remove from this collection all of its elements that are contained
++ * in the specified collection.
++ *
++ * @param collection Collection containing elements to be removed
++ * @throws UnsupportedOperationException if this optional operation
++ * is not supported by this list
++ */
++ public boolean removeAll(Collection<?> collection) {
++
++ if (fast) {
++ synchronized (this) {
++ ArrayList temp = (ArrayList) list.clone();
++ boolean result = temp.removeAll(collection);
++ list = temp;
++ return (result);
++ }
++ } else {
++ synchronized (list) {
++ return (list.removeAll(collection));
++ }
++ }
++
++ }
++
++
++ /**
++ * Remove from this collection all of its elements except those that are
++ * contained in the specified collection.
++ *
++ * @param collection Collection containing elements to be retained
++ * @throws UnsupportedOperationException if this optional operation
++ * is not supported by this list
++ */
++ public boolean retainAll(Collection<?> collection) {
++
++ if (fast) {
++ synchronized (this) {
++ ArrayList temp = (ArrayList) list.clone();
++ boolean result = temp.retainAll(collection);
++ list = temp;
++ return (result);
++ }
++ } else {
++ synchronized (list) {
++ return (list.retainAll(collection));
++ }
++ }
++
++ }
++
++
++ /**
++ * Replace the element at the specified position in this list with
++ * the specified element. Returns the previous object at that position.
++ * <br><br>
++ * <strong>IMPLEMENTATION NOTE</strong> - This operation is specifically
++ * documented to not be a structural change, so it is safe to be performed
++ * without cloning.
++ *
++ * @param index Index of the element to replace
++ * @param element The new element to be stored
++ * @throws IndexOutOfBoundsException if the index is out of range
++ */
++ public E set(int index, E element) {
++
++ if (fast) {
++ return (list.set(index, element));
++ } else {
++ synchronized (list) {
++ return (list.set(index, element));
++ }
++ }
++
++ }
++
++
++ /**
++ * Return the number of elements in this list.
++ */
++ public int size() {
++
++ if (fast) {
++ return (list.size());
++ } else {
++ synchronized (list) {
++ return (list.size());
++ }
++ }
++
++ }
++
++
++ /**
++ * Return a view of the portion of this list between fromIndex
++ * (inclusive) and toIndex (exclusive). The returned list is backed
++ * by this list, so non-structural changes in the returned list are
++ * reflected in this list. The returned list supports
++ * all of the optional list operations supported by this list.
++ *
++ * @param fromIndex The starting index of the sublist view
++ * @param toIndex The index after the end of the sublist view
++ * @throws IndexOutOfBoundsException if an index is out of range
++ */
++ public List<E> subList(int fromIndex, int toIndex) {
++ if (fast) {
++ return new SubList(fromIndex, toIndex);
++ } else {
++ return list.subList(fromIndex, toIndex);
++ }
++ }
++
++
++ /**
++ * Return an array containing all of the elements in this list in the
++ * correct order.
++ */
++ public Object[] toArray() {
++
++ if (fast) {
++ return (list.toArray());
++ } else {
++ synchronized (list) {
++ return (list.toArray());
++ }
++ }
++
++ }
++
++
++ /**
++ * Return an array containing all of the elements in this list in the
++ * correct order. The runtime type of the returned array is that of
++ * the specified array. If the list fits in the specified array, it is
++ * returned therein. Otherwise, a new array is allocated with the
++ * runtime type of the specified array, and the size of this list.
++ *
++ * @param array Array defining the element type of the returned list
++ * @throws ArrayStoreException if the runtime type of <code>array</code>
++ * is not a supertype of the runtime type of every element in this list
++ */
++ public <T> T[] toArray(T[] array) {
++
++ if (fast) {
++ return (list.toArray(array));
++ } else {
++ synchronized (list) {
++ return (list.toArray(array));
++ }
++ }
++
++ }
++
++
++ /**
++ * Return a String representation of this object.
++ */
++ public String toString() {
++
++ StringBuffer sb = new StringBuffer("FastArrayList[");
++ sb.append(list.toString());
++ sb.append("]");
++ return (sb.toString());
++
++ }
++
++
++ /**
++ * Trim the capacity of this <code>ArrayList</code> instance to be the
++ * list's current size. An application can use this operation to minimize
++ * the storage of an <code>ArrayList</code> instance.
++ */
++ public void trimToSize() {
++
++ if (fast) {
++ synchronized (this) {
++ ArrayList temp = (ArrayList) list.clone();
++ temp.trimToSize();
++ list = temp;
++ }
++ } else {
++ synchronized (list) {
++ list.trimToSize();
++ }
++ }
++
++ }
++
++
++ private class SubList implements List<E> {
++
++ private int first;
++ private int last;
++ private List<E> expected;
++
++
++ public SubList(int first, int last) {
++ this.first = first;
++ this.last = last;
++ this.expected = list;
++ }
++
++ private List<E> get(List<E> l) {
++ if (list != expected) {
++ throw new ConcurrentModificationException();
++ }
++ return l.subList(first, last);
++ }
++
++ public void clear() {
++ if (fast) {
++ synchronized (FastArrayList.this) {
++ ArrayList<E> temp = (ArrayList<E>) list.clone();
++ get(temp).clear();
++ last = first;
++ list = temp;
++ expected = temp;
++ }
++ } else {
++ synchronized (list) {
++ get(expected).clear();
++ }
++ }
++ }
++
++ public boolean remove(Object o) {
++ if (fast) {
++ synchronized (FastArrayList.this) {
++ ArrayList temp = (ArrayList) list.clone();
++ boolean r = get(temp).remove(o);
++ if (r) last--;
++ list = temp;
++ expected = temp;
++ return r;
++ }
++ } else {
++ synchronized (list) {
++ return get(expected).remove(o);
++ }
++ }
++ }
++
++ public boolean removeAll(Collection<?> o) {
++ if (fast) {
++ synchronized (FastArrayList.this) {
++ ArrayList temp = (ArrayList) list.clone();
++ List sub = get(temp);
++ boolean r = sub.removeAll(o);
++ if (r) last = first + sub.size();
++ list = temp;
++ expected = temp;
++ return r;
++ }
++ } else {
++ synchronized (list) {
++ return get(expected).removeAll(o);
++ }
++ }
++ }
++
++ public boolean retainAll(Collection<?> o) {
++ if (fast) {
++ synchronized (FastArrayList.this) {
++ ArrayList temp = (ArrayList) list.clone();
++ List sub = get(temp);
++ boolean r = sub.retainAll(o);
++ if (r) last = first + sub.size();
++ list = temp;
++ expected = temp;
++ return r;
++ }
++ } else {
++ synchronized (list) {
++ return get(expected).retainAll(o);
++ }
++ }
++ }
++
++ public int size() {
++ if (fast) {
++ return get(expected).size();
++ } else {
++ synchronized (list) {
++ return get(expected).size();
++ }
++ }
++ }
++
++
++ public boolean isEmpty() {
++ if (fast) {
++ return get(expected).isEmpty();
++ } else {
++ synchronized (list) {
++ return get(expected).isEmpty();
++ }
++ }
++ }
++
++ public boolean contains(Object o) {
++ if (fast) {
++ return get(expected).contains(o);
++ } else {
++ synchronized (list) {
++ return get(expected).contains(o);
++ }
++ }
++ }
++
++ public boolean containsAll(Collection<?> o) {
++ if (fast) {
++ return get(expected).containsAll(o);
++ } else {
++ synchronized (list) {
++ return get(expected).containsAll(o);
++ }
++ }
++ }
++
++ public <T> T[] toArray(T[] o) {
++ if (fast) {
++ return get(expected).toArray(o);
++ } else {
++ synchronized (list) {
++ return get(expected).toArray(o);
++ }
++ }
++ }
++
++ public Object[] toArray() {
++ if (fast) {
++ return get(expected).toArray();
++ } else {
++ synchronized (list) {
++ return get(expected).toArray();
++ }
++ }
++ }
++
++
++ public boolean equals(Object o) {
++ if (o == this) return true;
++ if (fast) {
++ return get(expected).equals(o);
++ } else {
++ synchronized (list) {
++ return get(expected).equals(o);
++ }
++ }
++ }
++
++ public int hashCode() {
++ if (fast) {
++ return get(expected).hashCode();
++ } else {
++ synchronized (list) {
++ return get(expected).hashCode();
++ }
++ }
++ }
++
++ public boolean add(E o) {
++ if (fast) {
++ synchronized (FastArrayList.this) {
++ ArrayList temp = (ArrayList) list.clone();
++ boolean r = get(temp).add(o);
++ if (r) last++;
++ list = temp;
++ expected = temp;
++ return r;
++ }
++ } else {
++ synchronized (list) {
++ return get(expected).add(o);
++ }
++ }
++ }
++
++ public boolean addAll(Collection<? extends E> o) {
++ if (fast) {
++ synchronized (FastArrayList.this) {
++ ArrayList temp = (ArrayList) list.clone();
++ boolean r = get(temp).addAll(o);
++ if (r) last += o.size();
++ list = temp;
++ expected = temp;
++ return r;
++ }
++ } else {
++ synchronized (list) {
++ return get(expected).addAll(o);
++ }
++ }
++ }
++
++ public void add(int i, E o) {
++ if (fast) {
++ synchronized (FastArrayList.this) {
++ ArrayList temp = (ArrayList) list.clone();
++ get(temp).add(i, o);
++ last++;
++ list = temp;
++ expected = temp;
++ }
++ } else {
++ synchronized (list) {
++ get(expected).add(i, o);
++ }
++ }
++ }
++
++ public boolean addAll(int i, Collection<? extends E> o) {
++ if (fast) {
++ synchronized (FastArrayList.this) {
++ ArrayList temp = (ArrayList) list.clone();
++ boolean r = get(temp).addAll(i, o);
++ list = temp;
++ if (r) last += o.size();
++ expected = temp;
++ return r;
++ }
++ } else {
++ synchronized (list) {
++ return get(expected).addAll(i, o);
++ }
++ }
++ }
++
++ public E remove(int i) {
++ if (fast) {
++ synchronized (FastArrayList.this) {
++ ArrayList temp = (ArrayList) list.clone();
++ E o = get(temp).remove(i);
++ last--;
++ list = temp;
++ expected = temp;
++ return o;
++ }
++ } else {
++ synchronized (list) {
++ return get(expected).remove(i);
++ }
++ }
++ }
++
++ public E set(int i, E a) {
++ if (fast) {
++ synchronized (FastArrayList.this) {
++ ArrayList temp = (ArrayList) list.clone();
++ E o = get(temp).set(i, a);
++ list = temp;
++ expected = temp;
++ return o;
++ }
++ } else {
++ synchronized (list) {
++ return get(expected).set(i, a);
++ }
++ }
++ }
++
++
++ public Iterator<E> iterator() {
++ return new SubListIter(0);
++ }
++
++ public ListIterator<E> listIterator() {
++ return new SubListIter(0);
++ }
++
++ public ListIterator<E> listIterator(int i) {
++ return new SubListIter(i);
++ }
++
++
++ public E get(int i) {
++ if (fast) {
++ return get(expected).get(i);
++ } else {
++ synchronized (list) {
++ return get(expected).get(i);
++ }
++ }
++ }
++
++ public int indexOf(Object o) {
++ if (fast) {
++ return get(expected).indexOf(o);
++ } else {
++ synchronized (list) {
++ return get(expected).indexOf(o);
++ }
++ }
++ }
++
++
++ public int lastIndexOf(Object o) {
++ if (fast) {
++ return get(expected).lastIndexOf(o);
++ } else {
++ synchronized (list) {
++ return get(expected).lastIndexOf(o);
++ }
++ }
++ }
++
++
++ public List<E> subList(int f, int l) {
++ if (list != expected) {
++ throw new ConcurrentModificationException();
++ }
++ return new SubList(first + f, f + l);
++ }
++
++
++ private class SubListIter implements ListIterator<E> {
++
++ private List<E> expected;
++ private ListIterator<E> iter;
++ private int lastReturnedIndex = -1;
++
++
++ public SubListIter(int i) {
++ this.expected = list;
++ this.iter = SubList.this.get(expected).listIterator(i);
++ }
++
++ private void checkMod() {
++ if (list != expected) {
++ throw new ConcurrentModificationException();
++ }
++ }
++
++ List<E> get() {
++ return SubList.this.get(expected);
++ }
++
++ public boolean hasNext() {
++ checkMod();
++ return iter.hasNext();
++ }
++
++ public E next() {
++ checkMod();
++ lastReturnedIndex = iter.nextIndex();
++ return iter.next();
++ }
++
++ public boolean hasPrevious() {
++ checkMod();
++ return iter.hasPrevious();
++ }
++
++ public E previous() {
++ checkMod();
++ lastReturnedIndex = iter.previousIndex();
++ return iter.previous();
++ }
++
++ public int previousIndex() {
++ checkMod();
++ return iter.previousIndex();
++ }
++
++ public int nextIndex() {
++ checkMod();
++ return iter.nextIndex();
++ }
++
++ public void remove() {
++ checkMod();
++ if (lastReturnedIndex < 0) {
++ throw new IllegalStateException();
++ }
++ get().remove(lastReturnedIndex);
++ last--;
++ expected = list;
++ iter = get().listIterator(previousIndex());
++ lastReturnedIndex = -1;
++ }
++
++ public void set(E o) {
++ checkMod();
++ if (lastReturnedIndex < 0) {
++ throw new IllegalStateException();
++ }
++ get().set(lastReturnedIndex, o);
++ expected = list;
++ iter = get().listIterator(previousIndex() + 1);
++ }
++
++ public void add(E o) {
++ checkMod();
++ int i = nextIndex();
++ get().add(i, o);
++ last++;
++ iter = get().listIterator(i + 1);
++ lastReturnedIndex = 1;
++ }
++
++ }
++
++
++ }
++
++
++ private class ListIter implements ListIterator<E> {
++
++ private List<E> expected;
++ private ListIterator<E> iter;
++ private int lastReturnedIndex = -1;
++
++
++ public ListIter(int i) {
++ this.expected = list;
++ this.iter = get().listIterator(i);
++ }
++
++ private void checkMod() {
++ if (list != expected) {
++ throw new ConcurrentModificationException();
++ }
++ }
++
++ List get() {
++ return expected;
++ }
++
++ public boolean hasNext() {
++ checkMod();
++ return iter.hasNext();
++ }
++
++ public E next() {
++ checkMod();
++ lastReturnedIndex = iter.nextIndex();
++ return iter.next();
++ }
++
++ public boolean hasPrevious() {
++ checkMod();
++ return iter.hasPrevious();
++ }
++
++ public E previous() {
++ checkMod();
++ lastReturnedIndex = iter.previousIndex();
++ return iter.previous();
++ }
++
++ public int previousIndex() {
++ checkMod();
++ return iter.previousIndex();
++ }
++
++ public int nextIndex() {
++ checkMod();
++ return iter.nextIndex();
++ }
++
++ public void remove() {
++ checkMod();
++ if (lastReturnedIndex < 0) {
++ throw new IllegalStateException();
++ }
++ get().remove(lastReturnedIndex);
++ expected = list;
++ iter = get().listIterator(previousIndex());
++ lastReturnedIndex = -1;
++ }
++
++ public void set(E o) {
++ checkMod();
++ if (lastReturnedIndex < 0) {
++ throw new IllegalStateException();
++ }
++ get().set(lastReturnedIndex, o);
++ expected = list;
++ iter = get().listIterator(previousIndex() + 1);
++ }
++
++ public void add(E o) {
++ checkMod();
++ int i = nextIndex();
++ get().add(i, o);
++ iter = get().listIterator(i + 1);
++ lastReturnedIndex = -1;
++ }
++
++ }
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/FixedSizeList.java
+@@ -0,0 +1,164 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import org.apache.commons.collections15.BoundedCollection;
++import org.apache.commons.collections15.iterators.AbstractListIteratorDecorator;
++import org.apache.commons.collections15.iterators.UnmodifiableIterator;
++
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.List;
++import java.util.ListIterator;
++
++/**
++ * Decorates another <code>List</code> to fix the size preventing add/remove.
++ * <p/>
++ * The add, remove, clear and retain operations are unsupported.
++ * The set method is allowed (as it doesn't change the list size).
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class FixedSizeList <E> extends AbstractSerializableListDecorator<E> implements BoundedCollection<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -2218010673611160319L;
++
++ /**
++ * Factory method to create a fixed size list.
++ *
++ * @param list the list to decorate, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ public static <E> List<E> decorate(List<E> list) {
++ return new FixedSizeList<E>(list);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param list the list to decorate, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ protected FixedSizeList(List<E> list) {
++ super(list);
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean add(E object) {
++ throw new UnsupportedOperationException("List is fixed size");
++ }
++
++ public void add(int index, E object) {
++ throw new UnsupportedOperationException("List is fixed size");
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ throw new UnsupportedOperationException("List is fixed size");
++ }
++
++ public boolean addAll(int index, Collection<? extends E> coll) {
++ throw new UnsupportedOperationException("List is fixed size");
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException("List is fixed size");
++ }
++
++ public E get(int index) {
++ return getList().get(index);
++ }
++
++ public int indexOf(Object object) {
++ return getList().indexOf(object);
++ }
++
++ public Iterator<E> iterator() {
++ return UnmodifiableIterator.decorate(getCollection().iterator());
++ }
++
++ public int lastIndexOf(Object object) {
++ return getList().lastIndexOf(object);
++ }
++
++ public ListIterator<E> listIterator() {
++ return new FixedSizeListIterator<E>(getList().listIterator(0));
++ }
++
++ public ListIterator<E> listIterator(int index) {
++ return new FixedSizeListIterator<E>(getList().listIterator(index));
++ }
++
++ public E remove(int index) {
++ throw new UnsupportedOperationException("List is fixed size");
++ }
++
++ public boolean remove(Object object) {
++ throw new UnsupportedOperationException("List is fixed size");
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ throw new UnsupportedOperationException("List is fixed size");
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ throw new UnsupportedOperationException("List is fixed size");
++ }
++
++ public E set(int index, E object) {
++ return getList().set(index, object);
++ }
++
++ public List<E> subList(int fromIndex, int toIndex) {
++ List<E> sub = getList().subList(fromIndex, toIndex);
++ return new FixedSizeList<E>(sub);
++ }
++
++ /**
++ * List iterator that only permits changes via set()
++ */
++ static class FixedSizeListIterator <E> extends AbstractListIteratorDecorator<E> {
++ protected FixedSizeListIterator(ListIterator<E> iterator) {
++ super(iterator);
++ }
++
++ public void remove() {
++ throw new UnsupportedOperationException("List is fixed size");
++ }
++
++ public void add(E object) {
++ throw new UnsupportedOperationException("List is fixed size");
++ }
++ }
++
++ public boolean isFull() {
++ return true;
++ }
++
++ public int maxSize() {
++ return size();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/LazyList.java
+@@ -0,0 +1,140 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import org.apache.commons.collections15.Factory;
++
++import java.util.List;
++
++/**
++ * Decorates another <code>List</code> to create objects in the list on demand.
++ * <p/>
++ * When the {@link #get(int)} method is called with an index greater than
++ * the size of the list, the list will automatically grow in size and return
++ * a new object from the specified factory. The gaps will be filled by null.
++ * If a get method call encounters a null, it will be replaced with a new
++ * object from the factory. Thus this list is unsuitable for storing null
++ * objects.
++ * <p/>
++ * For instance:
++ * <p/>
++ * <pre>
++ * Factory factory = new Factory() {
++ * public Object create() {
++ * return new Date();
++ * }
++ * }
++ * List lazy = LazyList.decorate(new ArrayList(), factory);
++ * Object obj = lazy.get(3);
++ * </pre>
++ * <p/>
++ * After the above code is executed, <code>obj</code> will contain
++ * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
++ * instance is the fourth element in the list. The first, second,
++ * and third element are all set to <code>null</code>.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Arron Bates
++ * @author Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class LazyList <E> extends AbstractSerializableListDecorator<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -1708388017160694542L;
++
++ /**
++ * The factory to use to lazily instantiate the objects
++ */
++ protected final Factory<? extends E> factory;
++
++ /**
++ * Factory method to create a lazily instantiating list.
++ *
++ * @param list the list to decorate, must not be null
++ * @param factory the factory to use for creation, must not be null
++ * @throws IllegalArgumentException if list or factory is null
++ */
++ public static <E> List<E> decorate(List<E> list, Factory<? extends E> factory) {
++ return new LazyList<E>(list, factory);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param list the list to decorate, must not be null
++ * @param factory the factory to use for creation, must not be null
++ * @throws IllegalArgumentException if list or factory is null
++ */
++ protected LazyList(List<E> list, Factory<? extends E> factory) {
++ super(list);
++ if (factory == null) {
++ throw new IllegalArgumentException("Factory must not be null");
++ }
++ this.factory = factory;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Decorate the get method to perform the lazy behaviour.
++ * <p/>
++ * If the requested index is greater than the current size, the list will
++ * grow to the new size and a new object will be returned from the factory.
++ * Indexes in-between the old size and the requested size are left with a
++ * placeholder that is replaced with a factory object when requested.
++ *
++ * @param index the index to retrieve
++ */
++ public E get(int index) {
++ int size = getList().size();
++ if (index < size) {
++ // within bounds, get the object
++ E object = getList().get(index);
++ if (object == null) {
++ // item is a place holder, create new one, set and return
++ object = factory.create();
++ getList().set(index, object);
++ return object;
++ } else {
++ // good and ready to go
++ return object;
++ }
++ } else {
++ // we have to grow the list
++ for (int i = size; i < index; i++) {
++ getList().add(null);
++ }
++ // create our last object, set and return
++ E object = factory.create();
++ getList().add(object);
++ return object;
++ }
++ }
++
++
++ public List<E> subList(int fromIndex, int toIndex) {
++ List<E> sub = getList().subList(fromIndex, toIndex);
++ return new LazyList<E>(sub, factory);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/NodeCachingLinkedList.java
+@@ -0,0 +1,247 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++
++/**
++ * A <code>List</code> implementation that stores a cache of internal Node objects
++ * in an effort to reduce wasteful object creation.
++ * <p/>
++ * A linked list creates one Node for each item of data added. This can result in
++ * a lot of object creation and garbage collection. This implementation seeks to
++ * avoid that by maintaining a store of cached nodes.
++ * <p/>
++ * This implementation is suitable for long-lived lists where both add and remove
++ * are used. Short-lived lists, or lists which only grow will have worse performance
++ * using this class.
++ * <p/>
++ * <b>Note that this implementation is not synchronized.</b>
++ *
++ * @author Matt Hall, John Watkinson, Jeff Varszegi
++ * @author Rich Dougherty
++ * @author Phil Steitz
++ * @author Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class NodeCachingLinkedList <E> extends AbstractLinkedList<E> implements Serializable {
++
++ /**
++ * Serialization version
++ */
++ static final long serialVersionUID = 6897789178562232073L;
++
++ /**
++ * The default value for {@link #maximumCacheSize}.
++ */
++ protected static final int DEFAULT_MAXIMUM_CACHE_SIZE = 20;
++
++ /**
++ * The first cached node, or <code>null</code> if no nodes are cached.
++ * Cached nodes are stored in a singly-linked list with
++ * <code>next</code> pointing to the next element.
++ */
++ protected transient Node<E> firstCachedNode;
++
++ /**
++ * The size of the cache.
++ */
++ protected transient int cacheSize;
++
++ /**
++ * The maximum size of the cache.
++ */
++ protected int maximumCacheSize;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that creates.
++ */
++ public NodeCachingLinkedList() {
++ this(DEFAULT_MAXIMUM_CACHE_SIZE);
++ }
++
++ /**
++ * Constructor that copies the specified collection
++ *
++ * @param coll the collection to copy
++ */
++ public NodeCachingLinkedList(Collection<E> coll) {
++ super(coll);
++ this.maximumCacheSize = DEFAULT_MAXIMUM_CACHE_SIZE;
++ }
++
++ /**
++ * Constructor that species the maximum cache size.
++ *
++ * @param maximumCacheSize the maximum cache size
++ */
++ public NodeCachingLinkedList(int maximumCacheSize) {
++ super();
++ this.maximumCacheSize = maximumCacheSize;
++ init(); // must call init() as use super();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the maximum size of the cache.
++ *
++ * @return the maximum cache size
++ */
++ protected int getMaximumCacheSize() {
++ return maximumCacheSize;
++ }
++
++ /**
++ * Sets the maximum size of the cache.
++ *
++ * @param maximumCacheSize the new maximum cache size
++ */
++ protected void setMaximumCacheSize(int maximumCacheSize) {
++ this.maximumCacheSize = maximumCacheSize;
++ shrinkCacheToMaximumSize();
++ }
++
++ /**
++ * Reduce the size of the cache to the maximum, if necessary.
++ */
++ protected void shrinkCacheToMaximumSize() {
++ // Rich Dougherty: This could be more efficient.
++ while (cacheSize > maximumCacheSize) {
++ getNodeFromCache();
++ }
++ }
++
++ /**
++ * Gets a node from the cache. If a node is returned, then the value of
++ * {@link #cacheSize} is decreased accordingly. The node that is returned
++ * will have <code>null</code> values for next, previous and element.
++ *
++ * @return a node, or <code>null</code> if there are no nodes in the cache.
++ */
++ protected Node<E> getNodeFromCache() {
++ if (cacheSize == 0) {
++ return null;
++ }
++ Node<E> cachedNode = firstCachedNode;
++ firstCachedNode = cachedNode.next;
++ cachedNode.next = null; // This should be changed anyway, but defensively
++ // set it to null.
++ cacheSize--;
++ return cachedNode;
++ }
++
++ /**
++ * Checks whether the cache is full.
++ *
++ * @return true if the cache is full
++ */
++ protected boolean isCacheFull() {
++ return cacheSize >= maximumCacheSize;
++ }
++
++ /**
++ * Adds a node to the cache, if the cache isn't full.
++ * The node's contents are cleared to so they can be garbage collected.
++ *
++ * @param node the node to add to the cache
++ */
++ protected void addNodeToCache(Node<E> node) {
++ if (isCacheFull()) {
++ // don't cache the node.
++ return;
++ }
++ // clear the node's contents and add it to the cache.
++ Node<E> nextCachedNode = firstCachedNode;
++ node.previous = null;
++ node.next = nextCachedNode;
++ node.setValue(null);
++ firstCachedNode = node;
++ cacheSize++;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Creates a new node, either by reusing one from the cache or creating
++ * a new one.
++ *
++ * @param value value of the new node
++ * @return the newly created node
++ */
++ protected Node<E> createNode(E value) {
++ Node<E> cachedNode = getNodeFromCache();
++ if (cachedNode == null) {
++ return super.createNode(value);
++ } else {
++ cachedNode.setValue(value);
++ return cachedNode;
++ }
++ }
++
++ /**
++ * Removes the node from the list, storing it in the cache for reuse
++ * if the cache is not yet full.
++ *
++ * @param node the node to remove
++ */
++ protected void removeNode(Node<E> node) {
++ super.removeNode(node);
++ addNodeToCache(node);
++ }
++
++ /**
++ * Removes all the nodes from the list, storing as many as required in the
++ * cache for reuse.
++ */
++ protected void removeAllNodes() {
++ // Add the removed nodes to the cache, then remove the rest.
++ // We can add them to the cache before removing them, since
++ // {@link AbstractLinkedList.removeAllNodes()} removes the
++ // nodes by removing references directly from {@link #header}.
++ int numberOfNodesToCache = Math.min(size, maximumCacheSize - cacheSize);
++ Node<E> node = header.next;
++ for (int currentIndex = 0; currentIndex < numberOfNodesToCache; currentIndex++) {
++ Node<E> oldNode = node;
++ node = node.next;
++ addNodeToCache(oldNode);
++ }
++ super.removeAllNodes();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Serializes the data held in this object to the stream specified.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ doWriteObject(out);
++ }
++
++ /**
++ * Deserializes the data held in this object to the stream specified.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ doReadObject(in);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/PredicatedList.java
+@@ -0,0 +1,161 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import org.apache.commons.collections15.Predicate;
++import org.apache.commons.collections15.collection.PredicatedCollection;
++import org.apache.commons.collections15.iterators.AbstractListIteratorDecorator;
++
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.List;
++import java.util.ListIterator;
++
++/**
++ * Decorates another <code>List</code> to validate that all additions
++ * match a specified predicate.
++ * <p/>
++ * This list exists to provide validation for the decorated list.
++ * It is normally created to decorate an empty list.
++ * If an object cannot be added to the list, an IllegalArgumentException is thrown.
++ * <p/>
++ * One usage would be to ensure that no null entries are added to the list.
++ * <pre>List list = PredicatedList.decorate(new ArrayList(), NotNullPredicate.INSTANCE);</pre>
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @author Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class PredicatedList <E> extends PredicatedCollection<E> implements List<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -5722039223898659102L;
++
++ /**
++ * Factory method to create a predicated (validating) list.
++ * <p/>
++ * If there are any elements already in the list being decorated, they
++ * are validated.
++ *
++ * @param list the list to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @throws IllegalArgumentException if list or predicate is null
++ * @throws IllegalArgumentException if the list contains invalid elements
++ */
++ public static <E> List<E> decorate(List<E> list, Predicate<? super E> predicate) {
++ return new PredicatedList<E>(list, predicate);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the list being decorated, they
++ * are validated.
++ *
++ * @param list the list to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @throws IllegalArgumentException if list or predicate is null
++ * @throws IllegalArgumentException if the list contains invalid elements
++ */
++ protected PredicatedList(List<E> list, Predicate<? super E> predicate) {
++ super(list, predicate);
++ }
++
++ /**
++ * Gets the list being decorated.
++ *
++ * @return the decorated list
++ */
++ protected List<E> getList() {
++ return (List<E>) getCollection();
++ }
++
++ //-----------------------------------------------------------------------
++ public E get(int index) {
++ return getList().get(index);
++ }
++
++ public int indexOf(Object object) {
++ return getList().indexOf(object);
++ }
++
++ public int lastIndexOf(Object object) {
++ return getList().lastIndexOf(object);
++ }
++
++ public E remove(int index) {
++ return getList().remove(index);
++ }
++
++ //-----------------------------------------------------------------------
++ public void add(int index, E object) {
++ validate(object);
++ getList().add(index, object);
++ }
++
++ public boolean addAll(int index, Collection<? extends E> coll) {
++ for (Iterator<? extends E> it = coll.iterator(); it.hasNext();) {
++ validate(it.next());
++ }
++ return getList().addAll(index, coll);
++ }
++
++ public ListIterator<E> listIterator() {
++ return listIterator(0);
++ }
++
++ public ListIterator<E> listIterator(int i) {
++ return new PredicatedListIterator(getList().listIterator(i));
++ }
++
++ public E set(int index, E object) {
++ validate(object);
++ return getList().set(index, object);
++ }
++
++ public List<E> subList(int fromIndex, int toIndex) {
++ List<E> sub = getList().subList(fromIndex, toIndex);
++ return new PredicatedList<E>(sub, predicate);
++ }
++
++ /**
++ * Inner class Iterator for the PredicatedList
++ */
++ protected class PredicatedListIterator extends AbstractListIteratorDecorator<E> {
++
++ protected PredicatedListIterator(ListIterator<E> iterator) {
++ super(iterator);
++ }
++
++ public void add(E object) {
++ validate(object);
++ iterator.add(object);
++ }
++
++ public void set(E object) {
++ validate(object);
++ iterator.set(object);
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/SetUniqueList.java
+@@ -0,0 +1,332 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import org.apache.commons.collections15.iterators.AbstractIteratorDecorator;
++import org.apache.commons.collections15.iterators.AbstractListIteratorDecorator;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++import java.util.*;
++
++/**
++ * Decorates a <code>List</code> to ensure that no duplicates are present
++ * much like a <code>Set</code>.
++ * <p/>
++ * The <code>List</code> interface makes certain assumptions/requirements.
++ * This implementation breaks these in certain ways, but this is merely the
++ * result of rejecting duplicates.
++ * Each violation is explained in the method, but it should not affect you.
++ * <p/>
++ * The {@link org.apache.commons.collections15.set.ListOrderedSet ListOrderedSet}
++ * class provides an alternative approach, by wrapping an existing Set and
++ * retaining insertion order in the iterator.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matthew Hawthorne
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class SetUniqueList <E> extends AbstractSerializableListDecorator<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 7196982186153478694L;
++
++ /**
++ * Internal Set to maintain uniqueness.
++ */
++ protected final Set<E> set;
++
++ /**
++ * Factory method to create a SetList using the supplied list to retain order.
++ * <p/>
++ * If the list contains duplicates, these are removed (first indexed one kept).
++ * A <code>HashSet</code> is used for the set behaviour.
++ *
++ * @param list the list to decorate, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ public static <E> SetUniqueList<E> decorate(List<E> list) {
++ if (list == null) {
++ throw new IllegalArgumentException("List must not be null");
++ }
++ if (list.isEmpty()) {
++ return new SetUniqueList<E>(list, new HashSet());
++ } else {
++ List temp = new ArrayList(list);
++ list.clear();
++ SetUniqueList<E> sl = new SetUniqueList<E>(list, new HashSet());
++ sl.addAll(temp);
++ return sl;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies) the List and specifies the set to use.
++ * <p/>
++ * The set and list must both be correctly initialised to the same elements.
++ *
++ * @param set the set to decorate, must not be null
++ * @param list the list to decorate, must not be null
++ * @throws IllegalArgumentException if set or list is null
++ */
++ protected SetUniqueList(List<E> list, Set<E> set) {
++ super(list);
++ if (set == null) {
++ throw new IllegalArgumentException("Set must not be null");
++ }
++ this.set = set;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an unmodifiable view as a Set.
++ *
++ * @return an unmodifiable set view
++ */
++ public Set<E> asSet() {
++ return UnmodifiableSet.decorate(set);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Adds an element to the list if it is not already present.
++ * <p/>
++ * <i>(Violation)</i>
++ * The <code>List</code> interface requires that this method returns
++ * <code>true</code> always. However this class may return <code>false</code>
++ * because of the <code>Set</code> behaviour.
++ *
++ * @param object the object to add
++ * @return true if object was added
++ */
++ public boolean add(E object) {
++ // gets initial size
++ final int sizeBefore = size();
++
++ // adds element if unique
++ add(size(), object);
++
++ // compares sizes to detect if collection changed
++ return (sizeBefore != size());
++ }
++
++ /**
++ * Adds an element to a specific index in the list if it is not already present.
++ * <p/>
++ * <i>(Violation)</i>
++ * The <code>List</code> interface makes the assumption that the element is
++ * always inserted. This may not happen with this implementation.
++ *
++ * @param index the index to insert at
++ * @param object the object to add
++ */
++ public void add(int index, E object) {
++ // adds element if it is not contained already
++ if (set.contains(object) == false) {
++ super.add(index, object);
++ set.add(object);
++ }
++ }
++
++ /**
++ * Adds an element to the end of the list if it is not already present.
++ * <p/>
++ * <i>(Violation)</i>
++ * The <code>List</code> interface makes the assumption that the element is
++ * always inserted. This may not happen with this implementation.
++ *
++ * @param coll the collection to add
++ */
++ public boolean addAll(Collection<? extends E> coll) {
++ return addAll(size(), coll);
++ }
++
++ /**
++ * Adds a collection of objects to the end of the list avoiding duplicates.
++ * <p/>
++ * Only elements that are not already in this list will be added, and
++ * duplicates from the specified collection will be ignored.
++ * <p/>
++ * <i>(Violation)</i>
++ * The <code>List</code> interface makes the assumption that the elements
++ * are always inserted. This may not happen with this implementation.
++ *
++ * @param index the index to insert at
++ * @param coll the collection to add in iterator order
++ * @return true if this collection changed
++ */
++ public boolean addAll(int index, Collection<? extends E> coll) {
++ // gets initial size
++ final int sizeBefore = size();
++
++ // adds all elements
++ for (final Iterator it = coll.iterator(); it.hasNext();) {
++ add((E) it.next());
++ }
++
++ // compares sizes to detect if collection changed
++ return sizeBefore != size();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Sets the value at the specified index avoiding duplicates.
++ * <p/>
++ * The object is set into the specified index.
++ * Afterwards, any previous duplicate is removed
++ * If the object is not already in the list then a normal set occurs.
++ * If it is present, then the old version is removed and re-added at this index
++ *
++ * @param index the index to insert at
++ * @param object the object to set
++ * @return the previous object
++ */
++ public E set(int index, E object) {
++ int pos = indexOf(object);
++ E result = super.set(index, object);
++ if (pos == -1 || pos == index) {
++ return result;
++ }
++ return remove(pos);
++ }
++
++ public boolean remove(Object object) {
++ boolean result = super.remove(object);
++ set.remove(object);
++ return result;
++ }
++
++ public E remove(int index) {
++ E result = super.remove(index);
++ set.remove(result);
++ return result;
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ boolean result = super.removeAll(coll);
++ set.removeAll(coll);
++ return result;
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ boolean result = super.retainAll(coll);
++ set.retainAll(coll);
++ return result;
++ }
++
++ public void clear() {
++ super.clear();
++ set.clear();
++ }
++
++ public boolean contains(Object object) {
++ return set.contains(object);
++ }
++
++ public boolean containsAll(Collection<?> coll) {
++ return set.containsAll(coll);
++ }
++
++ public Iterator<E> iterator() {
++ return new SetListIterator(super.iterator(), set);
++ }
++
++ public ListIterator<E> listIterator() {
++ return new SetListListIterator(super.listIterator(), set);
++ }
++
++ public ListIterator<E> listIterator(int index) {
++ return new SetListListIterator(super.listIterator(index), set);
++ }
++
++ public List<E> subList(int fromIndex, int toIndex) {
++ return new SetUniqueList<E>(super.subList(fromIndex, toIndex), set);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Inner class iterator.
++ */
++ static class SetListIterator <E> extends AbstractIteratorDecorator<E> {
++
++ protected final Set<E> set;
++ protected E last = null;
++
++ protected SetListIterator(Iterator<E> it, Set<E> set) {
++ super(it);
++ this.set = set;
++ }
++
++ public E next() {
++ last = super.next();
++ return last;
++ }
++
++ public void remove() {
++ super.remove();
++ set.remove(last);
++ last = null;
++ }
++ }
++
++ /**
++ * Inner class iterator.
++ */
++ static class SetListListIterator <E> extends AbstractListIteratorDecorator<E> {
++
++ protected final Set<E> set;
++ protected E last = null;
++
++ protected SetListListIterator(ListIterator<E> it, Set<E> set) {
++ super(it);
++ this.set = set;
++ }
++
++ public E next() {
++ last = super.next();
++ return last;
++ }
++
++ public E previous() {
++ last = super.previous();
++ return last;
++ }
++
++ public void remove() {
++ super.remove();
++ set.remove(last);
++ last = null;
++ }
++
++ public void add(E object) {
++ if (set.contains(object) == false) {
++ super.add(object);
++ set.add(object);
++ }
++ }
++
++ public void set(E object) {
++ throw new UnsupportedOperationException("ListIterator does not support set");
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/SynchronizedList.java
+@@ -0,0 +1,165 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import org.apache.commons.collections15.collection.SynchronizedCollection;
++
++import java.util.Collection;
++import java.util.List;
++import java.util.ListIterator;
++
++/**
++ * Decorates another <code>List</code> to synchronize its behaviour
++ * for a multi-threaded environment.
++ * <p/>
++ * Methods are synchronized, then forwarded to the decorated list.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class SynchronizedList <E> extends SynchronizedCollection<E> implements List<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -1403835447328619437L;
++
++ /**
++ * Factory method to create a synchronized list.
++ *
++ * @param list the list to decorate, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ public static <E> List<E> decorate(List<E> list) {
++ return new SynchronizedList<E>(list);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param list the list to decorate, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ protected SynchronizedList(List<E> list) {
++ super(list);
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param list the list to decorate, must not be null
++ * @param lock the lock to use, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ protected SynchronizedList(List<E> list, Object lock) {
++ super(list, lock);
++ }
++
++ /**
++ * Gets the decorated list.
++ *
++ * @return the decorated list
++ */
++ protected List<E> getList() {
++ return (List<E>) collection;
++ }
++
++ //-----------------------------------------------------------------------
++ public void add(int index, E object) {
++ synchronized (lock) {
++ getList().add(index, object);
++ }
++ }
++
++ public boolean addAll(int index, Collection<? extends E> coll) {
++ synchronized (lock) {
++ return getList().addAll(index, coll);
++ }
++ }
++
++ public E get(int index) {
++ synchronized (lock) {
++ return getList().get(index);
++ }
++ }
++
++ public int indexOf(Object object) {
++ synchronized (lock) {
++ return getList().indexOf(object);
++ }
++ }
++
++ public int lastIndexOf(Object object) {
++ synchronized (lock) {
++ return getList().lastIndexOf(object);
++ }
++ }
++
++ /**
++ * Iterators must be manually synchronized.
++ * <pre>
++ * synchronized (coll) {
++ * ListIterator it = coll.listIterator();
++ * // do stuff with iterator
++ * }
++ *
++ * @return an iterator that must be manually synchronized on the collection
++ */
++ public ListIterator<E> listIterator() {
++ return getList().listIterator();
++ }
++
++ /**
++ * Iterators must be manually synchronized.
++ * <pre>
++ * synchronized (coll) {
++ * ListIterator it = coll.listIterator(3);
++ * // do stuff with iterator
++ * }
++ *
++ * @return an iterator that must be manually synchronized on the collection
++ */
++ public ListIterator<E> listIterator(int index) {
++ return getList().listIterator(index);
++ }
++
++ public E remove(int index) {
++ synchronized (lock) {
++ return getList().remove(index);
++ }
++ }
++
++ public E set(int index, E object) {
++ synchronized (lock) {
++ return getList().set(index, object);
++ }
++ }
++
++ public List<E> subList(int fromIndex, int toIndex) {
++ synchronized (lock) {
++ List<E> list = getList().subList(fromIndex, toIndex);
++ // the lock is passed into the constructor here to ensure that the sublist is
++ // synchronized on the same lock as the parent list
++ return new SynchronizedList<E>(list, lock);
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/TransformedList.java
+@@ -0,0 +1,168 @@
++// GenericsNote: Converted, but unfortunately very little type-safety could be achieved without breaking List and ListIterator interfaces.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import org.apache.commons.collections15.Transformer;
++import org.apache.commons.collections15.collection.TransformedCollection;
++import org.apache.commons.collections15.iterators.AbstractListIteratorDecorator;
++
++import java.util.Collection;
++import java.util.List;
++import java.util.ListIterator;
++
++/**
++ * Decorates another <code>List</code> to transform objects that are added.
++ * <p/>
++ * The add and set methods are affected by this class.
++ * Thus objects must be removed or searched for using their transformed form.
++ * For example, if the transformation converts Strings to Integers, you must
++ * use the Integer form to remove objects.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ * <p>
++ * Note: This class cannot support generics without breaking the Collection contract.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class TransformedList <I,O> extends TransformedCollection<I, O> implements List {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 1077193035000013141L;
++
++ /**
++ * Factory method to create a transforming list.
++ * <p/>
++ * If there are any elements already in the list being decorated, they
++ * are NOT transformed.
++ *
++ * @param list the list to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @throws IllegalArgumentException if list or transformer is null
++ */
++ public static <I,O> List<O> decorate(List<I> list, Transformer<? super I, ? extends O> transformer) {
++ return new TransformedList<I, O>(list, transformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the list being decorated, they
++ * are NOT transformed.
++ *
++ * @param list the list to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @throws IllegalArgumentException if list or transformer is null
++ */
++ protected TransformedList(List<I> list, Transformer<? super I, ? extends O> transformer) {
++ super(list, transformer);
++ }
++
++ /**
++ * Gets the decorated list.
++ *
++ * @return the decorated list
++ */
++ protected List<O> getList() {
++ return (List<O>) collection;
++ }
++
++ //-----------------------------------------------------------------------
++ public O get(int index) {
++ return getList().get(index);
++ }
++
++ public int indexOf(Object object) {
++ return getList().indexOf(object);
++ }
++
++ public int lastIndexOf(Object object) {
++ return getList().lastIndexOf(object);
++ }
++
++ public Object remove(int index) {
++ return getList().remove(index);
++ }
++
++ //-----------------------------------------------------------------------
++ public void add(int index, Object object) {
++ O transformed = transform((I) object);
++ getList().add(index, transformed);
++ }
++
++ /**
++ * Type-safe version of {@link #add(int, Object)} (but breaks List interface).
++ */
++ public void addTyped(int index, I object) {
++ add(index, object);
++ }
++
++ public boolean addAll(int index, Collection coll) {
++ Collection<O> transformed = transform((Collection<? extends I>) coll);
++ return getList().addAll(index, transformed);
++ }
++
++ public ListIterator<O> listIterator() {
++ return listIterator(0);
++ }
++
++ public ListIterator<O> listIterator(int i) {
++ return new TransformedListIterator(getList().listIterator(i));
++ }
++
++ public O set(int index, Object object) {
++ O transformed = transform((I) object);
++ return getList().set(index, transformed);
++ }
++
++ /**
++ * Type-safe version of {@link #set(int, Object)} (but breaks List interface).
++ */
++ public O setTyped(int index, I object) {
++ return set(index, object);
++ }
++
++ public List<O> subList(int fromIndex, int toIndex) {
++ List sub = getList().subList(fromIndex, toIndex);
++ return new TransformedList<I, O>(sub, transformer);
++ }
++
++ /**
++ * Inner class Iterator for the TransformedList
++ */
++ protected class TransformedListIterator extends AbstractListIteratorDecorator {
++
++ protected TransformedListIterator(ListIterator<O> iterator) {
++ super(iterator);
++ }
++
++ public void add(Object object) {
++ O transformed = transform((I) object);
++ iterator.add(transformed);
++ }
++
++ public void set(Object object) {
++ O transformed = transform((I) object);
++ iterator.set(transformed);
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/TreeList.java
+@@ -0,0 +1,898 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import org.apache.commons.collections15.OrderedIterator;
++
++import java.util.*;
++
++/**
++ * A <code>List</code> implementation that is optimised for fast insertions and
++ * removals at any index in the list.
++ * <p/>
++ * This list implementation utilises a tree structure internally to ensure that
++ * all insertions and removals are O(log n). This provides much faster performance
++ * than both an <code>ArrayList</code> and a <code>LinkedList</code> where elements
++ * are inserted and removed repeatedly from anywhere in the list.
++ * <p/>
++ * The following relative performance statistics are indicative of this class:
++ * <pre>
++ * get add insert iterate remove
++ * TreeList 3 5 1 2 1
++ * ArrayList 1 1 40 1 40
++ * LinkedList 5800 1 350 2 325
++ * </pre>
++ * <code>ArrayList</code> is a good general purpose list implementation.
++ * It is faster than <code>TreeList</code> for most operations except inserting
++ * and removing in the middle of the list. <code>ArrayList</code> also uses less
++ * memory as <code>TreeList</code> uses one object per entry.
++ * <p/>
++ * <code>LinkedList</code> is rarely a good choice of implementation.
++ * <code>TreeList</code> is almost always a good replacement for it, although it
++ * does use sligtly more memory.
++ *
++ * @author Matt Hall, John Watkinson, Joerg Schmuecker
++ * @author Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.1
++ */
++public class TreeList <E> extends AbstractList<E> {
++ // add; toArray; iterator; insert; get; indexOf; remove
++ // TreeList = 1260;7360;3080; 160; 170;3400; 170;
++ // ArrayList = 220;1480;1760; 6870; 50;1540; 7200;
++ // LinkedList = 270;7360;3350;55860;290720;2910;55200;
++
++ /**
++ * The root node in the AVL tree
++ */
++ private AVLNode<E> root;
++
++ /**
++ * The current size of the list
++ */
++ private int size;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructs a new empty list.
++ */
++ public TreeList() {
++ super();
++ }
++
++ /**
++ * Constructs a new empty list that copies the specified list.
++ *
++ * @param coll the collection to copy
++ * @throws NullPointerException if the collection is null
++ */
++ public TreeList(Collection<? extends E> coll) {
++ super();
++ addAll(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the element at the specified index.
++ *
++ * @param index the index to retrieve
++ * @return the element at the specified index
++ */
++ public E get(int index) {
++ checkInterval(index, 0, size() - 1);
++ return root.get(index).getValue();
++ }
++
++ /**
++ * Gets the current size of the list.
++ *
++ * @return the current size
++ */
++ public int size() {
++ return size;
++ }
++
++ /**
++ * Gets an iterator over the list.
++ *
++ * @return an iterator over the list
++ */
++ public Iterator<E> iterator() {
++ // override to go 75% faster
++ return listIterator(0);
++ }
++
++ /**
++ * Gets a ListIterator over the list.
++ *
++ * @return the new iterator
++ */
++ public ListIterator<E> listIterator() {
++ // override to go 75% faster
++ return listIterator(0);
++ }
++
++ /**
++ * Gets a ListIterator over the list.
++ *
++ * @param fromIndex the index to start from
++ * @return the new iterator
++ */
++ public ListIterator<E> listIterator(int fromIndex) {
++ // override to go 75% faster
++ // cannot use EmptyIterator as iterator.add() must work
++ checkInterval(fromIndex, 0, size());
++ return new TreeListIterator<E>(this, fromIndex);
++ }
++
++ /**
++ * Searches for the index of an object in the list.
++ *
++ * @return the index of the object, -1 if not found
++ */
++ public int indexOf(Object object) {
++ // override to go 75% faster
++ if (root == null) {
++ return -1;
++ }
++ return root.indexOf((E) object, root.relativePosition);
++ }
++
++ /**
++ * Searches for the presence of an object in the list.
++ *
++ * @return true if the object is found
++ */
++ public boolean contains(Object object) {
++ return (indexOf(object) >= 0);
++ }
++
++ /**
++ * Converts the list into an array.
++ *
++ * @return the list as an array
++ */
++ public Object[] toArray() {
++ // override to go 20% faster
++ Object[] array = new Object[size()];
++ if (root != null) {
++ root.toArray((E[]) array, root.relativePosition);
++ }
++ return array;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Adds a new element to the list.
++ *
++ * @param index the index to add before
++ * @param obj the element to add
++ */
++ public void add(int index, E obj) {
++ modCount++;
++ checkInterval(index, 0, size());
++ if (root == null) {
++ root = new AVLNode<E>(index, obj, null, null);
++ } else {
++ root = root.insert(index, obj);
++ }
++ size++;
++ }
++
++ /**
++ * Sets the element at the specified index.
++ *
++ * @param index the index to set
++ * @param obj the object to store at the specified index
++ * @return the previous object at that index
++ * @throws IndexOutOfBoundsException if the index is invalid
++ */
++ public E set(int index, E obj) {
++ checkInterval(index, 0, size() - 1);
++ AVLNode<E> node = root.get(index);
++ E result = node.value;
++ node.setValue(obj);
++ return result;
++ }
++
++ /**
++ * Removes the element at the specified index.
++ *
++ * @param index the index to remove
++ * @return the previous object at that index
++ */
++ public E remove(int index) {
++ modCount++;
++ checkInterval(index, 0, size() - 1);
++ E result = get(index);
++ root = root.remove(index);
++ size--;
++ return result;
++ }
++
++ /**
++ * Clears the list, removing all entries.
++ */
++ public void clear() {
++ modCount++;
++ root = null;
++ size = 0;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Checks whether the index is valid.
++ *
++ * @param index the index to check
++ * @param startIndex the first allowed index
++ * @param endIndex the last allowed index
++ * @throws IndexOutOfBoundsException if the index is invalid
++ */
++ private void checkInterval(int index, int startIndex, int endIndex) {
++ if (index < startIndex || index > endIndex) {
++ throw new IndexOutOfBoundsException("Invalid index:" + index + ", size=" + size());
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Implements an AVLNode which keeps the offset updated.
++ * <p/>
++ * This node contains the real work.
++ * TreeList is just there to implement {@link java.util.List}.
++ * The nodes don't know the index of the object they are holding. They
++ * do know however their position relative to their parent node.
++ * This allows to calculate the index of a node while traversing the tree.
++ * <p/>
++ * The Faedelung calculation stores a flag for both the left and right child
++ * to indicate if they are a child (false) or a link as in linked list (true).
++ */
++ static class AVLNode <T> {
++ /**
++ * The left child node or the predecessor if {@link #leftIsPrevious}.
++ */
++ private AVLNode<T> left;
++ /**
++ * Flag indicating that left reference is not a subtree but the predecessor.
++ */
++ private boolean leftIsPrevious;
++ /**
++ * The right child node or the successor if {@link #rightIsNext}.
++ */
++ private AVLNode<T> right;
++ /**
++ * Flag indicating that right reference is not a subtree but the successor.
++ */
++ private boolean rightIsNext;
++ /**
++ * How many levels of left/right are below this one.
++ */
++ private int height;
++ /**
++ * The relative position, root holds absolute position.
++ */
++ private int relativePosition;
++ /**
++ * The stored element.
++ */
++ private T value;
++
++ /**
++ * Constructs a new node with a relative position.
++ *
++ * @param relativePosition the relative position of the node
++ * @param obj the value for the ndoe
++ * @param rightFollower the node with the value following this one
++ * @param leftFollower the node with the value leading this one
++ */
++ private AVLNode(int relativePosition, T obj, AVLNode<T> rightFollower, AVLNode<T> leftFollower) {
++ this.relativePosition = relativePosition;
++ value = obj;
++ rightIsNext = true;
++ leftIsPrevious = true;
++ right = rightFollower;
++ left = leftFollower;
++ }
++
++ /**
++ * Gets the value.
++ *
++ * @return the value of this node
++ */
++ T getValue() {
++ return value;
++ }
++
++ /**
++ * Sets the value.
++ *
++ * @param obj the value to store
++ */
++ void setValue(T obj) {
++ this.value = obj;
++ }
++
++ /**
++ * Locate the element with the given index relative to the
++ * offset of the parent of this node.
++ */
++ AVLNode<T> get(int index) {
++ int indexRelativeToMe = index - relativePosition;
++
++ if (indexRelativeToMe == 0) {
++ return this;
++ }
++
++ AVLNode<T> nextNode = ((indexRelativeToMe < 0) ? getLeftSubTree() : getRightSubTree());
++ if (nextNode == null) {
++ return null;
++ }
++ return nextNode.get(indexRelativeToMe);
++ }
++
++ /**
++ * Locate the index that contains the specified object.
++ */
++ int indexOf(T object, int index) {
++ if (getLeftSubTree() != null) {
++ int result = left.indexOf(object, index + left.relativePosition);
++ if (result != -1) {
++ return result;
++ }
++ }
++ if (value == null ? value == object : value.equals(object)) {
++ return index;
++ }
++ if (getRightSubTree() != null) {
++ return right.indexOf(object, index + right.relativePosition);
++ }
++ return -1;
++ }
++
++ /**
++ * Stores the node and its children into the array specified.
++ *
++ * @param array the array to be filled
++ * @param index the index of this node
++ */
++ void toArray(T[] array, int index) {
++ array[index] = value;
++ if (getLeftSubTree() != null) {
++ left.toArray(array, index + left.relativePosition);
++ }
++ if (getRightSubTree() != null) {
++ right.toArray(array, index + right.relativePosition);
++ }
++ }
++
++ /**
++ * Gets the next node in the list after this one.
++ *
++ * @return the next node
++ */
++ AVLNode<T> next() {
++ if (rightIsNext || right == null) {
++ return right;
++ }
++ return right.min();
++ }
++
++ /**
++ * Gets the node in the list before this one.
++ *
++ * @return the previous node
++ */
++ AVLNode<T> previous() {
++ if (leftIsPrevious || left == null) {
++ return left;
++ }
++ return left.max();
++ }
++
++ /**
++ * Inserts a node at the position index.
++ *
++ * @param index is the index of the position relative to the position of
++ * the parent node.
++ * @param obj is the object to be stored in the position.
++ */
++ AVLNode<T> insert(int index, T obj) {
++ int indexRelativeToMe = index - relativePosition;
++
++ if (indexRelativeToMe <= 0) {
++ return insertOnLeft(indexRelativeToMe, obj);
++ } else {
++ return insertOnRight(indexRelativeToMe, obj);
++ }
++ }
++
++ private AVLNode<T> insertOnLeft(int indexRelativeToMe, T obj) {
++ AVLNode<T> ret = this;
++
++ if (getLeftSubTree() == null) {
++ setLeft(new AVLNode<T>(-1, obj, this, left), null);
++ } else {
++ setLeft(left.insert(indexRelativeToMe, obj), null);
++ }
++
++ if (relativePosition >= 0) {
++ relativePosition++;
++ }
++ ret = balance();
++ recalcHeight();
++ return ret;
++ }
++
++ private AVLNode<T> insertOnRight(int indexRelativeToMe, T obj) {
++ AVLNode<T> ret = this;
++
++ if (getRightSubTree() == null) {
++ setRight(new AVLNode<T>(+1, obj, right, this), null);
++ } else {
++ setRight(right.insert(indexRelativeToMe, obj), null);
++ }
++ if (relativePosition < 0) {
++ relativePosition--;
++ }
++ ret = balance();
++ recalcHeight();
++ return ret;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the left node, returning null if its a faedelung.
++ */
++ private AVLNode<T> getLeftSubTree() {
++ return (leftIsPrevious ? null : left);
++ }
++
++ /**
++ * Gets the right node, returning null if its a faedelung.
++ */
++ private AVLNode<T> getRightSubTree() {
++ return (rightIsNext ? null : right);
++ }
++
++ /**
++ * Gets the rightmost child of this node.
++ *
++ * @return the rightmost child (greatest index)
++ */
++ private AVLNode<T> max() {
++ return (getRightSubTree() == null) ? this : right.max();
++ }
++
++ /**
++ * Gets the leftmost child of this node.
++ *
++ * @return the leftmost child (smallest index)
++ */
++ private AVLNode<T> min() {
++ return (getLeftSubTree() == null) ? this : left.min();
++ }
++
++ /**
++ * Removes the node at a given position.
++ *
++ * @param index is the index of the element to be removed relative to the position of
++ * the parent node of the current node.
++ */
++ AVLNode<T> remove(int index) {
++ int indexRelativeToMe = index - relativePosition;
++
++ if (indexRelativeToMe == 0) {
++ return removeSelf();
++ }
++ if (indexRelativeToMe > 0) {
++ setRight(right.remove(indexRelativeToMe), right.right);
++ if (relativePosition < 0) {
++ relativePosition++;
++ }
++ } else {
++ setLeft(left.remove(indexRelativeToMe), left.left);
++ if (relativePosition > 0) {
++ relativePosition--;
++ }
++ }
++ recalcHeight();
++ return balance();
++ }
++
++ private AVLNode<T> removeMax() {
++ if (getRightSubTree() == null) {
++ return removeSelf();
++ }
++ setRight(right.removeMax(), right.right);
++ if (relativePosition < 0) {
++ relativePosition++;
++ }
++ recalcHeight();
++ return balance();
++ }
++
++ private AVLNode<T> removeMin() {
++ if (getLeftSubTree() == null) {
++ return removeSelf();
++ }
++ setLeft(left.removeMin(), left.left);
++ if (relativePosition > 0) {
++ relativePosition--;
++ }
++ recalcHeight();
++ return balance();
++ }
++
++ private AVLNode<T> removeSelf() {
++ if (getRightSubTree() == null && getLeftSubTree() == null)
++ return null;
++ if (getRightSubTree() == null) {
++ if (relativePosition > 0) {
++ left.relativePosition += relativePosition + (relativePosition > 0 ? 0 : 1);
++ }
++ left.max().setRight(null, right);
++ return left;
++ }
++ if (getLeftSubTree() == null) {
++ right.relativePosition += relativePosition - (relativePosition < 0 ? 0 : 1);
++ right.min().setLeft(null, left);
++ return right;
++ }
++
++ if (heightRightMinusLeft() > 0) {
++ AVLNode<T> rightMin = right.min();
++ value = rightMin.value;
++ if (leftIsPrevious) {
++ left = rightMin.left;
++ }
++ right = right.removeMin();
++ if (relativePosition < 0) {
++ relativePosition++;
++ }
++ } else {
++ AVLNode<T> leftMax = left.max();
++ value = leftMax.value;
++ if (rightIsNext) {
++ right = leftMax.right;
++ }
++ left = left.removeMax();
++ if (relativePosition > 0) {
++ relativePosition--;
++ }
++ }
++ recalcHeight();
++ return this;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Balances according to the AVL algorithm.
++ */
++ private AVLNode<T> balance() {
++ switch (heightRightMinusLeft()) {
++ case 1:
++ case 0:
++ case -1:
++ return this;
++ case -2:
++ if (left.heightRightMinusLeft() > 0) {
++ setLeft(left.rotateLeft(), null);
++ }
++ return rotateRight();
++ case 2:
++ if (right.heightRightMinusLeft() < 0) {
++ setRight(right.rotateRight(), null);
++ }
++ return rotateLeft();
++ default :
++ throw new RuntimeException("tree inconsistent!");
++ }
++ }
++
++ /**
++ * Gets the relative position.
++ */
++ private int getOffset(AVLNode<T> node) {
++ if (node == null) {
++ return 0;
++ }
++ return node.relativePosition;
++ }
++
++ /**
++ * Sets the relative position.
++ */
++ private int setOffset(AVLNode<T> node, int newOffest) {
++ if (node == null) {
++ return 0;
++ }
++ int oldOffset = getOffset(node);
++ node.relativePosition = newOffest;
++ return oldOffset;
++ }
++
++ /**
++ * Sets the height by calculation.
++ */
++ private void recalcHeight() {
++ height = Math.max(getLeftSubTree() == null ? -1 : getLeftSubTree().height, getRightSubTree() == null ? -1 : getRightSubTree().height) + 1;
++ }
++
++ /**
++ * Returns the height of the node or -1 if the node is null.
++ */
++ private int getHeight(AVLNode<T> node) {
++ return (node == null ? -1 : node.height);
++ }
++
++ /**
++ * Returns the height difference right - left
++ */
++ private int heightRightMinusLeft() {
++ return getHeight(getRightSubTree()) - getHeight(getLeftSubTree());
++ }
++
++ private AVLNode<T> rotateLeft() {
++ AVLNode<T> newTop = right; // can't be faedelung!
++ AVLNode<T> movedNode = getRightSubTree().getLeftSubTree();
++
++ int newTopPosition = relativePosition + getOffset(newTop);
++ int myNewPosition = -newTop.relativePosition;
++ int movedPosition = getOffset(newTop) + getOffset(movedNode);
++
++ setRight(movedNode, newTop);
++ newTop.setLeft(this, null);
++
++ setOffset(newTop, newTopPosition);
++ setOffset(this, myNewPosition);
++ setOffset(movedNode, movedPosition);
++ return newTop;
++ }
++
++ private AVLNode<T> rotateRight() {
++ AVLNode<T> newTop = left; // can't be faedelung
++ AVLNode<T> movedNode = getLeftSubTree().getRightSubTree();
++
++ int newTopPosition = relativePosition + getOffset(newTop);
++ int myNewPosition = -newTop.relativePosition;
++ int movedPosition = getOffset(newTop) + getOffset(movedNode);
++
++ setLeft(movedNode, newTop);
++ newTop.setRight(this, null);
++
++ setOffset(newTop, newTopPosition);
++ setOffset(this, myNewPosition);
++ setOffset(movedNode, movedPosition);
++ return newTop;
++ }
++
++ private void setLeft(AVLNode<T> node, AVLNode<T> previous) {
++ leftIsPrevious = (node == null);
++ left = (leftIsPrevious ? previous : node);
++ recalcHeight();
++ }
++
++ private void setRight(AVLNode<T> node, AVLNode<T> next) {
++ rightIsNext = (node == null);
++ right = (rightIsNext ? next : node);
++ recalcHeight();
++ }
++
++ // private void checkFaedelung() {
++ // AVLNode maxNode = left.max();
++ // if (!maxNode.rightIsFaedelung || maxNode.right != this) {
++ // throw new RuntimeException(maxNode + " should right-faedel to " + this);
++ // }
++ // AVLNode minNode = right.min();
++ // if (!minNode.leftIsFaedelung || minNode.left != this) {
++ // throw new RuntimeException(maxNode + " should left-faedel to " + this);
++ // }
++ // }
++ //
++ // private int checkTreeDepth() {
++ // int hright = (getRightSubTree() == null ? -1 : getRightSubTree().checkTreeDepth());
++ // // System.out.print("checkTreeDepth");
++ // // System.out.print(this);
++ // // System.out.print(" left: ");
++ // // System.out.print(_left);
++ // // System.out.print(" right: ");
++ // // System.out.println(_right);
++ //
++ // int hleft = (left == null ? -1 : left.checkTreeDepth());
++ // if (height != Math.max(hright, hleft) + 1) {
++ // throw new RuntimeException(
++ // "height should be max" + hleft + "," + hright + " but is " + height);
++ // }
++ // return height;
++ // }
++ //
++ // private int checkLeftSubNode() {
++ // if (getLeftSubTree() == null) {
++ // return 0;
++ // }
++ // int count = 1 + left.checkRightSubNode();
++ // if (left.relativePosition != -count) {
++ // throw new RuntimeException();
++ // }
++ // return count + left.checkLeftSubNode();
++ // }
++ //
++ // private int checkRightSubNode() {
++ // AVLNode right = getRightSubTree();
++ // if (right == null) {
++ // return 0;
++ // }
++ // int count = 1;
++ // count += right.checkLeftSubNode();
++ // if (right.relativePosition != count) {
++ // throw new RuntimeException();
++ // }
++ // return count + right.checkRightSubNode();
++ // }
++
++ /**
++ * Used for debugging.
++ */
++ public String toString() {
++ return "AVLNode(" + relativePosition + "," + (left != null) + "," + value + "," + (getRightSubTree() != null) + ", faedelung " + rightIsNext + " )";
++ }
++ }
++
++ /**
++ * A list iterator over the linked list.
++ */
++ static class TreeListIterator <E> implements ListIterator<E>, OrderedIterator<E> {
++ /**
++ * The parent list
++ */
++ protected final TreeList<E> parent;
++ /**
++ * The node that will be returned by {@link #next()}. If this is equal
++ * to {@link AbstractLinkedList#header} then there are no more values to return.
++ */
++ protected AVLNode<E> next;
++ /**
++ * The index of {@link #next}.
++ */
++ protected int nextIndex;
++ /**
++ * The last node that was returned by {@link #next()} or {@link
++ * #previous()}. Set to <code>null</code> if {@link #next()} or {@link
++ * #previous()} haven't been called, or if the node has been removed
++ * with {@link #remove()} or a new node added with {@link #add(Object)}.
++ * Should be accessed through {@link #getLastNodeReturned()} to enforce
++ * this behaviour.
++ */
++ protected AVLNode<E> current;
++ /**
++ * The index of {@link #current}.
++ */
++ protected int currentIndex;
++ /**
++ * The modification count that the list is expected to have. If the list
++ * doesn't have this count, then a
++ * {@link java.util.ConcurrentModificationException} may be thrown by
++ * the operations.
++ */
++ protected int expectedModCount;
++
++ /**
++ * Create a ListIterator for a list.
++ *
++ * @param parent the parent list
++ * @param fromIndex the index to start at
++ */
++ protected TreeListIterator(TreeList<E> parent, int fromIndex) throws IndexOutOfBoundsException {
++ super();
++ this.parent = parent;
++ this.expectedModCount = parent.modCount;
++ this.next = (parent.root == null ? null : parent.root.get(fromIndex));
++ this.nextIndex = fromIndex;
++ }
++
++ /**
++ * Checks the modification count of the list is the value that this
++ * object expects.
++ *
++ * @throws ConcurrentModificationException
++ * If the list's modification
++ * count isn't the value that was expected.
++ */
++ protected void checkModCount() {
++ if (parent.modCount != expectedModCount) {
++ throw new ConcurrentModificationException();
++ }
++ }
++
++ public boolean hasNext() {
++ return (nextIndex < parent.size());
++ }
++
++ public E next() {
++ checkModCount();
++ if (!hasNext()) {
++ throw new NoSuchElementException("No element at index " + nextIndex + ".");
++ }
++ if (next == null) {
++ next = parent.root.get(nextIndex);
++ }
++ E value = next.getValue();
++ current = next;
++ currentIndex = nextIndex++;
++ next = next.next();
++ return value;
++ }
++
++ public boolean hasPrevious() {
++ return (nextIndex > 0);
++ }
++
++ public E previous() {
++ checkModCount();
++ if (!hasPrevious()) {
++ throw new NoSuchElementException("Already at start of list.");
++ }
++ if (next == null) {
++ next = parent.root.get(nextIndex - 1);
++ } else {
++ next = next.previous();
++ }
++ E value = next.getValue();
++ current = next;
++ currentIndex = --nextIndex;
++ return value;
++ }
++
++ public int nextIndex() {
++ return nextIndex;
++ }
++
++ public int previousIndex() {
++ return nextIndex() - 1;
++ }
++
++ public void remove() {
++ checkModCount();
++ if (current == null) {
++ throw new IllegalStateException();
++ }
++ parent.remove(currentIndex);
++ current = null;
++ currentIndex = -1;
++ nextIndex--;
++ expectedModCount++;
++ }
++
++ public void set(E obj) {
++ checkModCount();
++ if (current == null) {
++ throw new IllegalStateException();
++ }
++ current.setValue(obj);
++ }
++
++ public void add(E obj) {
++ checkModCount();
++ parent.add(nextIndex, obj);
++ current = null;
++ currentIndex = -1;
++ nextIndex++;
++ expectedModCount++;
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/TypedList.java
+@@ -0,0 +1,60 @@
++// GenericsNote: deprecated and useless
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import org.apache.commons.collections15.functors.InstanceofPredicate;
++
++import java.util.List;
++
++/**
++ * Decorates another <code>List</code> to validate that elements
++ * added are of a specific type.
++ * <p/>
++ * The validation of additions is performed via an instanceof test against
++ * a specified <code>Class</code>. If an object cannot be added to the
++ * collection, an IllegalArgumentException is thrown.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Matthew Hawthorne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ * @deprecated Java Generics makes this class obsolete.
++ */
++public class TypedList {
++
++ /**
++ * Factory method to create a typed list.
++ * <p/>
++ * If there are any elements already in the list being decorated, they
++ * are validated.
++ *
++ * @param list the list to decorate, must not be null
++ * @param type the type to allow into the collection, must not be null
++ * @throws IllegalArgumentException if list or type is null
++ * @throws IllegalArgumentException if the list contains invalid elements
++ */
++ public static List decorate(List list, Class type) {
++ return new PredicatedList(list, InstanceofPredicate.getInstance(type));
++ }
++
++ /**
++ * Restrictive constructor.
++ */
++ protected TypedList() {
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/UnmodifiableList.java
+@@ -0,0 +1,127 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.list;
++
++import org.apache.commons.collections15.Unmodifiable;
++import org.apache.commons.collections15.iterators.UnmodifiableIterator;
++import org.apache.commons.collections15.iterators.UnmodifiableListIterator;
++
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.List;
++import java.util.ListIterator;
++
++/**
++ * Decorates another <code>List</code> to ensure it can't be altered.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableList <E> extends AbstractSerializableListDecorator<E> implements Unmodifiable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 6595182819922443652L;
++
++ /**
++ * Factory method to create an unmodifiable list.
++ *
++ * @param list the list to decorate, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ public static <E> List<E> decorate(List<E> list) {
++ if (list instanceof Unmodifiable) {
++ return list;
++ }
++ return new UnmodifiableList<E>(list);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param list the list to decorate, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ private UnmodifiableList(List<E> list) {
++ super(list);
++ }
++
++ //-----------------------------------------------------------------------
++ public Iterator<E> iterator() {
++ return UnmodifiableIterator.decorate(getCollection().iterator());
++ }
++
++ public boolean add(E object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean remove(Object object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ //-----------------------------------------------------------------------
++ public ListIterator<E> listIterator() {
++ return UnmodifiableListIterator.decorate(getList().listIterator());
++ }
++
++ public ListIterator<E> listIterator(int index) {
++ return UnmodifiableListIterator.decorate(getList().listIterator(index));
++ }
++
++ public void add(int index, E object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean addAll(int index, Collection<? extends E> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public E remove(int index) {
++ throw new UnsupportedOperationException();
++ }
++
++ public E set(int index, E object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public List<E> subList(int fromIndex, int toIndex) {
++ List<E> sub = getList().subList(fromIndex, toIndex);
++ return new UnmodifiableList<E>(sub);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/list/package.html
+@@ -0,0 +1,41 @@
++<!-- $Id: package.html,v 1.1 2005/10/11 17:05:32 pents90 Exp $ -->
++ <!--
++ Copyright 2003-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<BODY>
++<p>
++This package contains implementations of the
++{@link java.util.List List} interface.
++<p>
++The following implementations are provided in the package:
++<ul>
++<li>TreeList - a list that is optimised for insertions and removals at any index in the list
++<li>CursorableLinkedList - a list that can be modified while it's listIterator (cursor) is being used
++<li>NodeCachingLinkedList - a linked list that caches the storage nodes for a performance gain
++</ul>
++<p>
++The following decorators are provided in the package:
++<ul>
++<li>Synchronized - synchronizes method access for multi-threaded environments
++<li>Unmodifiable - ensures the collection cannot be altered
++<li>Predicated - ensures that only elements that are valid according to a predicate can be added
++<li>Typed - ensures that only elements that are of a specific type can be added
++<li>Transformed - transforms each element added
++<li>FixedSize - ensures that the size of the list cannot change
++<li>Lazy - creates objects in the list on demand
++<li>SetUnique - a list that avoids duplicate entries like a Set
++</ul>
++</pre>
++</BODY>
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/AbstractHashedMap.java
+@@ -0,0 +1,1344 @@
++// GenericsNote: Converted -- However, null keys will now be represented in the internal structures, a big change.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.IterableMap;
++import org.apache.commons.collections15.KeyValue;
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.iterators.EmptyIterator;
++import org.apache.commons.collections15.iterators.EmptyMapIterator;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.util.*;
++
++/**
++ * An abstract implementation of a hash-based map which provides numerous points for
++ * subclasses to override.
++ * <p/>
++ * This class implements all the features necessary for a subclass hash-based map.
++ * Key-value entries are stored in instances of the <code>HashEntry</code> class,
++ * which can be overridden and replaced. The iterators can similarly be replaced,
++ * without the need to replace the KeySet, EntrySet and Values view classes.
++ * <p/>
++ * Overridable methods are provided to change the default hashing behaviour, and
++ * to change how entries are added to and removed from the map. Hopefully, all you
++ * need for unusual subclasses is here.
++ * <p/>
++ * NOTE: From Commons Collections 3.1 this class extends AbstractMap.
++ * This is to provide backwards compatibility for ReferenceMap between v3.0 and v3.1.
++ * This extends clause will be removed in v4.0.
++ *
++ * @author java util HashMap
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class AbstractHashedMap <K,V> extends AbstractMap<K, V> implements IterableMap<K, V> {
++
++ protected static final String NO_NEXT_ENTRY = "No next() entry in the iteration";
++ protected static final String NO_PREVIOUS_ENTRY = "No previous() entry in the iteration";
++ protected static final String REMOVE_INVALID = "remove() can only be called once after next()";
++ protected static final String GETKEY_INVALID = "getKey() can only be called after next() and before remove()";
++ protected static final String GETVALUE_INVALID = "getValue() can only be called after next() and before remove()";
++ protected static final String SETVALUE_INVALID = "setValue() can only be called after next() and before remove()";
++
++ /**
++ * The default capacity to use
++ */
++ protected static final int DEFAULT_CAPACITY = 16;
++ /**
++ * The default threshold to use
++ */
++ protected static final int DEFAULT_THRESHOLD = 12;
++ /**
++ * The default load factor to use
++ */
++ protected static final float DEFAULT_LOAD_FACTOR = 0.75f;
++ /**
++ * The maximum capacity allowed
++ */
++ protected static final int MAXIMUM_CAPACITY = 1 << 30;
++ /**
++ * An object for masking null
++ */
++ protected static final Object NULL = new Object();
++
++ /**
++ * Load factor, normally 0.75
++ */
++ protected transient float loadFactor;
++ /**
++ * The size of the map
++ */
++ protected transient int size;
++ /**
++ * Map entries
++ */
++ protected transient HashEntry<K, V>[] data;
++ /**
++ * Size at which to rehash
++ */
++ protected transient int threshold;
++ /**
++ * Modification count for iterators
++ */
++ protected transient int modCount;
++ /**
++ * Entry set
++ */
++ protected transient EntrySet<K, V> entrySet;
++ /**
++ * Key set
++ */
++ protected transient KeySet<K, V> keySet;
++ /**
++ * Values
++ */
++ protected transient Values<K, V> values;
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ */
++ protected AbstractHashedMap() {
++ super();
++ }
++
++ /**
++ * Constructor which performs no validation on the passed in parameters.
++ *
++ * @param initialCapacity the initial capacity, must be a power of two
++ * @param loadFactor the load factor, must be > 0.0f and generally < 1.0f
++ * @param threshold the threshold, must be sensible
++ */
++ protected AbstractHashedMap(int initialCapacity, float loadFactor, int threshold) {
++ super();
++ this.loadFactor = loadFactor;
++ this.data = new HashEntry[initialCapacity];
++ this.threshold = threshold;
++ init();
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity and
++ * default load factor.
++ *
++ * @param initialCapacity the initial capacity
++ * @throws IllegalArgumentException if the initial capacity is less than one
++ */
++ protected AbstractHashedMap(int initialCapacity) {
++ this(initialCapacity, DEFAULT_LOAD_FACTOR);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity and
++ * load factor.
++ *
++ * @param initialCapacity the initial capacity
++ * @param loadFactor the load factor
++ * @throws IllegalArgumentException if the initial capacity is less than one
++ * @throws IllegalArgumentException if the load factor is less than or equal to zero
++ */
++ protected AbstractHashedMap(int initialCapacity, float loadFactor) {
++ super();
++ if (initialCapacity < 1) {
++ throw new IllegalArgumentException("Initial capacity must be greater than 0");
++ }
++ if (loadFactor <= 0.0f || Float.isNaN(loadFactor)) {
++ throw new IllegalArgumentException("Load factor must be greater than 0");
++ }
++ this.loadFactor = loadFactor;
++ this.threshold = calculateThreshold(initialCapacity, loadFactor);
++ initialCapacity = calculateNewCapacity(initialCapacity);
++ this.data = new HashEntry[initialCapacity];
++ init();
++ }
++
++ /**
++ * Constructor copying elements from another map.
++ *
++ * @param map the map to copy
++ * @throws NullPointerException if the map is null
++ */
++ protected AbstractHashedMap(Map<? extends K, ? extends V> map) {
++ this(Math.max(2 * map.size(), DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR);
++ putAll(map);
++ }
++
++ /**
++ * Initialise subclasses during construction, cloning or deserialization.
++ */
++ protected void init() {
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the value mapped to the key specified.
++ *
++ * @param key the key
++ * @return the mapped value, null if no match
++ */
++ public V get(Object key) {
++ int hashCode = hash((key == null) ? NULL : key);
++ HashEntry<K, V> entry = data[hashIndex(hashCode, data.length)]; // no local for hash index
++ while (entry != null) {
++ if (entry.hashCode == hashCode && isEqualKey(key, entry.key)) {
++ return entry.getValue();
++ }
++ entry = entry.next;
++ }
++ return null;
++ }
++
++ /**
++ * Gets the size of the map.
++ *
++ * @return the size
++ */
++ public int size() {
++ return size;
++ }
++
++ /**
++ * Checks whether the map is currently empty.
++ *
++ * @return true if the map is currently size zero
++ */
++ public boolean isEmpty() {
++ return (size == 0);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Checks whether the map contains the specified key.
++ *
++ * @param key the key to search for
++ * @return true if the map contains the key
++ */
++ public boolean containsKey(Object key) {
++ int hashCode = hash((key == null) ? NULL : key);
++ HashEntry entry = data[hashIndex(hashCode, data.length)]; // no local for hash index
++ while (entry != null) {
++ if (entry.hashCode == hashCode && isEqualKey(key, entry.getKey())) {
++ return true;
++ }
++ entry = entry.next;
++ }
++ return false;
++ }
++
++ /**
++ * Checks whether the map contains the specified value.
++ *
++ * @param value the value to search for
++ * @return true if the map contains the value
++ */
++ public boolean containsValue(Object value) {
++ if (value == null) {
++ for (int i = 0, isize = data.length; i < isize; i++) {
++ HashEntry entry = data[i];
++ while (entry != null) {
++ if (entry.getValue() == null) {
++ return true;
++ }
++ entry = entry.next;
++ }
++ }
++ } else {
++ for (int i = 0, isize = data.length; i < isize; i++) {
++ HashEntry entry = data[i];
++ while (entry != null) {
++ if (isEqualValue(value, entry.getValue())) {
++ return true;
++ }
++ entry = entry.next;
++ }
++ }
++ }
++ return false;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Puts a key-value mapping into this map.
++ *
++ * @param key the key to add
++ * @param value the value to add
++ * @return the value previously mapped to this key, null if none
++ */
++ public V put(K key, V value) {
++ int hashCode = hash((key == null) ? NULL : key);
++ int index = hashIndex(hashCode, data.length);
++ HashEntry<K, V> entry = data[index];
++ while (entry != null) {
++ if (entry.hashCode == hashCode && isEqualKey(key, entry.getKey())) {
++ V oldValue = entry.getValue();
++ updateEntry(entry, value);
++ return oldValue;
++ }
++ entry = entry.next;
++ }
++ addMapping(index, hashCode, key, value);
++ return null;
++ }
++
++ /**
++ * Puts all the values from the specified map into this map.
++ * <p/>
++ * This implementation iterates around the specified map and
++ * uses {@link #put(Object, Object)}.
++ *
++ * @param map the map to add
++ * @throws NullPointerException if the map is null
++ */
++ public void putAll(Map<? extends K, ? extends V> map) {
++ int mapSize = map.size();
++ if (mapSize == 0) {
++ return;
++ }
++ int newSize = (int) ((size + mapSize) / loadFactor + 1);
++ ensureCapacity(calculateNewCapacity(newSize));
++ // Have to cast here because of compiler inference problems.
++ for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
++ Map.Entry<? extends K, ? extends V> entry = (Map.Entry<? extends K, ? extends V>) it.next();
++ put(entry.getKey(), entry.getValue());
++ }
++ }
++
++ /**
++ * Removes the specified mapping from this map.
++ *
++ * @param key the mapping to remove
++ * @return the value mapped to the removed key, null if key not in map
++ */
++ public V remove(Object key) {
++ int hashCode = hash((key == null) ? NULL : key);
++ int index = hashIndex(hashCode, data.length);
++ HashEntry<K, V> entry = data[index];
++ HashEntry<K, V> previous = null;
++ while (entry != null) {
++ if (entry.hashCode == hashCode && isEqualKey(key, entry.getKey())) {
++ V oldValue = entry.getValue();
++ removeMapping(entry, index, previous);
++ return oldValue;
++ }
++ previous = entry;
++ entry = entry.next;
++ }
++ return null;
++ }
++
++ /**
++ * Clears the map, resetting the size to zero and nullifying references
++ * to avoid garbage collection issues.
++ */
++ public void clear() {
++ modCount++;
++ HashEntry[] data = this.data;
++ for (int i = data.length - 1; i >= 0; i--) {
++ data[i] = null;
++ }
++ size = 0;
++ }
++
++ /**
++ * Gets the hash code for the key specified.
++ * This implementation uses the additional hashing routine from JDK1.4.
++ * Subclasses can override this to return alternate hash codes.
++ *
++ * @param key the key to get a hash code for
++ * @return the hash code
++ */
++ protected int hash(Object key) {
++ // same as JDK 1.4
++ int h = key.hashCode();
++ h += ~(h << 9);
++ h ^= (h >>> 14);
++ h += (h << 4);
++ h ^= (h >>> 10);
++ return h;
++ }
++
++ /**
++ * Compares two keys, in internal converted form, to see if they are equal.
++ * This implementation uses the equals method.
++ * Subclasses can override this to match differently.
++ *
++ * @param key1 the first key to compare passed in from outside
++ * @param key2 the second key extracted from the entry via <code>entry.key</code>
++ * @return true if equal
++ */
++ protected boolean isEqualKey(Object key1, Object key2) {
++ return (key1 == key2 || ((key1 != null) && key1.equals(key2)));
++ }
++
++ /**
++ * Compares two values, in external form, to see if they are equal.
++ * This implementation uses the equals method and assumes neither value is null.
++ * Subclasses can override this to match differently.
++ *
++ * @param value1 the first value to compare passed in from outside
++ * @param value2 the second value extracted from the entry via <code>getValue()</code>
++ * @return true if equal
++ */
++ protected boolean isEqualValue(Object value1, Object value2) {
++ return (value1 == value2 || value1.equals(value2));
++ }
++
++ /**
++ * Gets the index into the data storage for the hashCode specified.
++ * This implementation uses the least significant bits of the hashCode.
++ * Subclasses can override this to return alternate bucketing.
++ *
++ * @param hashCode the hash code to use
++ * @param dataSize the size of the data to pick a bucket from
++ * @return the bucket index
++ */
++ protected int hashIndex(int hashCode, int dataSize) {
++ return hashCode & (dataSize - 1);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the entry mapped to the key specified.
++ * <p/>
++ * This method exists for subclasses that may need to perform a multi-step
++ * process accessing the entry. The public methods in this class don't use this
++ * method to gain a small performance boost.
++ *
++ * @param key the key
++ * @return the entry, null if no match
++ */
++ protected HashEntry<K, V> getEntry(Object key) {
++ int hashCode = hash((key == null) ? NULL : key);
++ HashEntry<K, V> entry = data[hashIndex(hashCode, data.length)]; // no local for hash index
++ while (entry != null) {
++ if (entry.hashCode == hashCode && isEqualKey(key, entry.getKey())) {
++ return entry;
++ }
++ entry = entry.next;
++ }
++ return null;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Updates an existing key-value mapping to change the value.
++ * <p/>
++ * This implementation calls <code>setValue()</code> on the entry.
++ * Subclasses could override to handle changes to the map.
++ *
++ * @param entry the entry to update
++ * @param newValue the new value to store
++ */
++ protected void updateEntry(HashEntry<K, V> entry, V newValue) {
++ entry.setValue(newValue);
++ }
++
++ /**
++ * Reuses an existing key-value mapping, storing completely new data.
++ * <p/>
++ * This implementation sets all the data fields on the entry.
++ * Subclasses could populate additional entry fields.
++ *
++ * @param entry the entry to update, not null
++ * @param hashIndex the index in the data array
++ * @param hashCode the hash code of the key to add
++ * @param key the key to add
++ * @param value the value to add
++ */
++ protected void reuseEntry(HashEntry<K, V> entry, int hashIndex, int hashCode, K key, V value) {
++ entry.next = data[hashIndex];
++ entry.hashCode = hashCode;
++ entry.key = key;
++ entry.value = value;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Adds a new key-value mapping into this map.
++ * <p/>
++ * This implementation calls <code>createEntry()</code>, <code>addEntry()</code>
++ * and <code>checkCapacity()</code>.
++ * It also handles changes to <code>modCount</code> and <code>size</code>.
++ * Subclasses could override to fully control adds to the map.
++ *
++ * @param hashIndex the index into the data array to store at
++ * @param hashCode the hash code of the key to add
++ * @param key the key to add
++ * @param value the value to add
++ */
++ protected void addMapping(int hashIndex, int hashCode, K key, V value) {
++ modCount++;
++ HashEntry<K, V> entry = createEntry(data[hashIndex], hashCode, key, value);
++ addEntry(entry, hashIndex);
++ size++;
++ checkCapacity();
++ }
++
++ /**
++ * Creates an entry to store the key-value data.
++ * <p/>
++ * This implementation creates a new HashEntry instance.
++ * Subclasses can override this to return a different storage class,
++ * or implement caching.
++ *
++ * @param next the next entry in sequence
++ * @param hashCode the hash code to use
++ * @param key the key to store
++ * @param value the value to store
++ * @return the newly created entry
++ */
++ protected HashEntry<K, V> createEntry(HashEntry<K, V> next, int hashCode, K key, V value) {
++ return new HashEntry<K, V>(next, hashCode, key, value);
++ }
++
++ /**
++ * Adds an entry into this map.
++ * <p/>
++ * This implementation adds the entry to the data storage table.
++ * Subclasses could override to handle changes to the map.
++ *
++ * @param entry the entry to add
++ * @param hashIndex the index into the data array to store at
++ */
++ protected void addEntry(HashEntry<K, V> entry, int hashIndex) {
++ data[hashIndex] = entry;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Removes a mapping from the map.
++ * <p/>
++ * This implementation calls <code>removeEntry()</code> and <code>destroyEntry()</code>.
++ * It also handles changes to <code>modCount</code> and <code>size</code>.
++ * Subclasses could override to fully control removals from the map.
++ *
++ * @param entry the entry to remove
++ * @param hashIndex the index into the data structure
++ * @param previous the previous entry in the chain
++ */
++ protected void removeMapping(HashEntry<K, V> entry, int hashIndex, HashEntry<K, V> previous) {
++ modCount++;
++ removeEntry(entry, hashIndex, previous);
++ size--;
++ destroyEntry(entry);
++ }
++
++ /**
++ * Removes an entry from the chain stored in a particular index.
++ * <p/>
++ * This implementation removes the entry from the data storage table.
++ * The size is not updated.
++ * Subclasses could override to handle changes to the map.
++ *
++ * @param entry the entry to remove
++ * @param hashIndex the index into the data structure
++ * @param previous the previous entry in the chain
++ */
++ protected void removeEntry(HashEntry<K, V> entry, int hashIndex, HashEntry<K, V> previous) {
++ if (previous == null) {
++ data[hashIndex] = entry.next;
++ } else {
++ previous.next = entry.next;
++ }
++ }
++
++ /**
++ * Kills an entry ready for the garbage collector.
++ * <p/>
++ * This implementation prepares the HashEntry for garbage collection.
++ * Subclasses can override this to implement caching (override clear as well).
++ *
++ * @param entry the entry to destroy
++ */
++ protected void destroyEntry(HashEntry<K, V> entry) {
++ entry.next = null;
++ entry.key = null;
++ entry.value = null;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Checks the capacity of the map and enlarges it if necessary.
++ * <p/>
++ * This implementation uses the threshold to check if the map needs enlarging
++ */
++ protected void checkCapacity() {
++ if (size >= threshold) {
++ int newCapacity = data.length * 2;
++ if (newCapacity <= MAXIMUM_CAPACITY) {
++ ensureCapacity(newCapacity);
++ }
++ }
++ }
++
++ /**
++ * Changes the size of the data structure to the capacity proposed.
++ *
++ * @param newCapacity the new capacity of the array (a power of two, less or equal to max)
++ */
++ protected void ensureCapacity(int newCapacity) {
++ int oldCapacity = data.length;
++ if (newCapacity <= oldCapacity) {
++ return;
++ }
++ if (size == 0) {
++ threshold = calculateThreshold(newCapacity, loadFactor);
++ data = new HashEntry[newCapacity];
++ } else {
++ HashEntry<K, V> oldEntries[] = data;
++ HashEntry<K, V> newEntries[] = new HashEntry[newCapacity];
++
++ modCount++;
++ for (int i = oldCapacity - 1; i >= 0; i--) {
++ HashEntry<K, V> entry = oldEntries[i];
++ if (entry != null) {
++ oldEntries[i] = null; // gc
++ do {
++ HashEntry<K, V> next = entry.next;
++ int index = hashIndex(entry.hashCode, newCapacity);
++ entry.next = newEntries[index];
++ newEntries[index] = entry;
++ entry = next;
++ } while (entry != null);
++ }
++ }
++ threshold = calculateThreshold(newCapacity, loadFactor);
++ data = newEntries;
++ }
++ }
++
++ /**
++ * Calculates the new capacity of the map.
++ * This implementation normalizes the capacity to a power of two.
++ *
++ * @param proposedCapacity the proposed capacity
++ * @return the normalized new capacity
++ */
++ protected int calculateNewCapacity(int proposedCapacity) {
++ int newCapacity = 1;
++ if (proposedCapacity > MAXIMUM_CAPACITY) {
++ newCapacity = MAXIMUM_CAPACITY;
++ } else {
++ while (newCapacity < proposedCapacity) {
++ newCapacity <<= 1; // multiply by two
++ }
++ if (newCapacity > MAXIMUM_CAPACITY) {
++ newCapacity = MAXIMUM_CAPACITY;
++ }
++ }
++ return newCapacity;
++ }
++
++ /**
++ * Calculates the new threshold of the map, where it will be resized.
++ * This implementation uses the load factor.
++ *
++ * @param newCapacity the new capacity
++ * @param factor the load factor
++ * @return the new resize threshold
++ */
++ protected int calculateThreshold(int newCapacity, float factor) {
++ return (int) (newCapacity * factor);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the <code>next</code> field from a <code>HashEntry</code>.
++ * Used in subclasses that have no visibility of the field.
++ *
++ * @param entry the entry to query, must not be null
++ * @return the <code>next</code> field of the entry
++ * @throws NullPointerException if the entry is null
++ * @since Commons Collections 3.1
++ */
++ protected HashEntry<K, V> entryNext(HashEntry<K, V> entry) {
++ return entry.next;
++ }
++
++ /**
++ * Gets the <code>hashCode</code> field from a <code>HashEntry</code>.
++ * Used in subclasses that have no visibility of the field.
++ *
++ * @param entry the entry to query, must not be null
++ * @return the <code>hashCode</code> field of the entry
++ * @throws NullPointerException if the entry is null
++ * @since Commons Collections 3.1
++ */
++ protected int entryHashCode(HashEntry<K, V> entry) {
++ return entry.hashCode;
++ }
++
++ /**
++ * Gets the <code>key</code> field from a <code>HashEntry</code>.
++ * Used in subclasses that have no visibility of the field.
++ *
++ * @param entry the entry to query, must not be null
++ * @return the <code>key</code> field of the entry
++ * @throws NullPointerException if the entry is null
++ * @since Commons Collections 3.1
++ */
++ protected K entryKey(HashEntry<K, V> entry) {
++ return entry.key;
++ }
++
++ /**
++ * Gets the <code>value</code> field from a <code>HashEntry</code>.
++ * Used in subclasses that have no visibility of the field.
++ *
++ * @param entry the entry to query, must not be null
++ * @return the <code>value</code> field of the entry
++ * @throws NullPointerException if the entry is null
++ * @since Commons Collections 3.1
++ */
++ protected V entryValue(HashEntry<K, V> entry) {
++ return entry.value;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator over the map.
++ * Changes made to the iterator affect this map.
++ * <p/>
++ * A MapIterator returns the keys in the map. It also provides convenient
++ * methods to get the key and value, and set the value.
++ * It avoids the need to create an entrySet/keySet/values object.
++ * It also avoids creating the Map.Entry object.
++ *
++ * @return the map iterator
++ */
++ public MapIterator<K, V> mapIterator() {
++ if (size == 0) {
++ return EmptyMapIterator.INSTANCE;
++ }
++ return new HashMapIterator<K, V>(this);
++ }
++
++ /**
++ * MapIterator implementation.
++ */
++ protected static class HashMapIterator <K,V> extends HashIterator<K, V> implements MapIterator<K, V> {
++
++ protected HashMapIterator(AbstractHashedMap<K, V> parent) {
++ super(parent);
++ }
++
++ public K next() {
++ return super.nextEntry().getKey();
++ }
++
++ public K getKey() {
++ HashEntry<K, V> current = currentEntry();
++ if (current == null) {
++ throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
++ }
++ return current.getKey();
++ }
++
++ public V getValue() {
++ HashEntry<K, V> current = currentEntry();
++ if (current == null) {
++ throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
++ }
++ return current.getValue();
++ }
++
++ public V setValue(V value) {
++ HashEntry<K, V> current = currentEntry();
++ if (current == null) {
++ throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
++ }
++ return current.setValue(value);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the entrySet view of the map.
++ * Changes made to the view affect this map.
++ * To simply iterate through the entries, use {@link #mapIterator()}.
++ *
++ * @return the entrySet view
++ */
++ public Set<Map.Entry<K, V>> entrySet() {
++ if (entrySet == null) {
++ entrySet = new EntrySet<K, V>(this);
++ }
++ return entrySet;
++ }
++
++ /**
++ * Creates an entry set iterator.
++ * Subclasses can override this to return iterators with different properties.
++ *
++ * @return the entrySet iterator
++ */
++ protected Iterator<Map.Entry<K, V>> createEntrySetIterator() {
++ if (size() == 0) {
++ return EmptyIterator.INSTANCE;
++ }
++ return new EntrySetIterator<K, V>(this);
++ }
++
++ /**
++ * EntrySet implementation.
++ */
++ protected static class EntrySet <K,V> extends AbstractSet<Map.Entry<K, V>> {
++ /**
++ * The parent map
++ */
++ protected final AbstractHashedMap<K, V> parent;
++
++ protected EntrySet(AbstractHashedMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ }
++
++ public int size() {
++ return parent.size();
++ }
++
++ public void clear() {
++ parent.clear();
++ }
++
++ public boolean contains(Map.Entry<K, V> entry) {
++ Map.Entry<K, V> e = entry;
++ Entry<K, V> match = parent.getEntry(e.getKey());
++ return (match != null && match.equals(e));
++ }
++
++ public boolean remove(Object obj) {
++ if (obj instanceof Map.Entry == false) {
++ return false;
++ }
++ if (contains(obj) == false) {
++ return false;
++ }
++ Map.Entry<K, V> entry = (Map.Entry<K, V>) obj;
++ K key = entry.getKey();
++ parent.remove(key);
++ return true;
++ }
++
++ public Iterator<Map.Entry<K, V>> iterator() {
++ return parent.createEntrySetIterator();
++ }
++ }
++
++ /**
++ * EntrySet iterator.
++ */
++ protected static class EntrySetIterator <K,V> extends HashIterator<K, V> implements Iterator<Map.Entry<K, V>> {
++
++ protected EntrySetIterator(AbstractHashedMap<K, V> parent) {
++ super(parent);
++ }
++
++ public HashEntry<K, V> next() {
++ return super.nextEntry();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the keySet view of the map.
++ * Changes made to the view affect this map.
++ * To simply iterate through the keys, use {@link #mapIterator()}.
++ *
++ * @return the keySet view
++ */
++ public Set<K> keySet() {
++ if (keySet == null) {
++ keySet = new KeySet<K, V>(this);
++ }
++ return keySet;
++ }
++
++ /**
++ * Creates a key set iterator.
++ * Subclasses can override this to return iterators with different properties.
++ *
++ * @return the keySet iterator
++ */
++ protected Iterator<K> createKeySetIterator() {
++ if (size() == 0) {
++ return EmptyIterator.INSTANCE;
++ }
++ return new KeySetIterator<K, V>(this);
++ }
++
++ /**
++ * KeySet implementation.
++ */
++ protected static class KeySet <K,V> extends AbstractSet<K> {
++ /**
++ * The parent map
++ */
++ protected final AbstractHashedMap<K, V> parent;
++
++ protected KeySet(AbstractHashedMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ }
++
++ public int size() {
++ return parent.size();
++ }
++
++ public void clear() {
++ parent.clear();
++ }
++
++ public boolean contains(Object key) {
++ return parent.containsKey(key);
++ }
++
++ public boolean remove(Object key) {
++ boolean result = parent.containsKey(key);
++ parent.remove(key);
++ return result;
++ }
++
++ public Iterator<K> iterator() {
++ return parent.createKeySetIterator();
++ }
++ }
++
++ /**
++ * KeySet iterator.
++ */
++ protected static class KeySetIterator <K,V> extends HashIterator<K, V> implements Iterator<K> {
++
++ protected KeySetIterator(AbstractHashedMap<K, V> parent) {
++ super(parent);
++ }
++
++ public K next() {
++ return super.nextEntry().getKey();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the values view of the map.
++ * Changes made to the view affect this map.
++ * To simply iterate through the values, use {@link #mapIterator()}.
++ *
++ * @return the values view
++ */
++ public Collection<V> values() {
++ if (values == null) {
++ values = new Values(this);
++ }
++ return values;
++ }
++
++ /**
++ * Creates a values iterator.
++ * Subclasses can override this to return iterators with different properties.
++ *
++ * @return the values iterator
++ */
++ protected Iterator<V> createValuesIterator() {
++ if (size() == 0) {
++ return EmptyIterator.INSTANCE;
++ }
++ return new ValuesIterator<K, V>(this);
++ }
++
++ /**
++ * Values implementation.
++ */
++ protected static class Values <K,V> extends AbstractCollection<V> {
++ /**
++ * The parent map
++ */
++ protected final AbstractHashedMap<K, V> parent;
++
++ protected Values(AbstractHashedMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ }
++
++ public int size() {
++ return parent.size();
++ }
++
++ public void clear() {
++ parent.clear();
++ }
++
++ public boolean contains(Object value) {
++ return parent.containsValue(value);
++ }
++
++ public Iterator<V> iterator() {
++ return parent.createValuesIterator();
++ }
++ }
++
++ /**
++ * Values iterator.
++ */
++ protected static class ValuesIterator <K,V> extends HashIterator<K, V> implements Iterator<V> {
++
++ protected ValuesIterator(AbstractHashedMap<K, V> parent) {
++ super(parent);
++ }
++
++ public V next() {
++ return super.nextEntry().getValue();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * HashEntry used to store the data.
++ * <p/>
++ * If you subclass <code>AbstractHashedMap</code> but not <code>HashEntry</code>
++ * then you will not be able to access the protected fields.
++ * The <code>entryXxx()</code> methods on <code>AbstractHashedMap</code> exist
++ * to provide the necessary access.
++ */
++ protected static class HashEntry <K,V> implements Map.Entry<K, V>, KeyValue<K, V> {
++ /**
++ * The next entry in the hash chain
++ */
++ protected HashEntry<K, V> next;
++ /**
++ * The hash code of the key
++ */
++ protected int hashCode;
++ /**
++ * The key
++ */
++ private K key;
++ /**
++ * The value
++ */
++ private V value;
++
++ protected HashEntry(HashEntry<K, V> next, int hashCode, K key, V value) {
++ super();
++ this.next = next;
++ this.hashCode = hashCode;
++ this.key = key;
++ this.value = value;
++ }
++
++ public K getKey() {
++ return key;
++ }
++
++ public void setKey(K key) {
++ this.key = key;
++ }
++
++ public V getValue() {
++ return value;
++ }
++
++ public V setValue(V value) {
++ V old = this.value;
++ this.value = value;
++ return old;
++ }
++
++ 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()));
++ }
++
++ public int hashCode() {
++ return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode());
++ }
++
++ public String toString() {
++ return new StringBuffer().append(getKey()).append('=').append(getValue()).toString();
++ }
++ }
++
++ /**
++ * Base Iterator
++ */
++ protected static abstract class HashIterator <K,V> {
++
++ /**
++ * The parent map
++ */
++ protected final AbstractHashedMap parent;
++ /**
++ * The current index into the array of buckets
++ */
++ protected int hashIndex;
++ /**
++ * The last returned entry
++ */
++ protected HashEntry<K, V> last;
++ /**
++ * The next entry
++ */
++ protected HashEntry<K, V> next;
++ /**
++ * The modification count expected
++ */
++ protected int expectedModCount;
++
++ protected HashIterator(AbstractHashedMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ HashEntry<K, V>[] data = parent.data;
++ int i = data.length;
++ HashEntry<K, V> next = null;
++ while (i > 0 && next == null) {
++ next = data[--i];
++ }
++ this.next = next;
++ this.hashIndex = i;
++ this.expectedModCount = parent.modCount;
++ }
++
++ public boolean hasNext() {
++ return (next != null);
++ }
++
++ protected HashEntry<K, V> nextEntry() {
++ if (parent.modCount != expectedModCount) {
++ throw new ConcurrentModificationException();
++ }
++ HashEntry<K, V> newCurrent = next;
++ if (newCurrent == null) {
++ throw new NoSuchElementException(AbstractHashedMap.NO_NEXT_ENTRY);
++ }
++ HashEntry<K, V>[] data = parent.data;
++ int i = hashIndex;
++ HashEntry<K, V> n = newCurrent.next;
++ while (n == null && i > 0) {
++ n = data[--i];
++ }
++ next = n;
++ hashIndex = i;
++ last = newCurrent;
++ return newCurrent;
++ }
++
++ protected HashEntry<K, V> currentEntry() {
++ return last;
++ }
++
++ public void remove() {
++ if (last == null) {
++ throw new IllegalStateException(AbstractHashedMap.REMOVE_INVALID);
++ }
++ if (parent.modCount != expectedModCount) {
++ throw new ConcurrentModificationException();
++ }
++ parent.remove(last.getKey());
++ last = null;
++ expectedModCount = parent.modCount;
++ }
++
++ public String toString() {
++ if (last != null) {
++ return "Iterator[" + last.getKey() + "=" + last.getValue() + "]";
++ } else {
++ return "Iterator[]";
++ }
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Writes the map data to the stream. This method must be overridden if a
++ * subclass must be setup before <code>put()</code> is used.
++ * <p/>
++ * Serialization is not one of the JDK's nicest topics. Normal serialization will
++ * initialise the superclass before the subclass. Sometimes however, this isn't
++ * what you want, as in this case the <code>put()</code> method on read can be
++ * affected by subclass state.
++ * <p/>
++ * The solution adopted here is to serialize the state data of this class in
++ * this protected method. This method must be called by the
++ * <code>writeObject()</code> of the first serializable subclass.
++ * <p/>
++ * Subclasses may override if they have a specific field that must be present
++ * on read before this implementation will work. Generally, the read determines
++ * what must be serialized here, if anything.
++ *
++ * @param out the output stream
++ */
++ protected void doWriteObject(ObjectOutputStream out) throws IOException {
++ out.writeFloat(loadFactor);
++ out.writeInt(data.length);
++ out.writeInt(size);
++ for (MapIterator it = mapIterator(); it.hasNext();) {
++ out.writeObject(it.next());
++ out.writeObject(it.getValue());
++ }
++ }
++
++ /**
++ * Reads the map data from the stream. This method must be overridden if a
++ * subclass must be setup before <code>put()</code> is used.
++ * <p/>
++ * Serialization is not one of the JDK's nicest topics. Normal serialization will
++ * initialise the superclass before the subclass. Sometimes however, this isn't
++ * what you want, as in this case the <code>put()</code> method on read can be
++ * affected by subclass state.
++ * <p/>
++ * The solution adopted here is to deserialize the state data of this class in
++ * this protected method. This method must be called by the
++ * <code>readObject()</code> of the first serializable subclass.
++ * <p/>
++ * Subclasses may override if the subclass has a specific field that must be present
++ * before <code>put()</code> or <code>calculateThreshold()</code> will work correctly.
++ *
++ * @param in the input stream
++ */
++ protected void doReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ loadFactor = in.readFloat();
++ int capacity = in.readInt();
++ int size = in.readInt();
++ init();
++ data = new HashEntry[capacity];
++ for (int i = 0; i < size; i++) {
++ K key = (K) in.readObject();
++ V value = (V) in.readObject();
++ put(key, value);
++ }
++ threshold = calculateThreshold(data.length, loadFactor);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Clones the map without cloning the keys or values.
++ * <p/>
++ * To implement <code>clone()</code>, a subclass must implement the
++ * <code>Cloneable</code> interface and make this method public.
++ *
++ * @return a shallow clone
++ */
++ protected Object clone() {
++ try {
++ AbstractHashedMap cloned = (AbstractHashedMap) super.clone();
++ cloned.data = new HashEntry[data.length];
++ cloned.entrySet = null;
++ cloned.keySet = null;
++ cloned.values = null;
++ cloned.modCount = 0;
++ cloned.size = 0;
++ cloned.init();
++ cloned.putAll(this);
++ return cloned;
++
++ } catch (CloneNotSupportedException ex) {
++ return null; // should never happen
++ }
++ }
++
++ /**
++ * Compares this map with another.
++ *
++ * @param obj the object to compare to
++ * @return true if equal
++ */
++ public boolean equals(Object obj) {
++ if (obj == this) {
++ return true;
++ }
++ if (obj instanceof Map == false) {
++ return false;
++ }
++ Map map = (Map) obj;
++ if (map.size() != size()) {
++ return false;
++ }
++ MapIterator it = mapIterator();
++ try {
++ while (it.hasNext()) {
++ Object key = it.next();
++ Object value = it.getValue();
++ if (value == null) {
++ if (map.get(key) != null || map.containsKey(key) == false) {
++ return false;
++ }
++ } else {
++ if (value.equals(map.get(key)) == false) {
++ return false;
++ }
++ }
++ }
++ } catch (ClassCastException ignored) {
++ return false;
++ } catch (NullPointerException ignored) {
++ return false;
++ }
++ return true;
++ }
++
++ /**
++ * Gets the standard Map hashCode.
++ *
++ * @return the hash code defined in the Map interface
++ */
++ public int hashCode() {
++ int total = 0;
++ Iterator it = createEntrySetIterator();
++ while (it.hasNext()) {
++ total += it.next().hashCode();
++ }
++ return total;
++ }
++
++ /**
++ * Gets the map as a String.
++ *
++ * @return a string version of the map
++ */
++ public String toString() {
++ if (size() == 0) {
++ return "{}";
++ }
++ StringBuffer buf = new StringBuffer(32 * size());
++ buf.append('{');
++
++ MapIterator it = mapIterator();
++ boolean hasNext = it.hasNext();
++ while (hasNext) {
++ Object key = it.next();
++ Object value = it.getValue();
++ buf.append(key == this ? "(this Map)" : key).append('=').append(value == this ? "(this Map)" : value);
++
++ hasNext = it.hasNext();
++ if (hasNext) {
++ buf.append(',').append(' ');
++ }
++ }
++
++ buf.append('}');
++ return buf.toString();
++ }
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/AbstractInputCheckedMapDecorator.java
+@@ -0,0 +1,199 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.iterators.AbstractIteratorDecorator;
++import org.apache.commons.collections15.keyvalue.AbstractMapEntryDecorator;
++import org.apache.commons.collections15.set.AbstractSetDecorator;
++
++import java.lang.reflect.Array;
++import java.util.Iterator;
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * An abstract base class that simplifies the task of creating map decorators.
++ * <p/>
++ * The Map API is very difficult to decorate correctly, and involves implementing
++ * lots of different classes. This class exists to provide a simpler API.
++ * <p/>
++ * Special hook methods are provided that are called when objects are added to
++ * the map. By overriding these methods, the input can be validated or manipulated.
++ * In addition to the main map methods, the entrySet is also affected, which is
++ * the hardest part of writing map implementations.
++ * <p/>
++ * This class is package-scoped, and may be withdrawn or replaced in future
++ * versions of Commons Collections.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.1
++ */
++abstract class AbstractInputCheckedMapDecorator <K,V> extends AbstractMapDecorator<K, V> {
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ */
++ protected AbstractInputCheckedMapDecorator() {
++ super();
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ protected AbstractInputCheckedMapDecorator(Map<K, V> map) {
++ super(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Hook method called when a value is being set using <code>setValue</code>.
++ * <p/>
++ * An implementation may validate the value and throw an exception
++ * or it may transform the value into another object.
++ * <p/>
++ * This implementation returns the input value.
++ *
++ * @param value the value to check
++ * @throws UnsupportedOperationException if the map may not be changed by setValue
++ * @throws IllegalArgumentException if the specified value is invalid
++ * @throws ClassCastException if the class of the specified value is invalid
++ * @throws NullPointerException if the specified value is null and nulls are invalid
++ */
++ protected abstract V checkSetValue(V value);
++
++ /**
++ * Hook method called to determine if <code>checkSetValue</code> has any effect.
++ * <p/>
++ * An implementation should return false if the <code>checkSetValue</code> method
++ * has no effect as this optimises the implementation.
++ * <p/>
++ * This implementation returns <code>true</code>.
++ */
++ protected boolean isSetValueChecking() {
++ return true;
++ }
++
++ //-----------------------------------------------------------------------
++ public Set<Map.Entry<K, V>> entrySet() {
++ if (isSetValueChecking()) {
++ return new EntrySet<K, V>(map.entrySet(), this);
++ } else {
++ return map.entrySet();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Implementation of an entry set that checks additions via setValue.
++ */
++ static class EntrySet <K,V> extends AbstractSetDecorator<Map.Entry<K, V>> {
++
++ /**
++ * The parent map
++ */
++ private final AbstractInputCheckedMapDecorator<K, V> parent;
++
++ protected EntrySet(Set<Map.Entry<K, V>> set, AbstractInputCheckedMapDecorator<K, V> parent) {
++ super(set);
++ this.parent = parent;
++ }
++
++ public Iterator<Map.Entry<K, V>> iterator() {
++ return new EntrySetIterator<K, V>(collection.iterator(), parent);
++ }
++
++ public Object[] toArray() {
++ Object[] array = collection.toArray();
++ for (int i = 0; i < array.length; i++) {
++ array[i] = new MapEntry((Map.Entry) array[i], parent);
++ }
++ return array;
++ }
++
++ public <T> T[] toArray(T array[]) {
++ Object[] result = array;
++ if (array.length > 0) {
++ // we must create a new array to handle multi-threaded situations
++ // where another thread could access data before we decorate it
++ result = (T[]) Array.newInstance(array.getClass().getComponentType(), 0);
++ }
++ result = collection.toArray(result);
++ for (int i = 0; i < result.length; i++) {
++ result[i] = new MapEntry((Map.Entry) result[i], parent);
++ }
++
++ // check to see if result should be returned straight
++ if (result.length > array.length) {
++ return (T[]) result;
++ }
++
++ // copy back into input array to fulfil the method contract
++ System.arraycopy(result, 0, array, 0, result.length);
++ if (array.length > result.length) {
++ array[result.length] = null;
++ }
++ return (T[]) array;
++ }
++ }
++
++ /**
++ * Implementation of an entry set iterator that checks additions via setValue.
++ */
++ static class EntrySetIterator <K,V> extends AbstractIteratorDecorator<Map.Entry<K, V>> {
++
++ /**
++ * The parent map
++ */
++ private final AbstractInputCheckedMapDecorator<K, V> parent;
++
++ protected EntrySetIterator(Iterator<Map.Entry<K, V>> iterator, AbstractInputCheckedMapDecorator<K, V> parent) {
++ super(iterator);
++ this.parent = parent;
++ }
++
++ public Map.Entry<K, V> next() {
++ Map.Entry<K, V> entry = iterator.next();
++ return new MapEntry<K, V>(entry, parent);
++ }
++ }
++
++ /**
++ * Implementation of a map entry that checks additions via setValue.
++ */
++ static class MapEntry <K,V> extends AbstractMapEntryDecorator<K, V> {
++
++ /**
++ * The parent map
++ */
++ private final AbstractInputCheckedMapDecorator<K, V> parent;
++
++ protected MapEntry(Map.Entry<K, V> entry, AbstractInputCheckedMapDecorator<K, V> parent) {
++ super(entry);
++ this.parent = parent;
++ }
++
++ public V setValue(V value) {
++ value = parent.checkSetValue(value);
++ return entry.setValue(value);
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/AbstractLinkedMap.java
+@@ -0,0 +1,617 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.*;
++import org.apache.commons.collections15.iterators.EmptyOrderedIterator;
++import org.apache.commons.collections15.iterators.EmptyOrderedMapIterator;
++
++import java.util.ConcurrentModificationException;
++import java.util.Iterator;
++import java.util.Map;
++import java.util.NoSuchElementException;
++
++/**
++ * An abstract implementation of a hash-based map that links entries to create an
++ * ordered map and which provides numerous points for subclasses to override.
++ * <p/>
++ * This class implements all the features necessary for a subclass linked
++ * hash-based map. Key-value entries are stored in instances of the
++ * <code>LinkEntry</code> class which can be overridden and replaced.
++ * The iterators can similarly be replaced, without the need to replace the KeySet,
++ * EntrySet and Values view classes.
++ * <p/>
++ * Overridable methods are provided to change the default hashing behaviour, and
++ * to change how entries are added to and removed from the map. Hopefully, all you
++ * need for unusual subclasses is here.
++ * <p/>
++ * This implementation maintains order by original insertion, but subclasses
++ * may work differently. The <code>OrderedMap</code> interface is implemented
++ * to provide access to bidirectional iteration and extra convenience methods.
++ * <p/>
++ * The <code>orderedMapIterator()</code> method provides direct access to a
++ * bidirectional iterator. The iterators from the other views can also be cast
++ * to <code>OrderedIterator</code> if required.
++ * <p/>
++ * All the available iterators can be reset back to the start by casting to
++ * <code>ResettableIterator</code> and calling <code>reset()</code>.
++ * <p/>
++ * The implementation is also designed to be subclassed, with lots of useful
++ * methods exposed.
++ *
++ * @author java util LinkedHashMap
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class AbstractLinkedMap <K,V> extends AbstractHashedMap<K, V> implements OrderedMap<K, V> {
++
++ /**
++ * Header in the linked list
++ */
++ protected transient LinkEntry<K, V> header;
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ */
++ protected AbstractLinkedMap() {
++ super();
++ }
++
++ /**
++ * Constructor which performs no validation on the passed in parameters.
++ *
++ * @param initialCapacity the initial capacity, must be a power of two
++ * @param loadFactor the load factor, must be > 0.0f and generally < 1.0f
++ * @param threshold the threshold, must be sensible
++ */
++ protected AbstractLinkedMap(int initialCapacity, float loadFactor, int threshold) {
++ super(initialCapacity, loadFactor, threshold);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity.
++ *
++ * @param initialCapacity the initial capacity
++ * @throws IllegalArgumentException if the initial capacity is less than one
++ */
++ protected AbstractLinkedMap(int initialCapacity) {
++ super(initialCapacity);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity and
++ * load factor.
++ *
++ * @param initialCapacity the initial capacity
++ * @param loadFactor the load factor
++ * @throws IllegalArgumentException if the initial capacity is less than one
++ * @throws IllegalArgumentException if the load factor is less than zero
++ */
++ protected AbstractLinkedMap(int initialCapacity, float loadFactor) {
++ super(initialCapacity, loadFactor);
++ }
++
++ /**
++ * Constructor copying elements from another map.
++ *
++ * @param map the map to copy
++ * @throws NullPointerException if the map is null
++ */
++ protected AbstractLinkedMap(Map<? extends K, ? extends V> map) {
++ super(map);
++ }
++
++ /**
++ * Initialise this subclass during construction.
++ */
++ protected void init() {
++ header = new LinkEntry<K, V>(null, -1, null, null);
++ header.before = header.after = header;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Checks whether the map contains the specified value.
++ *
++ * @param value the value to search for
++ * @return true if the map contains the value
++ */
++ public boolean containsValue(Object value) {
++ // override uses faster iterator
++ if (value == null) {
++ for (LinkEntry entry = header.after; entry != header; entry = entry.after) {
++ if (entry.getValue() == null) {
++ return true;
++ }
++ }
++ } else {
++ for (LinkEntry entry = header.after; entry != header; entry = entry.after) {
++ if (isEqualValue(value, entry.getValue())) {
++ return true;
++ }
++ }
++ }
++ return false;
++ }
++
++ /**
++ * Clears the map, resetting the size to zero and nullifying references
++ * to avoid garbage collection issues.
++ */
++ public void clear() {
++ // override to reset the linked list
++ super.clear();
++ header.before = header.after = header;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the first key in the map, which is the most recently inserted.
++ *
++ * @return the most recently inserted key
++ */
++ public K firstKey() {
++ if (size == 0) {
++ throw new NoSuchElementException("Map is empty");
++ }
++ return header.after.getKey();
++ }
++
++ /**
++ * Gets the last key in the map, which is the first inserted.
++ *
++ * @return the eldest key
++ */
++ public K lastKey() {
++ if (size == 0) {
++ throw new NoSuchElementException("Map is empty");
++ }
++ return header.before.getKey();
++ }
++
++ /**
++ * Gets the next key in sequence.
++ *
++ * @param key the key to get after
++ * @return the next key
++ */
++ public K nextKey(K key) {
++ LinkEntry<K, V> entry = (LinkEntry<K, V>) getEntry(key);
++ return (entry == null || entry.after == header ? null : entry.after.getKey());
++ }
++
++ /**
++ * Gets the previous key in sequence.
++ *
++ * @param key the key to get before
++ * @return the previous key
++ */
++ public K previousKey(K key) {
++ LinkEntry<K, V> entry = (LinkEntry<K, V>) getEntry(key);
++ return (entry == null || entry.before == header ? null : entry.before.getKey());
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the key at the specified index.
++ *
++ * @param index the index to retrieve
++ * @return the key at the specified index
++ * @throws IndexOutOfBoundsException if the index is invalid
++ */
++ protected LinkEntry<K, V> getEntry(int index) {
++ if (index < 0) {
++ throw new IndexOutOfBoundsException("Index " + index + " is less than zero");
++ }
++ if (index >= size) {
++ throw new IndexOutOfBoundsException("Index " + index + " is invalid for size " + size);
++ }
++ LinkEntry<K, V> entry;
++ if (index < (size / 2)) {
++ // Search forwards
++ entry = header.after;
++ for (int currentIndex = 0; currentIndex < index; currentIndex++) {
++ entry = entry.after;
++ }
++ } else {
++ // Search backwards
++ entry = header;
++ for (int currentIndex = size; currentIndex > index; currentIndex--) {
++ entry = entry.before;
++ }
++ }
++ return entry;
++ }
++
++ /**
++ * Adds an entry into this map, maintaining insertion order.
++ * <p/>
++ * This implementation adds the entry to the data storage table and
++ * to the end of the linked list.
++ *
++ * @param entry the entry to add
++ * @param hashIndex the index into the data array to store at
++ */
++ protected void addEntry(HashEntry<K, V> entry, int hashIndex) {
++ LinkEntry<K, V> link = (LinkEntry<K, V>) entry;
++ link.after = header;
++ link.before = header.before;
++ header.before.after = link;
++ header.before = link;
++ data[hashIndex] = entry;
++ }
++
++ /**
++ * Creates an entry to store the data.
++ * <p/>
++ * This implementation creates a new LinkEntry instance.
++ *
++ * @param next the next entry in sequence
++ * @param hashCode the hash code to use
++ * @param key the key to store
++ * @param value the value to store
++ * @return the newly created entry
++ */
++ protected HashEntry<K, V> createEntry(HashEntry<K, V> next, int hashCode, K key, V value) {
++ return new LinkEntry<K, V>(next, hashCode, key, value);
++ }
++
++ /**
++ * Removes an entry from the map and the linked list.
++ * <p/>
++ * This implementation removes the entry from the linked list chain, then
++ * calls the superclass implementation.
++ *
++ * @param entry the entry to remove
++ * @param hashIndex the index into the data structure
++ * @param previous the previous entry in the chain
++ */
++ protected void removeEntry(HashEntry<K, V> entry, int hashIndex, HashEntry<K, V> previous) {
++ LinkEntry<K, V> link = (LinkEntry<K, V>) entry;
++ link.before.after = link.after;
++ link.after.before = link.before;
++ link.after = null;
++ link.before = null;
++ super.removeEntry(entry, hashIndex, previous);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the <code>before</code> field from a <code>LinkEntry</code>.
++ * Used in subclasses that have no visibility of the field.
++ *
++ * @param entry the entry to query, must not be null
++ * @return the <code>before</code> field of the entry
++ * @throws NullPointerException if the entry is null
++ * @since Commons Collections 3.1
++ */
++ protected LinkEntry<K, V> entryBefore(LinkEntry<K, V> entry) {
++ return entry.before;
++ }
++
++ /**
++ * Gets the <code>after</code> field from a <code>LinkEntry</code>.
++ * Used in subclasses that have no visibility of the field.
++ *
++ * @param entry the entry to query, must not be null
++ * @return the <code>after</code> field of the entry
++ * @throws NullPointerException if the entry is null
++ * @since Commons Collections 3.1
++ */
++ protected LinkEntry<K, V> entryAfter(LinkEntry<K, V> entry) {
++ return entry.after;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator over the map.
++ * Changes made to the iterator affect this map.
++ * <p/>
++ * A MapIterator returns the keys in the map. It also provides convenient
++ * methods to get the key and value, and set the value.
++ * It avoids the need to create an entrySet/keySet/values object.
++ *
++ * @return the map iterator
++ */
++ public MapIterator<K, V> mapIterator() {
++ if (size == 0) {
++ return EmptyOrderedMapIterator.INSTANCE;
++ }
++ return new LinkMapIterator<K, V>(this);
++ }
++
++ /**
++ * Gets a bidirectional iterator over the map.
++ * Changes made to the iterator affect this map.
++ * <p/>
++ * A MapIterator returns the keys in the map. It also provides convenient
++ * methods to get the key and value, and set the value.
++ * It avoids the need to create an entrySet/keySet/values object.
++ *
++ * @return the map iterator
++ */
++ public OrderedMapIterator<K, V> orderedMapIterator() {
++ if (size == 0) {
++ return EmptyOrderedMapIterator.INSTANCE;
++ }
++ return new LinkMapIterator<K, V>(this);
++ }
++
++ /**
++ * MapIterator implementation.
++ */
++ protected static class LinkMapIterator <K,V> extends LinkIterator<K, V> implements OrderedMapIterator<K, V>, OrderedIterator<K>, ResettableIterator<K> {
++
++ protected LinkMapIterator(AbstractLinkedMap<K, V> parent) {
++ super(parent);
++ }
++
++ public K next() {
++ return super.nextEntry().getKey();
++ }
++
++ public K previous() {
++ return super.previousEntry().getKey();
++ }
++
++ public K getKey() {
++ HashEntry<K, V> current = currentEntry();
++ if (current == null) {
++ throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
++ }
++ return current.getKey();
++ }
++
++ public V getValue() {
++ HashEntry<K, V> current = currentEntry();
++ if (current == null) {
++ throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
++ }
++ return current.getValue();
++ }
++
++ public V setValue(V value) {
++ HashEntry<K, V> current = currentEntry();
++ if (current == null) {
++ throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
++ }
++ return current.setValue(value);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Creates an entry set iterator.
++ * Subclasses can override this to return iterators with different properties.
++ *
++ * @return the entrySet iterator
++ */
++ protected Iterator<Map.Entry<K, V>> createEntrySetIterator() {
++ if (size() == 0) {
++ return EmptyOrderedIterator.INSTANCE;
++ }
++ return new EntrySetIterator<K, V>(this);
++ }
++
++ /**
++ * EntrySet iterator.
++ */
++ protected static class EntrySetIterator <K,V> extends LinkIterator<K, V> implements OrderedIterator<Map.Entry<K, V>>, ResettableIterator<Map.Entry<K, V>> {
++
++ protected EntrySetIterator(AbstractLinkedMap<K, V> parent) {
++ super(parent);
++ }
++
++ public Map.Entry<K, V> next() {
++ return super.nextEntry();
++ }
++
++ public Map.Entry<K, V> previous() {
++ return super.previousEntry();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Creates a key set iterator.
++ * Subclasses can override this to return iterators with different properties.
++ *
++ * @return the keySet iterator
++ */
++ protected Iterator createKeySetIterator() {
++ if (size() == 0) {
++ return EmptyOrderedIterator.INSTANCE;
++ }
++ return new KeySetIterator(this);
++ }
++
++ /**
++ * KeySet iterator.
++ */
++ protected static class KeySetIterator <K,V> extends LinkIterator<K, V> implements OrderedIterator<K>, ResettableIterator<K> {
++
++ protected KeySetIterator(AbstractLinkedMap<K, V> parent) {
++ super(parent);
++ }
++
++ public K next() {
++ return super.nextEntry().getKey();
++ }
++
++ public K previous() {
++ return super.previousEntry().getKey();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Creates a values iterator.
++ * Subclasses can override this to return iterators with different properties.
++ *
++ * @return the values iterator
++ */
++ protected Iterator<V> createValuesIterator() {
++ if (size() == 0) {
++ return EmptyOrderedIterator.INSTANCE;
++ }
++ return new ValuesIterator<K, V>(this);
++ }
++
++ /**
++ * Values iterator.
++ */
++ protected static class ValuesIterator <K,V> extends LinkIterator<K, V> implements OrderedIterator<V>, ResettableIterator<V> {
++
++ protected ValuesIterator(AbstractLinkedMap<K, V> parent) {
++ super(parent);
++ }
++
++ public V next() {
++ return super.nextEntry().getValue();
++ }
++
++ public V previous() {
++ return super.previousEntry().getValue();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * LinkEntry that stores the data.
++ * <p/>
++ * If you subclass <code>AbstractLinkedMap</code> but not <code>LinkEntry</code>
++ * then you will not be able to access the protected fields.
++ * The <code>entryXxx()</code> methods on <code>AbstractLinkedMap</code> exist
++ * to provide the necessary access.
++ */
++ protected static class LinkEntry <K,V> extends HashEntry<K, V> {
++ /**
++ * The entry before this one in the order
++ */
++ protected LinkEntry<K, V> before;
++ /**
++ * The entry after this one in the order
++ */
++ protected LinkEntry<K, V> after;
++
++ /**
++ * Constructs a new entry.
++ *
++ * @param next the next entry in the hash bucket sequence
++ * @param hashCode the hash code
++ * @param key the key
++ * @param value the value
++ */
++ protected LinkEntry(HashEntry<K, V> next, int hashCode, K key, V value) {
++ super(next, hashCode, key, value);
++ }
++ }
++
++ /**
++ * Base Iterator that iterates in link order.
++ */
++ protected static abstract class LinkIterator <K,V> {
++
++ /**
++ * The parent map
++ */
++ protected final AbstractLinkedMap<K, V> parent;
++ /**
++ * The current (last returned) entry
++ */
++ protected LinkEntry<K, V> last;
++ /**
++ * The next entry
++ */
++ protected LinkEntry<K, V> next;
++ /**
++ * The modification count expected
++ */
++ protected int expectedModCount;
++
++ protected LinkIterator(AbstractLinkedMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ this.next = parent.header.after;
++ this.expectedModCount = parent.modCount;
++ }
++
++ public boolean hasNext() {
++ return (next != parent.header);
++ }
++
++ public boolean hasPrevious() {
++ return (next.before != parent.header);
++ }
++
++ protected LinkEntry<K, V> nextEntry() {
++ if (parent.modCount != expectedModCount) {
++ throw new ConcurrentModificationException();
++ }
++ if (next == parent.header) {
++ throw new NoSuchElementException(AbstractHashedMap.NO_NEXT_ENTRY);
++ }
++ last = next;
++ next = next.after;
++ return last;
++ }
++
++ protected LinkEntry<K, V> previousEntry() {
++ if (parent.modCount != expectedModCount) {
++ throw new ConcurrentModificationException();
++ }
++ LinkEntry<K, V> previous = next.before;
++ if (previous == parent.header) {
++ throw new NoSuchElementException(AbstractHashedMap.NO_PREVIOUS_ENTRY);
++ }
++ next = previous;
++ last = previous;
++ return last;
++ }
++
++ protected LinkEntry<K, V> currentEntry() {
++ return last;
++ }
++
++ public void remove() {
++ if (last == null) {
++ throw new IllegalStateException(AbstractHashedMap.REMOVE_INVALID);
++ }
++ if (parent.modCount != expectedModCount) {
++ throw new ConcurrentModificationException();
++ }
++ parent.remove(last.getKey());
++ last = null;
++ expectedModCount = parent.modCount;
++ }
++
++ public void reset() {
++ last = null;
++ next = parent.header.after;
++ }
++
++ public String toString() {
++ if (last != null) {
++ return "Iterator[" + last.getKey() + "=" + last.getValue() + "]";
++ } else {
++ return "Iterator[]";
++ }
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/AbstractMapDecorator.java
+@@ -0,0 +1,143 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import java.util.Collection;
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * Provides a base decorator that enables additional functionality to be added
++ * to a Map via decoration.
++ * <p/>
++ * Methods are forwarded directly to the decorated map.
++ * <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.
++ *
++ * @author Daniel Rall
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractMapDecorator <K,V> implements Map<K, V> {
++
++ /**
++ * The map to decorate
++ */
++ protected transient Map<K, V> map;
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ *
++ * @since Commons Collections 3.1
++ */
++ protected AbstractMapDecorator() {
++ super();
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ public AbstractMapDecorator(Map<K, V> map) {
++ if (map == null) {
++ throw new IllegalArgumentException("Map must not be null");
++ }
++ this.map = map;
++ }
++
++ /**
++ * Gets the map being decorated.
++ *
++ * @return the decorated map
++ */
++ protected Map<K, V> getMap() {
++ return map;
++ }
++
++ //-----------------------------------------------------------------------
++ public void clear() {
++ map.clear();
++ }
++
++ public boolean containsKey(Object key) {
++ return map.containsKey(key);
++ }
++
++ public boolean containsValue(Object value) {
++ return map.containsValue(value);
++ }
++
++ public Set<Map.Entry<K, V>> entrySet() {
++ return map.entrySet();
++ }
++
++ public V get(Object key) {
++ return map.get(key);
++ }
++
++ public boolean isEmpty() {
++ return map.isEmpty();
++ }
++
++ public Set<K> keySet() {
++ return map.keySet();
++ }
++
++ public V put(K key, V value) {
++ return map.put(key, value);
++ }
++
++ public void putAll(Map<? extends K, ? extends V> mapToCopy) {
++ map.putAll(mapToCopy);
++ }
++
++ public V remove(Object key) {
++ return map.remove(key);
++ }
++
++ public int size() {
++ return map.size();
++ }
++
++ public Collection<V> values() {
++ return map.values();
++ }
++
++ public boolean equals(Object object) {
++ if (object == this) {
++ return true;
++ }
++ return map.equals(object);
++ }
++
++ public int hashCode() {
++ return map.hashCode();
++ }
++
++ public String toString() {
++ return map.toString();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/AbstractOrderedMapDecorator.java
+@@ -0,0 +1,94 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.OrderedMap;
++import org.apache.commons.collections15.OrderedMapIterator;
++
++/**
++ * Provides a base decorator that enables additional functionality to be added
++ * to an OrderedMap via decoration.
++ * <p/>
++ * Methods are forwarded directly to the decorated map.
++ * <p/>
++ * This implementation does not perform any special processing with the map views.
++ * 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.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractOrderedMapDecorator <K,V> extends AbstractMapDecorator<K, V> implements OrderedMap<K, V> {
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ *
++ * @since Commons Collections 3.1
++ */
++ protected AbstractOrderedMapDecorator() {
++ super();
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ public AbstractOrderedMapDecorator(OrderedMap<K, V> map) {
++ super(map);
++ }
++
++ /**
++ * Gets the map being decorated.
++ *
++ * @return the decorated map
++ */
++ protected OrderedMap<K, V> getOrderedMap() {
++ return (OrderedMap<K, V>) map;
++ }
++
++ //-----------------------------------------------------------------------
++ public K firstKey() {
++ return getOrderedMap().firstKey();
++ }
++
++ public K lastKey() {
++ return getOrderedMap().lastKey();
++ }
++
++ public K nextKey(K key) {
++ return getOrderedMap().nextKey(key);
++ }
++
++ public K previousKey(K key) {
++ return getOrderedMap().previousKey(key);
++ }
++
++ public MapIterator<K, V> mapIterator() {
++ return getOrderedMap().mapIterator();
++ }
++
++ public OrderedMapIterator<K, V> orderedMapIterator() {
++ return getOrderedMap().orderedMapIterator();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/AbstractReferenceMap.java
+@@ -0,0 +1,1028 @@
++// Converted, with some major refactors required. Not as memory-efficient as before, could use additional refactoring.
++// Perhaps use four different types of HashEntry classes for max efficiency:
++// normal HashEntry for HARD,HARD
++// HardRefEntry for HARD,(SOFT|WEAK)
++// RefHardEntry for (SOFT|WEAK),HARD
++// RefRefEntry for (SOFT|WEAK),(SOFT|WEAK)
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.keyvalue.DefaultMapEntry;
++
++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.*;
++
++/**
++ * An abstract implementation of a hash-based map that allows the entries to
++ * be removed by the garbage collector.
++ * <p/>
++ * This class implements all the features necessary for a subclass reference
++ * hash-based map. Key-value entries are stored in instances of the
++ * <code>ReferenceEntry</code> class which can be overridden and replaced.
++ * The iterators can similarly be replaced, without the need to replace the KeySet,
++ * EntrySet and Values view classes.
++ * <p/>
++ * Overridable methods are provided to change the default hashing behaviour, and
++ * to change how entries are added to and removed from the map. Hopefully, all you
++ * need for unusual subclasses is here.
++ * <p/>
++ * When you construct an <code>AbstractReferenceMap</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/>
++ * This {@link Map} implementation does <i>not</i> allow null elements.
++ * Attempting to add a null key or value to the map will raise a
++ * <code>NullPointerException</code>.
++ * <p/>
++ * All the available iterators can be reset back to the start by casting to
++ * <code>ResettableIterator</code> and calling <code>reset()</code>.
++ * <p/>
++ * This implementation is not synchronized.
++ * You can use {@link java.util.Collections#synchronizedMap} to
++ * provide synchronized access to a <code>ReferenceMap</code>.
++ *
++ * @author Paul Jack
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @see java.lang.ref.Reference
++ * @since Commons Collections 3.1 (extracted from ReferenceMap in 3.0)
++ */
++public abstract class AbstractReferenceMap <K,V> extends AbstractHashedMap<K, V> {
++
++ /**
++ * Constant indicating that hard references should be used
++ */
++ public static final int HARD = 0;
++
++ /**
++ * Constant indicating that soft references should be used
++ */
++ public static final int SOFT = 1;
++
++ /**
++ * Constant indicating that weak references should be used
++ */
++ public static final int WEAK = 2;
++
++ /**
++ * The reference type for keys. Must be HARD, SOFT, WEAK.
++ *
++ * @serial
++ */
++ protected int keyType;
++
++ /**
++ * The reference type for values. Must be HARD, SOFT, WEAK.
++ *
++ * @serial
++ */
++ protected int valueType;
++
++ /**
++ * Should the value be automatically purged when the associated key has been collected?
++ */
++ protected boolean purgeValues;
++
++ /**
++ * ReferenceQueue used to eliminate stale mappings.
++ * See purge.
++ */
++ private transient ReferenceQueue queue;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor used during deserialization.
++ */
++ protected AbstractReferenceMap() {
++ super();
++ }
++
++ /**
++ * Constructs a new empty map with the specified reference types,
++ * load factor and initial capacity.
++ *
++ * @param keyType the type of reference to use for keys;
++ * must be {@link #SOFT} or {@link #WEAK}
++ * @param valueType the type of reference to use for values;
++ * must be {@link #SOFT} or {@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
++ */
++ protected AbstractReferenceMap(int keyType, int valueType, int capacity, float loadFactor, boolean purgeValues) {
++ super(capacity, loadFactor);
++ verify("keyType", keyType);
++ verify("valueType", valueType);
++ this.keyType = keyType;
++ this.valueType = valueType;
++ this.purgeValues = purgeValues;
++ }
++
++ /**
++ * Initialise this subclass during construction, cloning or deserialization.
++ */
++ protected void init() {
++ queue = new ReferenceQueue();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Checks the type int is a valid value.
++ *
++ * @param name the name for error messages
++ * @param type the type value to check
++ * @throws IllegalArgumentException if the value if invalid
++ */
++ private static void verify(String name, int type) {
++ if ((type < HARD) || (type > WEAK)) {
++ throw new IllegalArgumentException(name + " must be HARD, SOFT, WEAK.");
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the size of the map.
++ *
++ * @return the size
++ */
++ public int size() {
++ purgeBeforeRead();
++ return super.size();
++ }
++
++ /**
++ * Checks whether the map is currently empty.
++ *
++ * @return true if the map is currently size zero
++ */
++ public boolean isEmpty() {
++ purgeBeforeRead();
++ return super.isEmpty();
++ }
++
++ /**
++ * Checks whether the map contains the specified key.
++ *
++ * @param key the key to search for
++ * @return true if the map contains the key
++ */
++ public boolean containsKey(Object key) {
++ purgeBeforeRead();
++ Entry entry = getEntry(key);
++ if (entry == null) {
++ return false;
++ }
++ return (entry.getValue() != null);
++ }
++
++ /**
++ * Checks whether the map contains the specified value.
++ *
++ * @param value the value to search for
++ * @return true if the map contains the value
++ */
++ public boolean containsValue(Object value) {
++ purgeBeforeRead();
++ if (value == null) {
++ return false;
++ }
++ return super.containsValue(value);
++ }
++
++ /**
++ * Gets the value mapped to the key specified.
++ *
++ * @param key the key
++ * @return the mapped value, null if no match
++ */
++ public V get(Object key) {
++ purgeBeforeRead();
++ Entry<K, V> entry = getEntry(key);
++ if (entry == null) {
++ return null;
++ }
++ return entry.getValue();
++ }
++
++
++ /**
++ * Puts a key-value mapping into this map.
++ * Neither the key nor the value may be null.
++ *
++ * @param key the key to add, must not be null
++ * @param value the value to add, must not be null
++ * @return the value previously mapped to this key, null if none
++ * @throws NullPointerException if either the key or value is null
++ */
++ public V put(K key, V value) {
++ if (key == null) {
++ throw new NullPointerException("null keys not allowed");
++ }
++ if (value == null) {
++ throw new NullPointerException("null values not allowed");
++ }
++
++ purgeBeforeWrite();
++ return super.put(key, value);
++ }
++
++ /**
++ * Removes the specified mapping from this map.
++ *
++ * @param key the mapping to remove
++ * @return the value mapped to the removed key, null if key not in map
++ */
++ public V remove(Object key) {
++ if (key == null) {
++ return null;
++ }
++ purgeBeforeWrite();
++ return super.remove(key);
++ }
++
++ /**
++ * Clears this map.
++ */
++ public void clear() {
++ super.clear();
++ while (queue.poll() != null) {
++ } // drain the queue
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets a MapIterator over the reference map.
++ * The iterator only returns valid key/value pairs.
++ *
++ * @return a map iterator
++ */
++ public MapIterator<K, V> mapIterator() {
++ return new ReferenceMapIterator<K, V>(this);
++ }
++
++ /**
++ * Returns a set view of this map's entries.
++ * An iterator returned entry is valid until <code>next()</code> is called again.
++ * The <code>setValue()</code> method on the <code>toArray</code> entries has no effect.
++ *
++ * @return a set view of this map's entries
++ */
++ public Set<Map.Entry<K, V>> entrySet() {
++ if (entrySet == null) {
++ entrySet = new ReferenceEntrySet<K, V>(this);
++ }
++ return entrySet;
++ }
++
++ /**
++ * Returns a set view of this map's keys.
++ *
++ * @return a set view of this map's keys
++ */
++ public Set<K> keySet() {
++ if (keySet == null) {
++ keySet = new ReferenceKeySet<K, V>(this);
++ }
++ return keySet;
++ }
++
++ /**
++ * Returns a collection view of this map's values.
++ *
++ * @return a set view of this map's values
++ */
++ public Collection<V> values() {
++ if (values == null) {
++ values = new ReferenceValues<K, V>(this);
++ }
++ return values;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Purges stale mappings from this map before read operations.
++ * <p/>
++ * This implementation calls {@link #purge()} to maintain a consistent state.
++ */
++ protected void purgeBeforeRead() {
++ purge();
++ }
++
++ /**
++ * Purges stale mappings from this map before write operations.
++ * <p/>
++ * This implementation calls {@link #purge()} to maintain a consistent state.
++ */
++ protected void purgeBeforeWrite() {
++ purge();
++ }
++
++ /**
++ * Purges stale mappings from this map.
++ * <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.
++ */
++ protected void purge() {
++ Reference ref = queue.poll();
++ while (ref != null) {
++ purge(ref);
++ ref = queue.poll();
++ }
++ }
++
++ /**
++ * Purges the specified reference.
++ *
++ * @param ref the reference to purge
++ */
++ protected 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 = hashIndex(hash, data.length);
++ HashEntry<K, V> previous = null;
++ HashEntry<K, V> entry = data[index];
++ while (entry != null) {
++ if (((ReferenceEntry<K, V>) entry).purge(ref)) {
++ if (previous == null) {
++ data[index] = entry.next;
++ } else {
++ previous.next = entry.next;
++ }
++ this.size--;
++ return;
++ }
++ previous = entry;
++ entry = entry.next;
++ }
++
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the entry mapped to the key specified.
++ *
++ * @param key the key
++ * @return the entry, null if no match
++ */
++ protected HashEntry<K, V> getEntry(Object key) {
++ if (key == null) {
++ return null;
++ } else {
++ return super.getEntry(key);
++ }
++ }
++
++ /**
++ * Gets the hash code for a MapEntry.
++ * Subclasses can override this, for example to use the identityHashCode.
++ *
++ * @param key the key to get a hash code for, may be null
++ * @param value the value to get a hash code for, may be null
++ * @return the hash code, as per the MapEntry specification
++ */
++ protected int hashEntry(Object key, Object value) {
++ return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode());
++ }
++
++ /**
++ * Compares two keys, in internal converted form, to see if they are equal.
++ * <p/>
++ * This implementation converts the key from the entry to a real reference
++ * before comparison.
++ *
++ * @param key1 the first key to compare passed in from outside
++ * @param key2 the second key extracted from the entry via <code>entry.key</code>
++ * @return true if equal
++ */
++ protected boolean isEqualKey(Object key1, Object key2) {
++ //if ((key1 == null) && (key2 != null) || (key1 != null) || (key2 == null)) {
++ // return false;
++ //}
++ // GenericsNote: Conversion from reference handled by getKey() which replaced all .key references
++ //key2 = (keyType > HARD ? ((Reference) key2).get() : key2);
++ return (key1 == key2 || key1.equals(key2));
++ }
++
++ /**
++ * Creates a ReferenceEntry instead of a HashEntry.
++ *
++ * @param next the next entry in sequence
++ * @param hashCode the hash code to use
++ * @param key the key to store
++ * @param value the value to store
++ * @return the newly created entry
++ */
++ public HashEntry<K, V> createEntry(HashEntry<K, V> next, int hashCode, K key, V value) {
++ return new ReferenceEntry<K, V>(this, (ReferenceEntry<K, V>) next, hashCode, key, value);
++ }
++
++ /**
++ * Creates an entry set iterator.
++ *
++ * @return the entrySet iterator
++ */
++ protected Iterator<Map.Entry<K, V>> createEntrySetIterator() {
++ return new ReferenceEntrySetIterator<K, V>(this);
++ }
++
++ /**
++ * Creates an key set iterator.
++ *
++ * @return the keySet iterator
++ */
++ protected Iterator<K> createKeySetIterator() {
++ return new ReferenceKeySetIterator<K, V>(this);
++ }
++
++ /**
++ * Creates an values iterator.
++ *
++ * @return the values iterator
++ */
++ protected Iterator<V> createValuesIterator() {
++ return new ReferenceValuesIterator<K, V>(this);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * EntrySet implementation.
++ */
++ static class ReferenceEntrySet <K,V> extends EntrySet<K, V> {
++
++ protected ReferenceEntrySet(AbstractHashedMap<K, V> parent) {
++ super(parent);
++ }
++
++ public Object[] toArray() {
++ return toArray(new Object[0]);
++ }
++
++ public <T> T[] toArray(T[] arr) {
++ // special implementation to handle disappearing entries
++ ArrayList<Map.Entry<K, V>> list = new ArrayList<Map.Entry<K, V>>();
++ Iterator<Map.Entry<K, V>> iterator = iterator();
++ while (iterator.hasNext()) {
++ Map.Entry<K, V> e = iterator.next();
++ list.add(new DefaultMapEntry<K, V>(e.getKey(), e.getValue()));
++ }
++ return list.toArray(arr);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * KeySet implementation.
++ */
++ static class ReferenceKeySet <K,V> extends KeySet<K, V> {
++
++ protected ReferenceKeySet(AbstractHashedMap<K, V> parent) {
++ super(parent);
++ }
++
++ public Object[] toArray() {
++ return toArray(new Object[0]);
++ }
++
++ public <T> T[] toArray(T[] arr) {
++ // special implementation to handle disappearing keys
++ List<K> list = new ArrayList<K>(parent.size());
++ for (Iterator<K> it = iterator(); it.hasNext();) {
++ list.add(it.next());
++ }
++ return list.toArray(arr);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Values implementation.
++ */
++ static class ReferenceValues <K,V> extends Values<K, V> {
++
++ protected ReferenceValues(AbstractHashedMap<K, V> parent) {
++ super(parent);
++ }
++
++ public Object[] toArray() {
++ return toArray(new Object[0]);
++ }
++
++ public <T> T[] toArray(T[] arr) {
++ // special implementation to handle disappearing values
++ List<V> list = new ArrayList<V>(parent.size());
++ for (Iterator<V> it = iterator(); it.hasNext();) {
++ list.add(it.next());
++ }
++ return list.toArray(arr);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * A MapEntry implementation for the map.
++ * <p/>
++ * If getKey() or getValue() returns null, it means
++ * the mapping is stale and should be removed.
++ *
++ * @since Commons Collections 3.1
++ */
++ protected static class ReferenceEntry <K,V> extends HashEntry<K, V> {
++ /**
++ * The parent map
++ */
++ protected final AbstractReferenceMap<K, V> parent;
++
++ protected Reference<K> refKey;
++ protected Reference<V> refValue;
++
++ /**
++ * Creates a new entry object for the ReferenceMap.
++ *
++ * @param parent the parent map
++ * @param next the next entry in the hash bucket
++ * @param hashCode the hash code of the key
++ * @param key the key
++ * @param value the value
++ */
++ public ReferenceEntry(AbstractReferenceMap<K, V> parent, ReferenceEntry<K, V> next, int hashCode, K key, V value) {
++ super(next, hashCode, null, null);
++ this.parent = parent;
++ if (parent.keyType != HARD) {
++ refKey = toReference(parent.keyType, key, hashCode);
++ } else {
++ this.setKey(key);
++ }
++ if (parent.valueType != HARD) {
++ refValue = toReference(parent.valueType, value, hashCode); // the key hashCode is passed in deliberately
++ } else {
++ this.setValue(value);
++ }
++ }
++
++ /**
++ * Gets the key from the entry.
++ * This method dereferences weak and soft keys and thus may return null.
++ *
++ * @return the key, which may be null if it was garbage collected
++ */
++ public K getKey() {
++ return (parent.keyType > HARD) ? refKey.get() : super.getKey();
++ }
++
++ /**
++ * Gets the value from the entry.
++ * This method dereferences weak and soft value and thus may return null.
++ *
++ * @return the value, which may be null if it was garbage collected
++ */
++ public V getValue() {
++ return (parent.valueType > HARD) ? refValue.get() : super.getValue();
++ }
++
++ /**
++ * Sets the value of the entry.
++ *
++ * @param obj the object to store
++ * @return the previous value
++ */
++ public V setValue(V obj) {
++ V old = getValue();
++ if (parent.valueType > HARD) {
++ refValue.clear();
++ refValue = toReference(parent.valueType, obj, hashCode);
++ } else {
++ super.setValue(obj);
++ }
++ return old;
++ }
++
++ /**
++ * Compares this map entry to another.
++ * <p/>
++ * This implementation uses <code>isEqualKey</code> and
++ * <code>isEqualValue</code> on the main map for comparison.
++ *
++ * @param obj the other map entry to compare to
++ * @return true if equal, false if not
++ */
++ public boolean equals(Object obj) {
++ if (obj == this) {
++ return true;
++ }
++ if (obj instanceof Map.Entry == false) {
++ return false;
++ }
++
++ Map.Entry entry = (Map.Entry) obj;
++ Object entryKey = entry.getKey(); // convert to hard reference
++ Object entryValue = entry.getValue(); // convert to hard reference
++ if ((entryKey == null) || (entryValue == null)) {
++ return false;
++ }
++ // compare using map methods, aiding identity subclass
++ // note that key is direct access and value is via method
++ return parent.isEqualKey(entryKey, getKey()) && parent.isEqualValue(entryValue, getValue());
++ }
++
++ /**
++ * Gets the hashcode of the entry using temporary hard references.
++ * <p/>
++ * This implementation uses <code>hashEntry</code> on the main map.
++ *
++ * @return the hashcode of the entry
++ */
++ public int hashCode() {
++ return parent.hashEntry(getKey(), getValue());
++ }
++
++ /**
++ * 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
++ */
++ protected <T> Reference<T> toReference(int type, T referent, int hash) {
++ switch (type) {
++ case SOFT:
++ return new SoftRef<T>(hash, referent, parent.queue);
++ case WEAK:
++ return new WeakRef<T>(hash, referent, parent.queue);
++ default:
++ throw new Error("Attempt to create hard reference in ReferenceMap!");
++ }
++ }
++
++ /**
++ * Purges the specified reference
++ *
++ * @param ref the reference to purge
++ * @return true or false
++ */
++ boolean purge(Reference ref) {
++ boolean r = (parent.keyType > HARD) && (refKey == ref);
++ r = r || ((parent.valueType > HARD) && (refValue == ref));
++ if (r) {
++ if (parent.keyType > HARD) {
++ refKey.clear();
++ }
++ if (parent.valueType > HARD) {
++ refValue.clear();
++ } else if (parent.purgeValues) {
++ setValue(null);
++ }
++ }
++ return r;
++ }
++
++ /**
++ * Gets the next entry in the bucket.
++ *
++ * @return the next entry in the bucket
++ */
++ protected ReferenceEntry<K, V> next() {
++ return (ReferenceEntry<K, V>) next;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * The EntrySet iterator.
++ */
++ static class ReferenceIteratorBase <K,V> {
++ /**
++ * The parent map
++ */
++ final AbstractReferenceMap<K, V> parent;
++
++ // These fields keep track of where we are in the table.
++ int index;
++ ReferenceEntry<K, V> entry;
++ ReferenceEntry<K, V> 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.
++ K nextKey;
++ V nextValue;
++ K currentKey;
++ V currentValue;
++
++ int expectedModCount;
++
++ public ReferenceIteratorBase(AbstractReferenceMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ index = (parent.size() != 0 ? parent.data.length : 0);
++ // have to do this here! size() invocation above
++ // may have altered the modCount.
++ expectedModCount = parent.modCount;
++ }
++
++ public boolean hasNext() {
++ checkMod();
++ while (nextNull()) {
++ ReferenceEntry<K, V> e = entry;
++ int i = index;
++ while ((e == null) && (i > 0)) {
++ i--;
++ e = (ReferenceEntry<K, V>) parent.data[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 (parent.modCount != expectedModCount) {
++ throw new ConcurrentModificationException();
++ }
++ }
++
++ private boolean nextNull() {
++ return (nextKey == null) || (nextValue == null);
++ }
++
++ protected ReferenceEntry<K, V> nextEntry() {
++ checkMod();
++ if (nextNull() && !hasNext()) {
++ throw new NoSuchElementException();
++ }
++ previous = entry;
++ entry = entry.next();
++ currentKey = nextKey;
++ currentValue = nextValue;
++ nextKey = null;
++ nextValue = null;
++ return previous;
++ }
++
++ protected ReferenceEntry<K, V> currentEntry() {
++ checkMod();
++ return previous;
++ }
++
++ public ReferenceEntry<K, V> superNext() {
++ return nextEntry();
++ }
++
++ public void remove() {
++ checkMod();
++ if (previous == null) {
++ throw new IllegalStateException();
++ }
++ parent.remove(currentKey);
++ previous = null;
++ currentKey = null;
++ currentValue = null;
++ expectedModCount = parent.modCount;
++ }
++ }
++
++ /**
++ * The EntrySet iterator.
++ */
++ static class ReferenceEntrySetIterator <K,V> extends ReferenceIteratorBase<K, V> implements Iterator<Map.Entry<K, V>> {
++
++ public ReferenceEntrySetIterator(AbstractReferenceMap<K, V> abstractReferenceMap) {
++ super(abstractReferenceMap);
++ }
++
++ public ReferenceEntry<K, V> next() {
++ return superNext();
++ }
++
++ }
++
++ /**
++ * The keySet iterator.
++ */
++ static class ReferenceKeySetIterator <K,V> extends ReferenceIteratorBase<K, V> implements Iterator<K> {
++
++ ReferenceKeySetIterator(AbstractReferenceMap<K, V> parent) {
++ super(parent);
++ }
++
++ public K next() {
++ return nextEntry().getKey();
++ }
++ }
++
++ /**
++ * The values iterator.
++ */
++ static class ReferenceValuesIterator <K,V> extends ReferenceIteratorBase<K, V> implements Iterator<V> {
++
++ ReferenceValuesIterator(AbstractReferenceMap<K, V> parent) {
++ super(parent);
++ }
++
++ public V next() {
++ return nextEntry().getValue();
++ }
++ }
++
++ /**
++ * The MapIterator implementation.
++ */
++ static class ReferenceMapIterator <K,V> extends ReferenceIteratorBase<K, V> implements MapIterator<K, V> {
++
++ protected ReferenceMapIterator(AbstractReferenceMap<K, V> parent) {
++ super(parent);
++ }
++
++ public K next() {
++ return nextEntry().getKey();
++ }
++
++ public K getKey() {
++ HashEntry<K, V> current = currentEntry();
++ if (current == null) {
++ throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
++ }
++ return current.getKey();
++ }
++
++ public V getValue() {
++ HashEntry<K, V> current = currentEntry();
++ if (current == null) {
++ throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
++ }
++ return current.getValue();
++ }
++
++ public V setValue(V value) {
++ HashEntry<K, V> current = currentEntry();
++ if (current == null) {
++ throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
++ }
++ return current.setValue(value);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ // 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.
++
++ /**
++ * A soft reference holder.
++ */
++ static class SoftRef <T> extends SoftReference<T> {
++ /**
++ * the hashCode of the key (even if the reference points to a value)
++ */
++ private int hash;
++
++ public SoftRef(int hash, T r, ReferenceQueue q) {
++ super(r, q);
++ this.hash = hash;
++ }
++
++ public int hashCode() {
++ return hash;
++ }
++ }
++
++ /**
++ * A weak reference holder.
++ */
++ static class WeakRef <T> extends WeakReference<T> {
++ /**
++ * the hashCode of the key (even if the reference points to a value)
++ */
++ private int hash;
++
++ public WeakRef(int hash, T r, ReferenceQueue q) {
++ super(r, q);
++ this.hash = hash;
++ }
++
++ public int hashCode() {
++ return hash;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Replaces the superclass method to store the state of this class.
++ * <p/>
++ * Serialization is not one of the JDK's nicest topics. Normal serialization will
++ * initialise the superclass before the subclass. Sometimes however, this isn't
++ * what you want, as in this case the <code>put()</code> method on read can be
++ * affected by subclass state.
++ * <p/>
++ * The solution adopted here is to serialize the state data of this class in
++ * this protected method. This method must be called by the
++ * <code>writeObject()</code> of the first serializable subclass.
++ * <p/>
++ * Subclasses may override if they have a specific field that must be present
++ * on read before this implementation will work. Generally, the read determines
++ * what must be serialized here, if anything.
++ *
++ * @param out the output stream
++ */
++ protected void doWriteObject(ObjectOutputStream out) throws IOException {
++ out.writeInt(keyType);
++ out.writeInt(valueType);
++ out.writeBoolean(purgeValues);
++ out.writeFloat(loadFactor);
++ out.writeInt(data.length);
++ for (MapIterator it = mapIterator(); it.hasNext();) {
++ out.writeObject(it.next());
++ out.writeObject(it.getValue());
++ }
++ out.writeObject(null); // null terminate map
++ // do not call super.doWriteObject() as code there doesn't work for reference map
++ }
++
++ /**
++ * Replaces the superclassm method to read the state of this class.
++ * <p/>
++ * Serialization is not one of the JDK's nicest topics. Normal serialization will
++ * initialise the superclass before the subclass. Sometimes however, this isn't
++ * what you want, as in this case the <code>put()</code> method on read can be
++ * affected by subclass state.
++ * <p/>
++ * The solution adopted here is to deserialize the state data of this class in
++ * this protected method. This method must be called by the
++ * <code>readObject()</code> of the first serializable subclass.
++ * <p/>
++ * Subclasses may override if the subclass has a specific field that must be present
++ * before <code>put()</code> or <code>calculateThreshold()</code> will work correctly.
++ *
++ * @param in the input stream
++ */
++ protected void doReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ this.keyType = in.readInt();
++ this.valueType = in.readInt();
++ this.purgeValues = in.readBoolean();
++ this.loadFactor = in.readFloat();
++ int capacity = in.readInt();
++ init();
++ data = new HashEntry[capacity];
++ while (true) {
++ K key = (K) in.readObject();
++ if (key == null) {
++ break;
++ }
++ V value = (V) in.readObject();
++ put(key, value);
++ }
++ threshold = calculateThreshold(data.length, loadFactor);
++ // do not call super.doReadObject() as code there doesn't work for reference map
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/AbstractSortedMapDecorator.java
+@@ -0,0 +1,93 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import java.util.Comparator;
++import java.util.SortedMap;
++
++/**
++ * Provides a base decorator that enables additional functionality to be added
++ * to a Map via decoration.
++ * <p/>
++ * Methods are forwarded directly to the decorated map.
++ * <p/>
++ * This implementation does not perform any special processing with the map views.
++ * 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.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractSortedMapDecorator <K,V> extends AbstractMapDecorator<K, V> implements SortedMap<K, V> {
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ *
++ * @since Commons Collections 3.1
++ */
++ protected AbstractSortedMapDecorator() {
++ super();
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if the collection is null
++ */
++ public AbstractSortedMapDecorator(SortedMap<K, V> map) {
++ super(map);
++ }
++
++ /**
++ * Gets the map being decorated.
++ *
++ * @return the decorated map
++ */
++ protected SortedMap<K, V> getSortedMap() {
++ return (SortedMap<K, V>) map;
++ }
++
++ //-----------------------------------------------------------------------
++ public Comparator<? super K> comparator() {
++ return getSortedMap().comparator();
++ }
++
++ public K firstKey() {
++ return getSortedMap().firstKey();
++ }
++
++ public SortedMap<K, V> headMap(K toKey) {
++ return getSortedMap().headMap(toKey);
++ }
++
++ public K lastKey() {
++ return getSortedMap().lastKey();
++ }
++
++ public SortedMap<K, V> subMap(K fromKey, K toKey) {
++ return getSortedMap().subMap(fromKey, toKey);
++ }
++
++ public SortedMap<K, V> tailMap(K fromKey) {
++ return getSortedMap().tailMap(fromKey);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/CaseInsensitiveMap.java
+@@ -0,0 +1,168 @@
++// GenericsNote: Converted -- refactored heavily, and now must be a map of String -> ?.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Iterator;
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * A case-insensitive <code>Map</code>.
++ * <p/>
++ * As entries are added to the map, keys are converted to all lowercase. A new
++ * key is compared to existing keys by comparing <code>newKey.toLower()</code>
++ * to the lowercase values in the current <code>KeySet.</code>
++ * <p/>
++ * Null keys are supported.
++ * <p/>
++ * The <code>keySet()</code> method returns all lowercase keys, or nulls.
++ * <p/>
++ * Example:
++ * <pre><code>
++ * Map map = new CaseInsensitiveMap();
++ * map.put("One", "One");
++ * map.put("Two", "Two");
++ * map.put(null, "Three");
++ * map.put("one", "Four");
++ * </code></pre>
++ * creates a <code>CaseInsensitiveMap</code> with three entries.<br>
++ * <code>map.get(null)</code> returns <code>"Three"</code> and <code>map.get("ONE")</code>
++ * returns <code>"Four".</code> The <code>Set</code> returned by <code>keySet()</code>
++ * equals <code>{"one", "two", null}.</code>
++ *
++ * @author Matt Hall, John Watkinson, Commons-Collections team
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class CaseInsensitiveMap <V> extends AbstractHashedMap<String, V> implements Serializable, Cloneable {
++
++ /**
++ * Serialisation version
++ */
++ private static final long serialVersionUID = -7074655917369299456L;
++
++ /**
++ * Constructs a new empty map with default size and load factor.
++ */
++ public CaseInsensitiveMap() {
++ super(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_THRESHOLD);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity.
++ *
++ * @param initialCapacity the initial capacity
++ * @throws IllegalArgumentException if the initial capacity is less than one
++ */
++ public CaseInsensitiveMap(int initialCapacity) {
++ super(initialCapacity);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity and
++ * load factor.
++ *
++ * @param initialCapacity the initial capacity
++ * @param loadFactor the load factor
++ * @throws IllegalArgumentException if the initial capacity is less than one
++ * @throws IllegalArgumentException if the load factor is less than zero
++ */
++ public CaseInsensitiveMap(int initialCapacity, float loadFactor) {
++ super(initialCapacity, loadFactor);
++ }
++
++ /**
++ * Constructor copying elements from another map.
++ * <p/>
++ * Keys will be converted to lower case strings, which may cause
++ * some entries to be removed (if string representation of keys differ
++ * only by character case).
++ *
++ * @param map the map to copy
++ * @throws NullPointerException if the map is null
++ */
++ public CaseInsensitiveMap(Map<? extends String, ? extends V> map) {
++ super(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Converts keys to lower case.
++ * <p/>
++ * Returns null if key is null.
++ *
++ * @param key the key convert
++ * @return the converted key
++ */
++ protected String convertKey(String key) {
++ if (key != null) {
++ return key.toString().toLowerCase();
++ } else {
++ return null;
++ }
++ }
++
++ @Override public V get(Object key) {
++ if (!(key instanceof String)) {
++ return super.get(key);
++ }
++ return super.get(convertKey((String) key));
++ }
++
++ @Override public V put(String s, V v) {
++ return super.put(convertKey(s), v);
++ }
++
++ @Override public void putAll(Map<? extends String, ? extends V> map) {
++ Set entries = map.entrySet();
++ for (Iterator<Entry<? extends String, ? extends V>> iterator = entries.iterator(); iterator.hasNext();) {
++ Entry<? extends String, ? extends V> entry = iterator.next();
++ put(entry.getKey(), entry.getValue());
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Clones the map without cloning the keys or values.
++ *
++ * @return a shallow clone
++ */
++ public Object clone() {
++ return super.clone();
++ }
++
++ /**
++ * Write the map out using a custom routine.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ doWriteObject(out);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ doReadObject(in);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/CompositeMap.java
+@@ -0,0 +1,523 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.CollectionUtils;
++import org.apache.commons.collections15.collection.CompositeCollection;
++import org.apache.commons.collections15.set.CompositeSet;
++
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * Decorates a map of other maps to provide a single unified view.
++ * <p/>
++ * Changes made to this map will actually be made on the decorated map.
++ * Add and remove operations require the use of a pluggable strategy. If no
++ * strategy is provided then add and remove are unsupported.
++ *
++ * @author Matt Hall, John Watkinson, Brian McCallister
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class CompositeMap <K,V> implements Map<K, V> {
++
++ /**
++ * Array of all maps in the composite
++ */
++ private Map[] composite;
++
++ /**
++ * Handle mutation operations
++ */
++ private MapMutator<K, V> mutator;
++
++ /**
++ * Create a new, empty, CompositeMap.
++ */
++ public CompositeMap() {
++ this(new Map[]{}, null);
++ }
++
++ /**
++ * Create a new CompositeMap with two composited Map instances.
++ *
++ * @param one the first Map to be composited
++ * @param two the second Map to be composited
++ * @throws IllegalArgumentException if there is a key collision
++ */
++ public CompositeMap(Map<? extends K, ? extends V> one, Map<? extends K, ? extends V> two) {
++ this(new Map[]{one, two}, null);
++ }
++
++ /**
++ * Create a new CompositeMap with two composited Map instances.
++ *
++ * @param one the first Map to be composited
++ * @param two the second Map to be composited
++ * @param mutator MapMutator to be used for mutation operations
++ */
++ public CompositeMap(Map<? extends K, ? extends V> one, Map<? extends K, ? extends V> two, MapMutator<K, V> mutator) {
++ this(new Map[]{one, two}, mutator);
++ }
++
++ /**
++ * Create a new CompositeMap which composites all of the Map instances in the
++ * argument. It copies the argument array, it does not use it directly.
++ *
++ * @param composite the Maps to be composited
++ * @throws IllegalArgumentException if there is a key collision
++ */
++ public CompositeMap(Map[] composite) {
++ this(composite, null);
++ }
++
++ /**
++ * Create a new CompositeMap which composites all of the Map instances in the
++ * argument. It copies the argument array, it does not use it directly.
++ *
++ * @param composite Maps to be composited
++ * @param mutator MapMutator to be used for mutation operations
++ */
++ public CompositeMap(Map[] composite, MapMutator<K, V> mutator) {
++ this.mutator = mutator;
++ this.composite = new Map[0];
++ for (int i = composite.length - 1; i >= 0; --i) {
++ this.addComposited(composite[i]);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Specify the MapMutator to be used by mutation operations.
++ *
++ * @param mutator the MapMutator to be used for mutation delegation
++ */
++ public void setMutator(MapMutator<K, V> mutator) {
++ this.mutator = mutator;
++ }
++
++ /**
++ * Add an additional Map to the composite.
++ *
++ * @param map the Map to be added to the composite
++ * @throws IllegalArgumentException if there is a key collision and there is no
++ * MapMutator set to handle it.
++ */
++ public synchronized void addComposited(Map<? extends K, ? extends V> map) throws IllegalArgumentException {
++ for (int i = composite.length - 1; i >= 0; --i) {
++ Collection<K> intersect = (Collection<K>) CollectionUtils.intersection(this.composite[i].keySet(), map.keySet());
++ if (intersect.size() != 0) {
++ if (this.mutator == null) {
++ throw new IllegalArgumentException("Key collision adding Map to CompositeMap");
++ } else {
++ this.mutator.resolveCollision(this, this.composite[i], map, intersect);
++ }
++ }
++ }
++ Map[] temp = new Map[this.composite.length + 1];
++ System.arraycopy(this.composite, 0, temp, 0, this.composite.length);
++ temp[temp.length - 1] = map;
++ this.composite = temp;
++ }
++
++ /**
++ * Remove a Map from the composite.
++ *
++ * @param map the Map to be removed from the composite
++ * @return The removed Map or <code>null</code> if map is not in the composite
++ */
++ public synchronized Map<? extends K, ? extends V> removeComposited(Map<? extends K, ? extends V> map) {
++ int size = this.composite.length;
++ for (int i = 0; i < size; ++i) {
++ if (this.composite[i].equals(map)) {
++ Map[] temp = new Map[size - 1];
++ System.arraycopy(this.composite, 0, temp, 0, i);
++ System.arraycopy(this.composite, i + 1, temp, i, size - i - 1);
++ this.composite = temp;
++ return map;
++ }
++ }
++ return null;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Calls <code>clear()</code> on all composited Maps.
++ *
++ * @throws UnsupportedOperationException if any of the composited Maps do not support clear()
++ */
++ public void clear() {
++ for (int i = this.composite.length - 1; i >= 0; --i) {
++ this.composite[i].clear();
++ }
++ }
++
++ /**
++ * Returns <tt>true</tt> if this map contains a mapping for the specified
++ * key. More formally, returns <tt>true</tt> if and only if
++ * this map contains at a mapping for a key <tt>k</tt> such that
++ * <tt>(key==null ? k==null : key.equals(k))</tt>. (There can be
++ * at most one such mapping.)
++ *
++ * @param key key whose presence in this map is to be tested.
++ * @return <tt>true</tt> if this map contains a mapping for the specified
++ * key.
++ * @throws ClassCastException if the key is of an inappropriate type for
++ * this map (optional).
++ * @throws NullPointerException if the key is <tt>null</tt> and this map
++ * does not not permit <tt>null</tt> keys (optional).
++ */
++ public boolean containsKey(Object key) {
++ for (int i = this.composite.length - 1; i >= 0; --i) {
++ if (this.composite[i].containsKey(key)) {
++ return true;
++ }
++ }
++ return false;
++ }
++
++ /**
++ * Returns <tt>true</tt> if this map maps one or more keys to the
++ * specified value. More formally, returns <tt>true</tt> if and only if
++ * this map contains at least one mapping to a value <tt>v</tt> such that
++ * <tt>(value==null ? v==null : value.equals(v))</tt>. This operation
++ * will probably require time linear in the map size for most
++ * implementations of the <tt>Map</tt> interface.
++ *
++ * @param value value whose presence in this map is to be tested.
++ * @return <tt>true</tt> if this map maps one or more keys to the
++ * specified value.
++ * @throws ClassCastException if the value is of an inappropriate type for
++ * this map (optional).
++ * @throws NullPointerException if the value is <tt>null</tt> and this map
++ * does not not permit <tt>null</tt> values (optional).
++ */
++ public boolean containsValue(Object value) {
++ for (int i = this.composite.length - 1; i >= 0; --i) {
++ if (this.composite[i].containsValue(value)) {
++ return true;
++ }
++ }
++ return false;
++ }
++
++ /**
++ * Returns a set view of the mappings contained in this map. Each element
++ * in the returned set is a <code>Map.Entry</code>. The set is backed by the
++ * map, so changes to the map are reflected in the set, and vice-versa.
++ * If the map is modified while an iteration over the set is in progress,
++ * the results of the iteration are undefined. The set supports element
++ * removal, which removes the corresponding mapping from the map, via the
++ * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>, <tt>removeAll</tt>,
++ * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not support
++ * the <tt>add</tt> or <tt>addAll</tt> operations.
++ * <p/>
++ * This implementation returns a <code>CompositeSet</code> which
++ * composites the entry sets from all of the composited maps.
++ *
++ * @return a set view of the mappings contained in this map.
++ * @see CompositeSet
++ */
++ public Set entrySet() {
++ CompositeSet<Map.Entry<K, V>> entries = new CompositeSet<Map.Entry<K, V>>();
++ for (int i = this.composite.length - 1; i >= 0; --i) {
++ entries.addComposited(this.composite[i].entrySet());
++ }
++ return entries;
++ }
++
++ /**
++ * Returns the value to which this map maps the specified key. Returns
++ * <tt>null</tt> if the map contains no mapping for this key. A return
++ * value of <tt>null</tt> does not <i>necessarily</i> indicate that the
++ * map contains no mapping for the key; it's also possible that the map
++ * explicitly maps the key to <tt>null</tt>. The <tt>containsKey</tt>
++ * operation may be used to distinguish these two cases.
++ * <p/>
++ * <p>More formally, if this map contains a mapping from a key
++ * <tt>k</tt> to a value <tt>v</tt> such that <tt>(key==null ? k==null :
++ * key.equals(k))</tt>, then this method returns <tt>v</tt>; otherwise
++ * it returns <tt>null</tt>. (There can be at most one such mapping.)
++ *
++ * @param key key whose associated value is to be returned.
++ * @return the value to which this map maps the specified key, or
++ * <tt>null</tt> if the map contains no mapping for this key.
++ * @throws ClassCastException if the key is of an inappropriate type for
++ * this map (optional).
++ * @throws NullPointerException key is <tt>null</tt> and this map does not
++ * not permit <tt>null</tt> keys (optional).
++ * @see #containsKey(Object)
++ */
++ public V get(Object key) {
++ for (int i = this.composite.length - 1; i >= 0; --i) {
++ if (this.composite[i].containsKey(key)) {
++ return (V) this.composite[i].get(key);
++ }
++ }
++ return null;
++ }
++
++ /**
++ * Returns <tt>true</tt> if this map contains no key-value mappings.
++ *
++ * @return <tt>true</tt> if this map contains no key-value mappings.
++ */
++ public boolean isEmpty() {
++ for (int i = this.composite.length - 1; i >= 0; --i) {
++ if (!this.composite[i].isEmpty()) {
++ return false;
++ }
++ }
++ return true;
++ }
++
++ /**
++ * Returns a set view of the keys contained in this map. The set is
++ * backed by the map, so changes to the map are reflected in the set, and
++ * vice-versa. If the map is modified while an iteration over the set is
++ * in progress, the results of the iteration are undefined. The set
++ * supports element removal, which removes the corresponding mapping from
++ * the map, via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
++ * <tt>removeAll</tt> <tt>retainAll</tt>, and <tt>clear</tt> operations.
++ * It does not support the add or <tt>addAll</tt> operations.
++ * <p/>
++ * This implementation returns a <code>CompositeSet</code> which
++ * composites the key sets from all of the composited maps.
++ *
++ * @return a set view of the keys contained in this map.
++ */
++ public Set keySet() {
++ CompositeSet<K> keys = new CompositeSet<K>();
++ for (int i = this.composite.length - 1; i >= 0; --i) {
++ keys.addComposited(this.composite[i].keySet());
++ }
++ return keys;
++ }
++
++ /**
++ * Associates the specified value with the specified key in this map
++ * (optional operation). If the map previously contained a mapping for
++ * this key, the old value is replaced by the specified value. (A map
++ * <tt>m</tt> is said to contain a mapping for a key <tt>k</tt> if and only
++ * if {@link #containsKey(Object) m.containsKey(k)} would return
++ * <tt>true</tt>.))
++ *
++ * @param key key with which the specified value is to be associated.
++ * @param value value to be associated with the specified key.
++ * @return previous value associated with specified key, or <tt>null</tt>
++ * if there was no mapping for key. A <tt>null</tt> return can
++ * also indicate that the map previously associated <tt>null</tt>
++ * with the specified key, if the implementation supports
++ * <tt>null</tt> values.
++ * @throws UnsupportedOperationException if no MapMutator has been specified
++ * @throws ClassCastException if the class of the specified key or value
++ * prevents it from being stored in this map.
++ * @throws IllegalArgumentException if some aspect of this key or value
++ * prevents it from being stored in this map.
++ * @throws NullPointerException this map does not permit <tt>null</tt>
++ * keys or values, and the specified key or value is
++ * <tt>null</tt>.
++ */
++ public V put(K key, V value) {
++ if (this.mutator == null) {
++ throw new UnsupportedOperationException("No mutator specified");
++ }
++ return this.mutator.put(this, this.composite, key, value);
++ }
++
++ /**
++ * Copies all of the mappings from the specified map to this map
++ * (optional operation). The effect of this call is equivalent to that
++ * of calling {@link #put(Object,Object) put(k, v)} on this map once
++ * for each mapping from key <tt>k</tt> to value <tt>v</tt> in the
++ * specified map. The behavior of this operation is unspecified if the
++ * specified map is modified while the operation is in progress.
++ *
++ * @param map Mappings to be stored in this map.
++ * @throws UnsupportedOperationException if the <tt>putAll</tt> method is
++ * not supported by this map.
++ * @throws ClassCastException if the class of a key or value in the
++ * specified map prevents it from being stored in this map.
++ * @throws IllegalArgumentException some aspect of a key or value in the
++ * specified map prevents it from being stored in this map.
++ * @throws NullPointerException the specified map is <tt>null</tt>, or if
++ * this map does not permit <tt>null</tt> keys or values, and the
++ * specified map contains <tt>null</tt> keys or values.
++ */
++ public void putAll(Map<? extends K, ? extends V> map) {
++ if (this.mutator == null) {
++ throw new UnsupportedOperationException("No mutator specified");
++ }
++ this.mutator.putAll(this, this.composite, map);
++ }
++
++ /**
++ * Removes the mapping for this key from this map if it is present
++ * (optional operation). More formally, if this map contains a mapping
++ * from key <tt>k</tt> to value <tt>v</tt> such that
++ * <code>(key==null ? k==null : key.equals(k))</code>, that mapping
++ * is removed. (The map can contain at most one such mapping.)
++ * <p/>
++ * <p>Returns the value to which the map previously associated the key, or
++ * <tt>null</tt> if the map contained no mapping for this key. (A
++ * <tt>null</tt> return can also indicate that the map previously
++ * associated <tt>null</tt> with the specified key if the implementation
++ * supports <tt>null</tt> values.) The map will not contain a mapping for
++ * the specified key once the call returns.
++ *
++ * @param key key whose mapping is to be removed from the map.
++ * @return previous value associated with specified key, or <tt>null</tt>
++ * if there was no mapping for key.
++ * @throws ClassCastException if the key is of an inappropriate type for
++ * the composited map (optional).
++ * @throws NullPointerException if the key is <tt>null</tt> and the composited map
++ * does not not permit <tt>null</tt> keys (optional).
++ * @throws UnsupportedOperationException if the <tt>remove</tt> method is
++ * not supported by the composited map containing the key
++ */
++ public V remove(Object key) {
++ for (int i = this.composite.length - 1; i >= 0; --i) {
++ if (this.composite[i].containsKey(key)) {
++ return (V) this.composite[i].remove(key);
++ }
++ }
++ return null;
++ }
++
++ /**
++ * Returns the number of key-value mappings in this map. If the
++ * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
++ * <tt>Integer.MAX_VALUE</tt>.
++ *
++ * @return the number of key-value mappings in this map.
++ */
++ public int size() {
++ int size = 0;
++ for (int i = this.composite.length - 1; i >= 0; --i) {
++ size += this.composite[i].size();
++ }
++ return size;
++ }
++
++ /**
++ * Returns a collection view of the values contained in this map. The
++ * collection is backed by the map, so changes to the map are reflected in
++ * the collection, and vice-versa. If the map is modified while an
++ * iteration over the collection is in progress, the results of the
++ * iteration are undefined. The collection supports element removal,
++ * which removes the corresponding mapping from the map, via the
++ * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
++ * <tt>removeAll</tt>, <tt>retainAll</tt> and <tt>clear</tt> operations.
++ * It does not support the add or <tt>addAll</tt> operations.
++ *
++ * @return a collection view of the values contained in this map.
++ */
++ public Collection<V> values() {
++ CompositeCollection<V> keys = new CompositeCollection<V>();
++ for (int i = this.composite.length - 1; i >= 0; --i) {
++ keys.addComposited(this.composite[i].values());
++ }
++ return keys;
++ }
++
++ /**
++ * Checks if this Map equals another as per the Map specification.
++ *
++ * @param obj the object to compare to
++ * @return true if the maps are equal
++ */
++ public boolean equals(Object obj) {
++ if (obj instanceof Map) {
++ Map map = (Map) obj;
++ return (this.entrySet().equals(map.entrySet()));
++ }
++ return false;
++ }
++
++ /**
++ * Gets a hash code for the Map as per the Map specification.
++ */
++ public int hashCode() {
++ int code = 0;
++ for (Iterator i = this.entrySet().iterator(); i.hasNext();) {
++ code += i.next().hashCode();
++ }
++ return code;
++ }
++
++ /**
++ * This interface allows definition for all of the indeterminate
++ * mutators in a CompositeMap, as well as providing a hook for
++ * callbacks on key collisions.
++ */
++ public static interface MapMutator <K,V> {
++ /**
++ * Called when adding a new Composited Map results in a
++ * key collision.
++ *
++ * @param composite the CompositeMap with the collision
++ * @param existing the Map already in the composite which contains the
++ * offending key
++ * @param added the Map being added
++ * @param intersect the intersection of the keysets of the existing and added maps
++ */
++ public void resolveCollision(CompositeMap<K, V> composite, Map<? extends K, ? extends V> existing, Map<? extends K, ? extends V> added, Collection<K> intersect);
++
++ /**
++ * Called when the CompositeMap.put() method is invoked.
++ *
++ * @param map the CompositeMap which is being modified
++ * @param composited array of Maps in the CompositeMap being modified
++ * @param key key with which the specified value is to be associated.
++ * @param value value to be associated with the specified key.
++ * @return previous value associated with specified key, or <tt>null</tt>
++ * if there was no mapping for key. A <tt>null</tt> return can
++ * also indicate that the map previously associated <tt>null</tt>
++ * with the specified key, if the implementation supports
++ * <tt>null</tt> values.
++ * @throws UnsupportedOperationException if not defined
++ * @throws ClassCastException if the class of the specified key or value
++ * prevents it from being stored in this map.
++ * @throws IllegalArgumentException if some aspect of this key or value
++ * prevents it from being stored in this map.
++ * @throws NullPointerException this map does not permit <tt>null</tt>
++ * keys or values, and the specified key or value is
++ * <tt>null</tt>.
++ */
++ public V put(CompositeMap<K, V> map, Map[] composited, K key, V value);
++
++ /**
++ * Called when the CompositeMap.putAll() method is invoked.
++ *
++ * @param map the CompositeMap which is being modified
++ * @param composited array of Maps in the CompositeMap being modified
++ * @param mapToAdd Mappings to be stored in this CompositeMap
++ * @throws UnsupportedOperationException if not defined
++ * @throws ClassCastException if the class of the specified key or value
++ * prevents it from being stored in this map.
++ * @throws IllegalArgumentException if some aspect of this key or value
++ * prevents it from being stored in this map.
++ * @throws NullPointerException this map does not permit <tt>null</tt>
++ * keys or values, and the specified key or value is
++ * <tt>null</tt>.
++ */
++ public void putAll(CompositeMap<K, V> map, Map[] composited, Map<? extends K, ? extends V> mapToAdd);
++ }
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/FastHashMap.java
+@@ -0,0 +1,711 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import java.util.*;
++
++/**
++ * <p>A customized implementation of <code>java.util.HashMap</code> designed
++ * to operate in a multithreaded environment where the large majority of
++ * method calls are read-only, instead of structural changes. When operating
++ * in "fast" mode, read calls are non-synchronized and write calls perform the
++ * following steps:</p>
++ * <ul>
++ * <li>Clone the existing collection
++ * <li>Perform the modification on the clone
++ * <li>Replace the existing collection with the (modified) clone
++ * </ul>
++ * <p>When first created, objects of this class default to "slow" mode, where
++ * all accesses of any type are synchronized but no cloning takes place. This
++ * is appropriate for initially populating the collection, followed by a switch
++ * to "fast" mode (by calling <code>setFast(true)</code>) after initialization
++ * is complete.</p>
++ * <p/>
++ * <p><strong>NOTE</strong>: If you are creating and accessing a
++ * <code>HashMap</code> only within a single thread, you should use
++ * <code>java.util.HashMap</code> directly (with no synchronization), for
++ * maximum performance.</p>
++ * <p/>
++ * <p><strong>NOTE</strong>: <i>This class is not cross-platform.
++ * Using it may cause unexpected failures on some architectures.</i>
++ * It suffers from the same problems as the double-checked locking idiom.
++ * In particular, the instruction that clones the internal collection and the
++ * instruction that sets the internal reference to the clone can be executed
++ * or perceived out-of-order. This means that any read operation might fail
++ * unexpectedly, as it may be reading the state of the internal collection
++ * before the internal collection is fully formed.
++ * For more information on the double-checked locking idiom, see the
++ * <a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">
++ * Double-Checked Locking Idiom Is Broken Declaration</a>.</p>
++ *
++ * @author Craig R. McClanahan
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 1.0
++ */
++public class FastHashMap <K,V> extends HashMap<K, V> {
++
++ /**
++ * The underlying map we are managing.
++ */
++ protected HashMap<K, V> map = null;
++
++ /**
++ * Are we currently operating in "fast" mode?
++ */
++ protected boolean fast = false;
++
++ // Constructors
++ // ----------------------------------------------------------------------
++
++ /**
++ * Construct an empty map.
++ */
++ public FastHashMap() {
++ super();
++ this.map = new HashMap<K, V>();
++ }
++
++ /**
++ * Construct an empty map with the specified capacity.
++ *
++ * @param capacity the initial capacity of the empty map
++ */
++ public FastHashMap(int capacity) {
++ super();
++ this.map = new HashMap<K, V>(capacity);
++ }
++
++ /**
++ * Construct an empty map with the specified capacity and load factor.
++ *
++ * @param capacity the initial capacity of the empty map
++ * @param factor the load factor of the new map
++ */
++ public FastHashMap(int capacity, float factor) {
++ super();
++ this.map = new HashMap<K, V>(capacity, factor);
++ }
++
++ /**
++ * Construct a new map with the same mappings as the specified map.
++ *
++ * @param map the map whose mappings are to be copied
++ */
++ public FastHashMap(Map map) {
++ super();
++ this.map = new HashMap<K, V>(map);
++ }
++
++
++ // Property access
++ // ----------------------------------------------------------------------
++
++ /**
++ * Returns true if this map is operating in fast mode.
++ *
++ * @return true if this map is operating in fast mode
++ */
++ public boolean getFast() {
++ return (this.fast);
++ }
++
++ /**
++ * Sets whether this map is operating in fast mode.
++ *
++ * @param fast true if this map should operate in fast mode
++ */
++ public void setFast(boolean fast) {
++ this.fast = fast;
++ }
++
++
++ // Map access
++ // ----------------------------------------------------------------------
++ // These methods can forward straight to the wrapped Map in 'fast' mode.
++ // (because they are query methods)
++
++ /**
++ * Return the value to which this map maps the specified key. Returns
++ * <code>null</code> if the map contains no mapping for this key, or if
++ * there is a mapping with a value of <code>null</code>. Use the
++ * <code>containsKey()</code> method to disambiguate these cases.
++ *
++ * @param key the key whose value is to be returned
++ * @return the value mapped to that key, or null
++ */
++ public V get(Object key) {
++ if (fast) {
++ return (map.get(key));
++ } else {
++ synchronized (map) {
++ return (map.get(key));
++ }
++ }
++ }
++
++ /**
++ * Return the number of key-value mappings in this map.
++ *
++ * @return the current size of the map
++ */
++ public int size() {
++ if (fast) {
++ return (map.size());
++ } else {
++ synchronized (map) {
++ return (map.size());
++ }
++ }
++ }
++
++ /**
++ * Return <code>true</code> if this map contains no mappings.
++ *
++ * @return is the map currently empty
++ */
++ public boolean isEmpty() {
++ if (fast) {
++ return (map.isEmpty());
++ } else {
++ synchronized (map) {
++ return (map.isEmpty());
++ }
++ }
++ }
++
++ /**
++ * Return <code>true</code> if this map contains a mapping for the
++ * specified key.
++ *
++ * @param key the key to be searched for
++ * @return true if the map contains the key
++ */
++ public boolean containsKey(Object key) {
++ if (fast) {
++ return (map.containsKey(key));
++ } else {
++ synchronized (map) {
++ return (map.containsKey(key));
++ }
++ }
++ }
++
++ /**
++ * Return <code>true</code> if this map contains one or more keys mapping
++ * to the specified value.
++ *
++ * @param value the value to be searched for
++ * @return true if the map contains the value
++ */
++ public boolean containsValue(Object value) {
++ if (fast) {
++ return (map.containsValue(value));
++ } else {
++ synchronized (map) {
++ return (map.containsValue(value));
++ }
++ }
++ }
++
++ // Map modification
++ // ----------------------------------------------------------------------
++ // These methods perform special behaviour in 'fast' mode.
++ // The map is cloned, updated and then assigned back.
++ // See the comments at the top as to why this won't always work.
++
++ /**
++ * Associate the specified value with the specified key in this map.
++ * If the map previously contained a mapping for this key, the old
++ * value is replaced and returned.
++ *
++ * @param key the key with which the value is to be associated
++ * @param value the value to be associated with this key
++ * @return the value previously mapped to the key, or null
++ */
++ public V put(K key, V value) {
++ if (fast) {
++ synchronized (this) {
++ HashMap<K, V> temp = (HashMap<K, V>) map.clone();
++ V result = temp.put(key, value);
++ map = temp;
++ return (result);
++ }
++ } else {
++ synchronized (map) {
++ return (map.put(key, value));
++ }
++ }
++ }
++
++ /**
++ * Copy all of the mappings from the specified map to this one, replacing
++ * any mappings with the same keys.
++ *
++ * @param in the map whose mappings are to be copied
++ */
++ public void putAll(Map<? extends K, ? extends V> in) {
++ if (fast) {
++ synchronized (this) {
++ HashMap<K, V> temp = (HashMap<K, V>) map.clone();
++ temp.putAll(in);
++ map = temp;
++ }
++ } else {
++ synchronized (map) {
++ map.putAll(in);
++ }
++ }
++ }
++
++ /**
++ * Remove any mapping for this key, and return any previously
++ * mapped value.
++ *
++ * @param key the key whose mapping is to be removed
++ * @return the value removed, or null
++ */
++ public V remove(Object key) {
++ if (fast) {
++ synchronized (this) {
++ HashMap<K, V> temp = (HashMap<K, V>) map.clone();
++ V result = temp.remove(key);
++ map = temp;
++ return (result);
++ }
++ } else {
++ synchronized (map) {
++ return (map.remove(key));
++ }
++ }
++ }
++
++ /**
++ * Remove all mappings from this map.
++ */
++ public void clear() {
++ if (fast) {
++ synchronized (this) {
++ map = new HashMap<K, V>();
++ }
++ } else {
++ synchronized (map) {
++ map.clear();
++ }
++ }
++ }
++
++ // Basic object methods
++ // ----------------------------------------------------------------------
++
++ /**
++ * Compare the specified object with this list for equality. This
++ * implementation uses exactly the code that is used to define the
++ * list equals function in the documentation for the
++ * <code>Map.equals</code> method.
++ *
++ * @param o the object to be compared to this list
++ * @return true if the two maps are equal
++ */
++ public boolean equals(Object o) {
++ // Simple tests that require no synchronization
++ if (o == this) {
++ return (true);
++ } else if (!(o instanceof Map)) {
++ return (false);
++ }
++ Map mo = (Map) o;
++
++ // Compare the two maps for equality
++ if (fast) {
++ if (mo.size() != map.size()) {
++ return (false);
++ }
++ Iterator i = map.entrySet().iterator();
++ while (i.hasNext()) {
++ Map.Entry e = (Map.Entry) i.next();
++ Object key = e.getKey();
++ Object value = e.getValue();
++ if (value == null) {
++ if (!(mo.get(key) == null && mo.containsKey(key))) {
++ return (false);
++ }
++ } else {
++ if (!value.equals(mo.get(key))) {
++ return (false);
++ }
++ }
++ }
++ return (true);
++
++ } else {
++ synchronized (map) {
++ if (mo.size() != map.size()) {
++ return (false);
++ }
++ Iterator i = map.entrySet().iterator();
++ while (i.hasNext()) {
++ Map.Entry e = (Map.Entry) i.next();
++ Object key = e.getKey();
++ Object value = e.getValue();
++ if (value == null) {
++ if (!(mo.get(key) == null && mo.containsKey(key))) {
++ return (false);
++ }
++ } else {
++ if (!value.equals(mo.get(key))) {
++ return (false);
++ }
++ }
++ }
++ return (true);
++ }
++ }
++ }
++
++ /**
++ * Return the hash code value for this map. This implementation uses
++ * exactly the code that is used to define the list hash function in the
++ * documentation for the <code>Map.hashCode</code> method.
++ *
++ * @return suitable integer hash code
++ */
++ public int hashCode() {
++ if (fast) {
++ int h = 0;
++ Iterator<Map.Entry<K, V>> i = map.entrySet().iterator();
++ while (i.hasNext()) {
++ h += i.next().hashCode();
++ }
++ return (h);
++ } else {
++ synchronized (map) {
++ int h = 0;
++ Iterator<Map.Entry<K, V>> i = map.entrySet().iterator();
++ while (i.hasNext()) {
++ h += i.next().hashCode();
++ }
++ return (h);
++ }
++ }
++ }
++
++ /**
++ * Return a shallow copy of this <code>FastHashMap</code> instance.
++ * The keys and values themselves are not copied.
++ *
++ * @return a clone of this map
++ */
++ public FastHashMap<K, V> clone() {
++ FastHashMap<K, V> results = null;
++ if (fast) {
++ results = new FastHashMap<K, V>(map);
++ } else {
++ synchronized (map) {
++ results = new FastHashMap<K, V>(map);
++ }
++ }
++ results.setFast(getFast());
++ return (results);
++ }
++
++ // Map views
++ // ----------------------------------------------------------------------
++
++ /**
++ * Return a collection view of the mappings contained in this map. Each
++ * element in the returned collection is a <code>Map.Entry</code>.
++ */
++ public Set<Map.Entry<K, V>> entrySet() {
++ return new EntrySet();
++ }
++
++ /**
++ * Return a set view of the keys contained in this map.
++ */
++ public Set<K> keySet() {
++ return new KeySet();
++ }
++
++ /**
++ * Return a collection view of the values contained in this map.
++ */
++ public Collection<V> values() {
++ return new Values();
++ }
++
++ // Map view inner classes
++ // ----------------------------------------------------------------------
++
++ /**
++ * Abstract collection implementation shared by keySet(), values() and entrySet().
++ */
++ private abstract class CollectionView <E> implements Collection<E> {
++
++ public CollectionView() {
++ }
++
++ protected abstract Collection<E> get(Map<K, V> map);
++
++ protected abstract E iteratorNext(Map.Entry<K, V> entry);
++
++
++ public void clear() {
++ if (fast) {
++ synchronized (FastHashMap.this) {
++ map = new HashMap<K, V>();
++ }
++ } else {
++ synchronized (map) {
++ get(map).clear();
++ }
++ }
++ }
++
++ public boolean remove(Object o) {
++ if (fast) {
++ synchronized (FastHashMap.this) {
++ HashMap temp = (HashMap) map.clone();
++ boolean r = get(temp).remove(o);
++ map = temp;
++ return r;
++ }
++ } else {
++ synchronized (map) {
++ return get(map).remove(o);
++ }
++ }
++ }
++
++ public boolean removeAll(Collection<?> o) {
++ if (fast) {
++ synchronized (FastHashMap.this) {
++ HashMap temp = (HashMap) map.clone();
++ boolean r = get(temp).removeAll(o);
++ map = temp;
++ return r;
++ }
++ } else {
++ synchronized (map) {
++ return get(map).removeAll(o);
++ }
++ }
++ }
++
++ public boolean retainAll(Collection<?> o) {
++ if (fast) {
++ synchronized (FastHashMap.this) {
++ HashMap temp = (HashMap) map.clone();
++ boolean r = get(temp).retainAll(o);
++ map = temp;
++ return r;
++ }
++ } else {
++ synchronized (map) {
++ return get(map).retainAll(o);
++ }
++ }
++ }
++
++ public int size() {
++ if (fast) {
++ return get(map).size();
++ } else {
++ synchronized (map) {
++ return get(map).size();
++ }
++ }
++ }
++
++
++ public boolean isEmpty() {
++ if (fast) {
++ return get(map).isEmpty();
++ } else {
++ synchronized (map) {
++ return get(map).isEmpty();
++ }
++ }
++ }
++
++ public boolean contains(Object o) {
++ if (fast) {
++ return get(map).contains(o);
++ } else {
++ synchronized (map) {
++ return get(map).contains(o);
++ }
++ }
++ }
++
++ public boolean containsAll(Collection<?> o) {
++ if (fast) {
++ return get(map).containsAll(o);
++ } else {
++ synchronized (map) {
++ return get(map).containsAll(o);
++ }
++ }
++ }
++
++ public <T> T[] toArray(T[] o) {
++ if (fast) {
++ return get(map).toArray(o);
++ } else {
++ synchronized (map) {
++ return get(map).toArray(o);
++ }
++ }
++ }
++
++ public Object[] toArray() {
++ if (fast) {
++ return get(map).toArray();
++ } else {
++ synchronized (map) {
++ return get(map).toArray();
++ }
++ }
++ }
++
++
++ public boolean equals(Object o) {
++ if (o == this) return true;
++ if (fast) {
++ return get(map).equals(o);
++ } else {
++ synchronized (map) {
++ return get(map).equals(o);
++ }
++ }
++ }
++
++ public int hashCode() {
++ if (fast) {
++ return get(map).hashCode();
++ } else {
++ synchronized (map) {
++ return get(map).hashCode();
++ }
++ }
++ }
++
++ public boolean add(E o) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean addAll(Collection<? extends E> c) {
++ throw new UnsupportedOperationException();
++ }
++
++ public Iterator<E> iterator() {
++ return new CollectionViewIterator();
++ }
++
++ private class CollectionViewIterator implements Iterator<E> {
++
++ private Map expected;
++ private Map.Entry lastReturned = null;
++ private Iterator iterator;
++
++ public CollectionViewIterator() {
++ this.expected = map;
++ this.iterator = expected.entrySet().iterator();
++ }
++
++ public boolean hasNext() {
++ if (expected != map) {
++ throw new ConcurrentModificationException();
++ }
++ return iterator.hasNext();
++ }
++
++ public E next() {
++ if (expected != map) {
++ throw new ConcurrentModificationException();
++ }
++ lastReturned = (Map.Entry) iterator.next();
++ return iteratorNext(lastReturned);
++ }
++
++ public void remove() {
++ if (lastReturned == null) {
++ throw new IllegalStateException();
++ }
++ if (fast) {
++ synchronized (FastHashMap.this) {
++ if (expected != map) {
++ throw new ConcurrentModificationException();
++ }
++ FastHashMap.this.remove(lastReturned.getKey());
++ lastReturned = null;
++ expected = map;
++ }
++ } else {
++ iterator.remove();
++ lastReturned = null;
++ }
++ }
++ }
++ }
++
++ /**
++ * Set implementation over the keys of the FastHashMap
++ */
++ private class KeySet extends CollectionView<K> implements Set<K> {
++
++ protected Collection get(Map<K, V> map) {
++ return map.keySet();
++ }
++
++ protected K iteratorNext(Map.Entry<K, V> entry) {
++ return entry.getKey();
++ }
++
++
++ }
++
++ /**
++ * Collection implementation over the values of the FastHashMap
++ */
++ private class Values extends CollectionView<V> {
++
++ protected Collection get(Map<K, V> map) {
++ return map.values();
++ }
++
++ protected V iteratorNext(Map.Entry<K, V> entry) {
++ return entry.getValue();
++ }
++ }
++
++ /**
++ * Set implementation over the entries of the FastHashMap
++ */
++ private class EntrySet extends CollectionView<Map.Entry<K, V>> implements Set<Map.Entry<K, V>> {
++
++ protected Collection get(Map<K, V> map) {
++ return map.entrySet();
++ }
++
++ protected Map.Entry<K, V> iteratorNext(Map.Entry<K, V> entry) {
++ return entry;
++ }
++
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/FastTreeMap.java
+@@ -0,0 +1,817 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import java.util.*;
++
++/**
++ * <p>A customized implementation of <code>java.util.TreeMap</code> designed
++ * to operate in a multithreaded environment where the large majority of
++ * method calls are read-only, instead of structural changes. When operating
++ * in "fast" mode, read calls are non-synchronized and write calls perform the
++ * following steps:</p>
++ * <ul>
++ * <li>Clone the existing collection
++ * <li>Perform the modification on the clone
++ * <li>Replace the existing collection with the (modified) clone
++ * </ul>
++ * <p>When first created, objects of this class default to "slow" mode, where
++ * all accesses of any type are synchronized but no cloning takes place. This
++ * is appropriate for initially populating the collection, followed by a switch
++ * to "fast" mode (by calling <code>setFast(true)</code>) after initialization
++ * is complete.</p>
++ * <p/>
++ * <p><strong>NOTE</strong>: If you are creating and accessing a
++ * <code>TreeMap</code> only within a single thread, you should use
++ * <code>java.util.TreeMap</code> directly (with no synchronization), for
++ * maximum performance.</p>
++ * <p/>
++ * <p><strong>NOTE</strong>: <i>This class is not cross-platform.
++ * Using it may cause unexpected failures on some architectures.</i>
++ * It suffers from the same problems as the double-checked locking idiom.
++ * In particular, the instruction that clones the internal collection and the
++ * instruction that sets the internal reference to the clone can be executed
++ * or perceived out-of-order. This means that any read operation might fail
++ * unexpectedly, as it may be reading the state of the internal collection
++ * before the internal collection is fully formed.
++ * For more information on the double-checked locking idiom, see the
++ * <a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">
++ * Double-Checked Locking Idiom Is Broken Declaration</a>.</p>
++ *
++ * @author Craig R. McClanahan
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 1.0
++ */
++public class FastTreeMap <K,V> extends TreeMap<K, V> {
++
++ /**
++ * The underlying map we are managing.
++ */
++ protected TreeMap<K, V> map = null;
++
++ /**
++ * Are we operating in "fast" mode?
++ */
++ protected boolean fast = false;
++
++
++ // Constructors
++ // ----------------------------------------------------------------------
++
++ /**
++ * Construct a an empty map.
++ */
++ public FastTreeMap() {
++ super();
++ this.map = new TreeMap<K, V>();
++ }
++
++ /**
++ * Construct an empty map with the specified comparator.
++ *
++ * @param comparator the comparator to use for ordering tree elements
++ */
++ public FastTreeMap(Comparator<K> comparator) {
++ super();
++ this.map = new TreeMap<K, V>(comparator);
++ }
++
++ /**
++ * Construct a new map with the same mappings as the specified map,
++ * sorted according to the keys's natural order
++ *
++ * @param map the map whose mappings are to be copied
++ */
++ public FastTreeMap(Map<K, V> map) {
++ super();
++ this.map = new TreeMap<K, V>(map);
++ }
++
++ /**
++ * Construct a new map with the same mappings as the specified map,
++ * sorted according to the same ordering
++ *
++ * @param map the map whose mappings are to be copied
++ */
++ public FastTreeMap(SortedMap<K, V> map) {
++ super();
++ this.map = new TreeMap<K, V>(map);
++ }
++
++
++ // Property access
++ // ----------------------------------------------------------------------
++
++ /**
++ * Returns true if this map is operating in fast mode.
++ *
++ * @return true if this map is operating in fast mode
++ */
++ public boolean getFast() {
++ return (this.fast);
++ }
++
++ /**
++ * Sets whether this map is operating in fast mode.
++ *
++ * @param fast true if this map should operate in fast mode
++ */
++ public void setFast(boolean fast) {
++ this.fast = fast;
++ }
++
++
++ // Map access
++ // ----------------------------------------------------------------------
++ // These methods can forward straight to the wrapped Map in 'fast' mode.
++ // (because they are query methods)
++
++ /**
++ * Return the value to which this map maps the specified key. Returns
++ * <code>null</code> if the map contains no mapping for this key, or if
++ * there is a mapping with a value of <code>null</code>. Use the
++ * <code>containsKey()</code> method to disambiguate these cases.
++ *
++ * @param key the key whose value is to be returned
++ * @return the value mapped to that key, or null
++ */
++ public V get(Object key) {
++ if (fast) {
++ return (map.get(key));
++ } else {
++ synchronized (map) {
++ return (map.get(key));
++ }
++ }
++ }
++
++ /**
++ * Return the number of key-value mappings in this map.
++ *
++ * @return the current size of the map
++ */
++ public int size() {
++ if (fast) {
++ return (map.size());
++ } else {
++ synchronized (map) {
++ return (map.size());
++ }
++ }
++ }
++
++ /**
++ * Return <code>true</code> if this map contains no mappings.
++ *
++ * @return is the map currently empty
++ */
++ public boolean isEmpty() {
++ if (fast) {
++ return (map.isEmpty());
++ } else {
++ synchronized (map) {
++ return (map.isEmpty());
++ }
++ }
++ }
++
++ /**
++ * Return <code>true</code> if this map contains a mapping for the
++ * specified key.
++ *
++ * @param key the key to be searched for
++ * @return true if the map contains the key
++ */
++ public boolean containsKey(Object key) {
++ if (fast) {
++ return (map.containsKey(key));
++ } else {
++ synchronized (map) {
++ return (map.containsKey(key));
++ }
++ }
++ }
++
++ /**
++ * Return <code>true</code> if this map contains one or more keys mapping
++ * to the specified value.
++ *
++ * @param value the value to be searched for
++ * @return true if the map contains the value
++ */
++ public boolean containsValue(Object value) {
++ if (fast) {
++ return (map.containsValue(value));
++ } else {
++ synchronized (map) {
++ return (map.containsValue(value));
++ }
++ }
++ }
++
++ /**
++ * Return the comparator used to order this map, or <code>null</code>
++ * if this map uses its keys' natural order.
++ *
++ * @return the comparator used to order the map, or null if natural order
++ */
++ public Comparator<? super K> comparator() {
++ if (fast) {
++ return (map.comparator());
++ } else {
++ synchronized (map) {
++ return (map.comparator());
++ }
++ }
++ }
++
++ /**
++ * Return the first (lowest) key currently in this sorted map.
++ *
++ * @return the first key in the map
++ */
++ public K firstKey() {
++ if (fast) {
++ return (map.firstKey());
++ } else {
++ synchronized (map) {
++ return (map.firstKey());
++ }
++ }
++ }
++
++ /**
++ * Return the last (highest) key currently in this sorted map.
++ *
++ * @return the last key in the map
++ */
++ public K lastKey() {
++ if (fast) {
++ return (map.lastKey());
++ } else {
++ synchronized (map) {
++ return (map.lastKey());
++ }
++ }
++ }
++
++
++ // Map modification
++ // ----------------------------------------------------------------------
++ // These methods perform special behaviour in 'fast' mode.
++ // The map is cloned, updated and then assigned back.
++ // See the comments at the top as to why this won't always work.
++
++ /**
++ * Associate the specified value with the specified key in this map.
++ * If the map previously contained a mapping for this key, the old
++ * value is replaced and returned.
++ *
++ * @param key the key with which the value is to be associated
++ * @param value the value to be associated with this key
++ * @return the value previously mapped to the key, or null
++ */
++ public V put(K key, V value) {
++ if (fast) {
++ synchronized (this) {
++ TreeMap<K, V> temp = (TreeMap<K, V>) map.clone();
++ V result = temp.put(key, value);
++ map = temp;
++ return (result);
++ }
++ } else {
++ synchronized (map) {
++ return (map.put(key, value));
++ }
++ }
++ }
++
++ /**
++ * Copy all of the mappings from the specified map to this one, replacing
++ * any mappings with the same keys.
++ *
++ * @param in the map whose mappings are to be copied
++ */
++ public void putAll(Map<? extends K, ? extends V> in) {
++ if (fast) {
++ synchronized (this) {
++ TreeMap<K, V> temp = (TreeMap<K, V>) map.clone();
++ temp.putAll(in);
++ map = temp;
++ }
++ } else {
++ synchronized (map) {
++ map.putAll(in);
++ }
++ }
++ }
++
++ /**
++ * Remove any mapping for this key, and return any previously
++ * mapped value.
++ *
++ * @param key the key whose mapping is to be removed
++ * @return the value removed, or null
++ */
++ public V remove(Object key) {
++ if (fast) {
++ synchronized (this) {
++ TreeMap<K, V> temp = (TreeMap<K, V>) map.clone();
++ V result = temp.remove(key);
++ map = temp;
++ return (result);
++ }
++ } else {
++ synchronized (map) {
++ return (map.remove(key));
++ }
++ }
++ }
++
++ /**
++ * Remove all mappings from this map.
++ */
++ public void clear() {
++ if (fast) {
++ synchronized (this) {
++ map = new TreeMap<K, V>();
++ }
++ } else {
++ synchronized (map) {
++ map.clear();
++ }
++ }
++ }
++
++
++ // Basic object methods
++ // ----------------------------------------------------------------------
++
++ /**
++ * Compare the specified object with this list for equality. This
++ * implementation uses exactly the code that is used to define the
++ * list equals function in the documentation for the
++ * <code>Map.equals</code> method.
++ *
++ * @param o the object to be compared to this list
++ * @return true if the two maps are equal
++ */
++ public boolean equals(Object o) {
++ // Simple tests that require no synchronization
++ if (o == this) {
++ return (true);
++ } else if (!(o instanceof Map)) {
++ return (false);
++ }
++ Map mo = (Map) o;
++
++ // Compare the two maps for equality
++ if (fast) {
++ if (mo.size() != map.size()) {
++ return (false);
++ }
++ Iterator i = map.entrySet().iterator();
++ while (i.hasNext()) {
++ Map.Entry e = (Map.Entry) i.next();
++ Object key = e.getKey();
++ Object value = e.getValue();
++ if (value == null) {
++ if (!(mo.get(key) == null && mo.containsKey(key))) {
++ return (false);
++ }
++ } else {
++ if (!value.equals(mo.get(key))) {
++ return (false);
++ }
++ }
++ }
++ return (true);
++ } else {
++ synchronized (map) {
++ if (mo.size() != map.size()) {
++ return (false);
++ }
++ Iterator i = map.entrySet().iterator();
++ while (i.hasNext()) {
++ Map.Entry e = (Map.Entry) i.next();
++ Object key = e.getKey();
++ Object value = e.getValue();
++ if (value == null) {
++ if (!(mo.get(key) == null && mo.containsKey(key))) {
++ return (false);
++ }
++ } else {
++ if (!value.equals(mo.get(key))) {
++ return (false);
++ }
++ }
++ }
++ return (true);
++ }
++ }
++ }
++
++ /**
++ * Return the hash code value for this map. This implementation uses
++ * exactly the code that is used to define the list hash function in the
++ * documentation for the <code>Map.hashCode</code> method.
++ *
++ * @return a suitable integer hash code
++ */
++ public int hashCode() {
++ if (fast) {
++ int h = 0;
++ Iterator i = map.entrySet().iterator();
++ while (i.hasNext()) {
++ h += i.next().hashCode();
++ }
++ return (h);
++ } else {
++ synchronized (map) {
++ int h = 0;
++ Iterator i = map.entrySet().iterator();
++ while (i.hasNext()) {
++ h += i.next().hashCode();
++ }
++ return (h);
++ }
++ }
++ }
++
++ /**
++ * Return a shallow copy of this <code>FastTreeMap</code> instance.
++ * The keys and values themselves are not copied.
++ *
++ * @return a clone of this map
++ */
++ public FastTreeMap<K, V> clone() {
++ FastTreeMap results = null;
++ if (fast) {
++ results = new FastTreeMap(map);
++ } else {
++ synchronized (map) {
++ results = new FastTreeMap(map);
++ }
++ }
++ results.setFast(getFast());
++ return (results);
++ }
++
++
++ // Sub map views
++ // ----------------------------------------------------------------------
++
++ /**
++ * Return a view of the portion of this map whose keys are strictly
++ * less than the specified key.
++ *
++ * @param key Key higher than any in the returned map
++ * @return a head map
++ */
++ public SortedMap<K, V> headMap(K key) {
++ if (fast) {
++ return (map.headMap(key));
++ } else {
++ synchronized (map) {
++ return (map.headMap(key));
++ }
++ }
++ }
++
++ /**
++ * Return a view of the portion of this map whose keys are in the
++ * range fromKey (inclusive) to toKey (exclusive).
++ *
++ * @param fromKey Lower limit of keys for the returned map
++ * @param toKey Upper limit of keys for the returned map
++ * @return a sub map
++ */
++ public SortedMap<K, V> subMap(K fromKey, K toKey) {
++ if (fast) {
++ return (map.subMap(fromKey, toKey));
++ } else {
++ synchronized (map) {
++ return (map.subMap(fromKey, toKey));
++ }
++ }
++ }
++
++ /**
++ * Return a view of the portion of this map whose keys are greater than
++ * or equal to the specified key.
++ *
++ * @param key Key less than or equal to any in the returned map
++ * @return a tail map
++ */
++ public SortedMap<K, V> tailMap(K key) {
++ if (fast) {
++ return (map.tailMap(key));
++ } else {
++ synchronized (map) {
++ return (map.tailMap(key));
++ }
++ }
++ }
++
++
++ // Map views
++ // ----------------------------------------------------------------------
++
++ /**
++ * Return a collection view of the mappings contained in this map. Each
++ * element in the returned collection is a <code>Map.Entry</code>.
++ */
++ public Set<Map.Entry<K, V>> entrySet() {
++ return new EntrySet();
++ }
++
++ /**
++ * Return a set view of the keys contained in this map.
++ */
++ public Set<K> keySet() {
++ return new KeySet();
++ }
++
++ /**
++ * Return a collection view of the values contained in this map.
++ */
++ public Collection<V> values() {
++ return new Values();
++ }
++
++ // Map view inner classes
++ // ----------------------------------------------------------------------
++
++ /**
++ * Abstract collection implementation shared by keySet(), values() and entrySet().
++ */
++ private abstract class CollectionView <E> implements Collection<E> {
++
++ public CollectionView() {
++ }
++
++ protected abstract Collection<E> get(Map<K, V> map);
++
++ protected abstract E iteratorNext(Map.Entry<K, V> entry);
++
++
++ public void clear() {
++ if (fast) {
++ synchronized (FastTreeMap.this) {
++ map = new TreeMap<K, V>();
++ }
++ } else {
++ synchronized (map) {
++ get(map).clear();
++ }
++ }
++ }
++
++ public boolean remove(Object o) {
++ if (fast) {
++ synchronized (FastTreeMap.this) {
++ TreeMap<K, V> temp = (TreeMap<K, V>) map.clone();
++ boolean r = get(temp).remove(o);
++ map = temp;
++ return r;
++ }
++ } else {
++ synchronized (map) {
++ return get(map).remove(o);
++ }
++ }
++ }
++
++ public boolean removeAll(Collection<?> o) {
++ if (fast) {
++ synchronized (FastTreeMap.this) {
++ TreeMap temp = (TreeMap) map.clone();
++ boolean r = get(temp).removeAll(o);
++ map = temp;
++ return r;
++ }
++ } else {
++ synchronized (map) {
++ return get(map).removeAll(o);
++ }
++ }
++ }
++
++ public boolean retainAll(Collection<?> o) {
++ if (fast) {
++ synchronized (FastTreeMap.this) {
++ TreeMap temp = (TreeMap) map.clone();
++ boolean r = get(temp).retainAll(o);
++ map = temp;
++ return r;
++ }
++ } else {
++ synchronized (map) {
++ return get(map).retainAll(o);
++ }
++ }
++ }
++
++ public int size() {
++ if (fast) {
++ return get(map).size();
++ } else {
++ synchronized (map) {
++ return get(map).size();
++ }
++ }
++ }
++
++
++ public boolean isEmpty() {
++ if (fast) {
++ return get(map).isEmpty();
++ } else {
++ synchronized (map) {
++ return get(map).isEmpty();
++ }
++ }
++ }
++
++ public boolean contains(Object o) {
++ if (fast) {
++ return get(map).contains(o);
++ } else {
++ synchronized (map) {
++ return get(map).contains(o);
++ }
++ }
++ }
++
++ public boolean containsAll(Collection<?> o) {
++ if (fast) {
++ return get(map).containsAll(o);
++ } else {
++ synchronized (map) {
++ return get(map).containsAll(o);
++ }
++ }
++ }
++
++ public <T> T[] toArray(T[] o) {
++ if (fast) {
++ return get(map).toArray(o);
++ } else {
++ synchronized (map) {
++ return get(map).toArray(o);
++ }
++ }
++ }
++
++ public Object[] toArray() {
++ if (fast) {
++ return get(map).toArray();
++ } else {
++ synchronized (map) {
++ return get(map).toArray();
++ }
++ }
++ }
++
++
++ public boolean equals(Object o) {
++ if (o == this) return true;
++ if (fast) {
++ return get(map).equals(o);
++ } else {
++ synchronized (map) {
++ return get(map).equals(o);
++ }
++ }
++ }
++
++ public int hashCode() {
++ if (fast) {
++ return get(map).hashCode();
++ } else {
++ synchronized (map) {
++ return get(map).hashCode();
++ }
++ }
++ }
++
++ public boolean add(E o) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean addAll(Collection<? extends E> c) {
++ throw new UnsupportedOperationException();
++ }
++
++ public Iterator<E> iterator() {
++ return new CollectionViewIterator();
++ }
++
++ private class CollectionViewIterator implements Iterator<E> {
++
++ private Map<K, V> expected;
++ private Map.Entry<K, V> lastReturned = null;
++ private Iterator<Map.Entry<K, V>> iterator;
++
++ public CollectionViewIterator() {
++ this.expected = map;
++ this.iterator = expected.entrySet().iterator();
++ }
++
++ public boolean hasNext() {
++ if (expected != map) {
++ throw new ConcurrentModificationException();
++ }
++ return iterator.hasNext();
++ }
++
++ public E next() {
++ if (expected != map) {
++ throw new ConcurrentModificationException();
++ }
++ lastReturned = (Map.Entry<K, V>) iterator.next();
++ return iteratorNext(lastReturned);
++ }
++
++ public void remove() {
++ if (lastReturned == null) {
++ throw new IllegalStateException();
++ }
++ if (fast) {
++ synchronized (FastTreeMap.this) {
++ if (expected != map) {
++ throw new ConcurrentModificationException();
++ }
++ FastTreeMap.this.remove(lastReturned.getKey());
++ lastReturned = null;
++ expected = map;
++ }
++ } else {
++ iterator.remove();
++ lastReturned = null;
++ }
++ }
++ }
++ }
++
++ /**
++ * Set implementation over the keys of the FastTreeMap
++ */
++ private class KeySet extends CollectionView<K> implements Set<K> {
++
++ protected Collection<K> get(Map<K, V> map) {
++ return map.keySet();
++ }
++
++ protected K iteratorNext(Map.Entry<K, V> entry) {
++ return entry.getKey();
++ }
++
++ }
++
++ /**
++ * Collection implementation over the values of the FastTreeMap
++ */
++ private class Values extends CollectionView<V> {
++
++ protected Collection<V> get(Map<K, V> map) {
++ return map.values();
++ }
++
++ protected V iteratorNext(Map.Entry<K, V> entry) {
++ return entry.getValue();
++ }
++ }
++
++ /**
++ * Set implementation over the entries of the FastTreeMap
++ */
++ private class EntrySet extends CollectionView<Map.Entry<K, V>> implements Set<Map.Entry<K, V>> {
++
++ protected Collection<Map.Entry<K, V>> get(Map<K, V> map) {
++ return map.entrySet();
++ }
++
++
++ protected Map.Entry<K, V> iteratorNext(Map.Entry<K, V> entry) {
++ return entry;
++ }
++
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/FixedSizeMap.java
+@@ -0,0 +1,155 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.BoundedMap;
++import org.apache.commons.collections15.collection.UnmodifiableCollection;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * Decorates another <code>Map</code> to fix the size, preventing add/remove.
++ * <p/>
++ * Any action that would change the size of the map is disallowed.
++ * The put method is allowed to change the value associated with an existing
++ * key however.
++ * <p/>
++ * If trying to remove or clear the map, an UnsupportedOperationException is
++ * thrown. If trying to put a new mapping into the map, an
++ * IllegalArgumentException is thrown. This is because the put method can
++ * succeed if the mapping's key already exists in the map, so the put method
++ * is not always unsupported.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class FixedSizeMap <K,V> extends AbstractMapDecorator<K, V> implements Map<K, V>, BoundedMap<K, V>, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 7450927208116179316L;
++
++ /**
++ * Factory method to create a fixed size map.
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ public static <K,V> Map<K, V> decorate(Map<K, V> map) {
++ return new FixedSizeMap<K, V>(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ protected FixedSizeMap(Map<K, V> map) {
++ super(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ * @since Commons Collections 3.1
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(map);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ * @since Commons Collections 3.1
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ map = (Map<K, V>) in.readObject();
++ }
++
++ //-----------------------------------------------------------------------
++ public V put(K key, V value) {
++ if (map.containsKey(key) == false) {
++ throw new IllegalArgumentException("Cannot put new key/value pair - Map is fixed size");
++ }
++ return map.put(key, value);
++ }
++
++ public void putAll(Map<? extends K, ? extends V> mapToCopy) {
++ for (Iterator it = mapToCopy.keySet().iterator(); it.hasNext();) {
++ if (mapToCopy.containsKey(it.next()) == false) {
++ throw new IllegalArgumentException("Cannot put new key/value pair - Map is fixed size");
++ }
++ }
++ map.putAll(mapToCopy);
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException("Map is fixed size");
++ }
++
++ public V remove(Object key) {
++ throw new UnsupportedOperationException("Map is fixed size");
++ }
++
++ public Set<Map.Entry<K, V>> entrySet() {
++ Set<Map.Entry<K, V>> set = map.entrySet();
++ // unmodifiable set will still allow modification via Map.Entry objects
++ return UnmodifiableSet.decorate(set);
++ }
++
++ public Set<K> keySet() {
++ Set<K> set = map.keySet();
++ return UnmodifiableSet.decorate(set);
++ }
++
++ public Collection<V> values() {
++ Collection<V> coll = map.values();
++ return UnmodifiableCollection.decorate(coll);
++ }
++
++ public boolean isFull() {
++ return true;
++ }
++
++ public int maxSize() {
++ return size();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/FixedSizeSortedMap.java
+@@ -0,0 +1,167 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.BoundedMap;
++import org.apache.commons.collections15.collection.UnmodifiableCollection;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.*;
++
++/**
++ * Decorates another <code>SortedMap</code> to fix the size blocking add/remove.
++ * <p/>
++ * Any action that would change the size of the map is disallowed.
++ * The put method is allowed to change the value associated with an existing
++ * key however.
++ * <p/>
++ * If trying to remove or clear the map, an UnsupportedOperationException is
++ * thrown. If trying to put a new mapping into the map, an
++ * IllegalArgumentException is thrown. This is because the put method can
++ * succeed if the mapping's key already exists in the map, so the put method
++ * is not always unsupported.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class FixedSizeSortedMap <K,V> extends AbstractSortedMapDecorator<K, V> implements SortedMap<K, V>, BoundedMap<K, V>, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 3126019624511683653L;
++
++ /**
++ * Factory method to create a fixed size sorted map.
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ public static <K,V> SortedMap<K, V> decorate(SortedMap<K, V> map) {
++ return new FixedSizeSortedMap<K, V>(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ protected FixedSizeSortedMap(SortedMap<K, V> map) {
++ super(map);
++ }
++
++ /**
++ * Gets the map being decorated.
++ *
++ * @return the decorated map
++ */
++ protected SortedMap<K, V> getSortedMap() {
++ return (SortedMap<K, V>) map;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(map);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ map = (Map<K, V>) in.readObject();
++ }
++
++ //-----------------------------------------------------------------------
++ public V put(K key, V value) {
++ if (map.containsKey(key) == false) {
++ throw new IllegalArgumentException("Cannot put new key/value pair - Map is fixed size");
++ }
++ return map.put(key, value);
++ }
++
++ public void putAll(Map<? extends K, ? extends V> mapToCopy) {
++ for (Iterator it = mapToCopy.keySet().iterator(); it.hasNext();) {
++ if (mapToCopy.containsKey(it.next()) == false) {
++ throw new IllegalArgumentException("Cannot put new key/value pair - Map is fixed size");
++ }
++ }
++ map.putAll(mapToCopy);
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException("Map is fixed size");
++ }
++
++ public V remove(Object key) {
++ throw new UnsupportedOperationException("Map is fixed size");
++ }
++
++ public Set<Map.Entry<K, V>> entrySet() {
++ Set<Map.Entry<K, V>> set = map.entrySet();
++ return UnmodifiableSet.decorate(set);
++ }
++
++ public Set<K> keySet() {
++ Set<K> set = map.keySet();
++ return UnmodifiableSet.decorate(set);
++ }
++
++ public Collection<V> values() {
++ Collection<V> coll = map.values();
++ return UnmodifiableCollection.decorate(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ public SortedMap<K, V> subMap(K fromKey, K toKey) {
++ SortedMap<K, V> map = getSortedMap().subMap(fromKey, toKey);
++ return new FixedSizeSortedMap<K, V>(map);
++ }
++
++ public SortedMap<K, V> headMap(K toKey) {
++ SortedMap<K, V> map = getSortedMap().headMap(toKey);
++ return new FixedSizeSortedMap<K, V>(map);
++ }
++
++ public SortedMap<K, V> tailMap(K fromKey) {
++ SortedMap<K, V> map = getSortedMap().tailMap(fromKey);
++ return new FixedSizeSortedMap<K, V>(map);
++ }
++
++ public boolean isFull() {
++ return true;
++ }
++
++ public int maxSize() {
++ return size();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/Flat3Map.java
+@@ -0,0 +1,1151 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.IterableMap;
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.ResettableIterator;
++import org.apache.commons.collections15.iterators.EmptyIterator;
++import org.apache.commons.collections15.iterators.EmptyMapIterator;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.*;
++
++/**
++ * A <code>Map</code> implementation that stores data in simple fields until
++ * the size is greater than 3.
++ * <p/>
++ * This map is designed for performance and can outstrip HashMap.
++ * It also has good garbage collection characteristics.
++ * <ul>
++ * <li>Optimised for operation at size 3 or less.
++ * <li>Still works well once size 3 exceeded.
++ * <li>Gets at size 3 or less are about 0-10% faster than HashMap,
++ * <li>Puts at size 3 or less are over 4 times faster than HashMap.
++ * <li>Performance 5% slower than HashMap once size 3 exceeded once.
++ * </ul>
++ * The design uses two distinct modes of operation - flat and delegate.
++ * While the map is size 3 or less, operations map straight onto fields using
++ * switch statements. Once size 4 is reached, the map switches to delegate mode
++ * and only switches back when cleared. In delegate mode, all operations are
++ * forwarded straight to a HashMap resulting in the 5% performance loss.
++ * <p/>
++ * The performance gains on puts are due to not needing to create a Map Entry
++ * object. This is a large saving not only in performance but in garbage collection.
++ * <p/>
++ * Whilst in flat mode this map is also easy for the garbage collector to dispatch.
++ * This is because it contains no complex objects or arrays which slow the progress.
++ * <p/>
++ * Do not use <code>Flat3Map</code> if the size is likely to grow beyond 3.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class Flat3Map <K,V> implements IterableMap<K, V>, Serializable, Cloneable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -6701087419741928296L;
++
++ /**
++ * The size of the map, used while in flat mode
++ */
++ private transient int size;
++ /**
++ * Hash, used while in flat mode
++ */
++ private transient int hash1;
++ /**
++ * Hash, used while in flat mode
++ */
++ private transient int hash2;
++ /**
++ * Hash, used while in flat mode
++ */
++ private transient int hash3;
++ /**
++ * Key, used while in flat mode
++ */
++ private transient K key1;
++ /**
++ * Key, used while in flat mode
++ */
++ private transient K key2;
++ /**
++ * Key, used while in flat mode
++ */
++ private transient K key3;
++ /**
++ * Value, used while in flat mode
++ */
++ private transient V value1;
++ /**
++ * Value, used while in flat mode
++ */
++ private transient V value2;
++ /**
++ * Value, used while in flat mode
++ */
++ private transient V value3;
++ /**
++ * Map, used while in delegate mode
++ */
++ private transient AbstractHashedMap<K, V> delegateMap;
++
++ /**
++ * Constructor.
++ */
++ public Flat3Map() {
++ super();
++ }
++
++ /**
++ * Constructor copying elements from another map.
++ *
++ * @param map the map to copy
++ * @throws NullPointerException if the map is null
++ */
++ public Flat3Map(Map<K, V> map) {
++ super();
++ putAll(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the value mapped to the key specified.
++ *
++ * @param key the key
++ * @return the mapped value, null if no match
++ */
++ public V get(Object key) {
++ if (delegateMap != null) {
++ return delegateMap.get(key);
++ }
++ if (key == null) {
++ switch (size) {
++ // drop through
++ case 3:
++ if (key3 == null) return value3;
++ case 2:
++ if (key2 == null) return value2;
++ case 1:
++ if (key1 == null) return value1;
++ }
++ } else {
++ if (size > 0) {
++ int hashCode = key.hashCode();
++ switch (size) {
++ // drop through
++ case 3:
++ if (hash3 == hashCode && key.equals(key3)) return value3;
++ case 2:
++ if (hash2 == hashCode && key.equals(key2)) return value2;
++ case 1:
++ if (hash1 == hashCode && key.equals(key1)) return value1;
++ }
++ }
++ }
++ return null;
++ }
++
++ /**
++ * Gets the size of the map.
++ *
++ * @return the size
++ */
++ public int size() {
++ if (delegateMap != null) {
++ return delegateMap.size();
++ }
++ return size;
++ }
++
++ /**
++ * Checks whether the map is currently empty.
++ *
++ * @return true if the map is currently size zero
++ */
++ public boolean isEmpty() {
++ return (size() == 0);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Checks whether the map contains the specified key.
++ *
++ * @param key the key to search for
++ * @return true if the map contains the key
++ */
++ public boolean containsKey(Object key) {
++ if (delegateMap != null) {
++ return delegateMap.containsKey(key);
++ }
++ if (key == null) {
++ switch (size) { // drop through
++ case 3:
++ if (key3 == null) return true;
++ case 2:
++ if (key2 == null) return true;
++ case 1:
++ if (key1 == null) return true;
++ }
++ } else {
++ if (size > 0) {
++ int hashCode = key.hashCode();
++ switch (size) { // drop through
++ case 3:
++ if (hash3 == hashCode && key.equals(key3)) return true;
++ case 2:
++ if (hash2 == hashCode && key.equals(key2)) return true;
++ case 1:
++ if (hash1 == hashCode && key.equals(key1)) return true;
++ }
++ }
++ }
++ return false;
++ }
++
++ /**
++ * Checks whether the map contains the specified value.
++ *
++ * @param value the value to search for
++ * @return true if the map contains the key
++ */
++ public boolean containsValue(Object value) {
++ if (delegateMap != null) {
++ return delegateMap.containsValue(value);
++ }
++ if (value == null) { // drop through
++ switch (size) {
++ case 3:
++ if (value3 == null) return true;
++ case 2:
++ if (value2 == null) return true;
++ case 1:
++ if (value1 == null) return true;
++ }
++ } else {
++ switch (size) { // drop through
++ case 3:
++ if (value.equals(value3)) return true;
++ case 2:
++ if (value.equals(value2)) return true;
++ case 1:
++ if (value.equals(value1)) return true;
++ }
++ }
++ return false;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Puts a key-value mapping into this map.
++ *
++ * @param key the key to add
++ * @param value the value to add
++ * @return the value previously mapped to this key, null if none
++ */
++ public V put(K key, V value) {
++ if (delegateMap != null) {
++ return delegateMap.put(key, value);
++ }
++ // change existing mapping
++ if (key == null) {
++ switch (size) { // drop through
++ case 3:
++ if (key3 == null) {
++ V old = value3;
++ value3 = value;
++ return old;
++ }
++ case 2:
++ if (key2 == null) {
++ V old = value2;
++ value2 = value;
++ return old;
++ }
++ case 1:
++ if (key1 == null) {
++ V old = value1;
++ value1 = value;
++ return old;
++ }
++ }
++ } else {
++ if (size > 0) {
++ int hashCode = key.hashCode();
++ switch (size) { // drop through
++ case 3:
++ if (hash3 == hashCode && key.equals(key3)) {
++ V old = value3;
++ value3 = value;
++ return old;
++ }
++ case 2:
++ if (hash2 == hashCode && key.equals(key2)) {
++ V old = value2;
++ value2 = value;
++ return old;
++ }
++ case 1:
++ if (hash1 == hashCode && key.equals(key1)) {
++ V old = value1;
++ value1 = value;
++ return old;
++ }
++ }
++ }
++ }
++
++ // add new mapping
++ switch (size) {
++ default:
++ convertToMap();
++ delegateMap.put(key, value);
++ return null;
++ case 2:
++ hash3 = (key == null ? 0 : key.hashCode());
++ key3 = key;
++ value3 = value;
++ break;
++ case 1:
++ hash2 = (key == null ? 0 : key.hashCode());
++ key2 = key;
++ value2 = value;
++ break;
++ case 0:
++ hash1 = (key == null ? 0 : key.hashCode());
++ key1 = key;
++ value1 = value;
++ break;
++ }
++ size++;
++ return null;
++ }
++
++ /**
++ * Puts all the values from the specified map into this map.
++ *
++ * @param map the map to add
++ * @throws NullPointerException if the map is null
++ */
++ public void putAll(Map<? extends K, ? extends V> map) {
++ int size = map.size();
++ if (size == 0) {
++ return;
++ }
++ if (delegateMap != null) {
++ delegateMap.putAll(map);
++ return;
++ }
++ if (size < 4) {
++ for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
++ Map.Entry<? extends K, ? extends V> entry = (Map.Entry<? extends K, ? extends V>) it.next();
++ put(entry.getKey(), entry.getValue());
++ }
++ } else {
++ convertToMap();
++ delegateMap.putAll(map);
++ }
++ }
++
++ /**
++ * Converts the flat map data to a map.
++ */
++ private void convertToMap() {
++ delegateMap = createDelegateMap();
++ switch (size) { // drop through
++ case 3:
++ delegateMap.put(key3, value3);
++ case 2:
++ delegateMap.put(key2, value2);
++ case 1:
++ delegateMap.put(key1, value1);
++ }
++
++ size = 0;
++ hash1 = hash2 = hash3 = 0;
++ key1 = key2 = key3 = null;
++ value1 = value2 = value3 = null;
++ }
++
++ /**
++ * Create an instance of the map used for storage when in delegation mode.
++ * <p/>
++ * This can be overridden by subclasses to provide a different map implementation.
++ * Not every AbstractHashedMap is suitable, identity and reference based maps
++ * would be poor choices.
++ *
++ * @return a new AbstractHashedMap or subclass
++ * @since Commons Collections 3.1
++ */
++ protected AbstractHashedMap<K, V> createDelegateMap() {
++ return new HashedMap<K, V>();
++ }
++
++ /**
++ * Removes the specified mapping from this map.
++ *
++ * @param key the mapping to remove
++ * @return the value mapped to the removed key, null if key not in map
++ */
++ public V remove(Object key) {
++ if (delegateMap != null) {
++ return delegateMap.remove(key);
++ }
++ if (size == 0) {
++ return null;
++ }
++ if (key == null) {
++ switch (size) { // drop through
++ case 3:
++ if (key3 == null) {
++ V old = value3;
++ hash3 = 0;
++ key3 = null;
++ value3 = null;
++ size = 2;
++ return old;
++ }
++ if (key2 == null) {
++ V old = value3;
++ hash2 = hash3;
++ key2 = key3;
++ value2 = value3;
++ hash3 = 0;
++ key3 = null;
++ value3 = null;
++ size = 2;
++ return old;
++ }
++ if (key1 == null) {
++ V old = value3;
++ hash1 = hash3;
++ key1 = key3;
++ value1 = value3;
++ hash3 = 0;
++ key3 = null;
++ value3 = null;
++ size = 2;
++ return old;
++ }
++ return null;
++ case 2:
++ if (key2 == null) {
++ V old = value2;
++ hash2 = 0;
++ key2 = null;
++ value2 = null;
++ size = 1;
++ return old;
++ }
++ if (key1 == null) {
++ V old = value2;
++ hash1 = hash2;
++ key1 = key2;
++ value1 = value2;
++ hash2 = 0;
++ key2 = null;
++ value2 = null;
++ size = 1;
++ return old;
++ }
++ return null;
++ case 1:
++ if (key1 == null) {
++ V old = value1;
++ hash1 = 0;
++ key1 = null;
++ value1 = null;
++ size = 0;
++ return old;
++ }
++ }
++ } else {
++ if (size > 0) {
++ int hashCode = key.hashCode();
++ switch (size) { // drop through
++ case 3:
++ if (hash3 == hashCode && key.equals(key3)) {
++ V old = value3;
++ hash3 = 0;
++ key3 = null;
++ value3 = null;
++ size = 2;
++ return old;
++ }
++ if (hash2 == hashCode && key.equals(key2)) {
++ V old = value3;
++ hash2 = hash3;
++ key2 = key3;
++ value2 = value3;
++ hash3 = 0;
++ key3 = null;
++ value3 = null;
++ size = 2;
++ return old;
++ }
++ if (hash1 == hashCode && key.equals(key1)) {
++ V old = value3;
++ hash1 = hash3;
++ key1 = key3;
++ value1 = value3;
++ hash3 = 0;
++ key3 = null;
++ value3 = null;
++ size = 2;
++ return old;
++ }
++ return null;
++ case 2:
++ if (hash2 == hashCode && key.equals(key2)) {
++ V old = value2;
++ hash2 = 0;
++ key2 = null;
++ value2 = null;
++ size = 1;
++ return old;
++ }
++ if (hash1 == hashCode && key.equals(key1)) {
++ V old = value2;
++ hash1 = hash2;
++ key1 = key2;
++ value1 = value2;
++ hash2 = 0;
++ key2 = null;
++ value2 = null;
++ size = 1;
++ return old;
++ }
++ return null;
++ case 1:
++ if (hash1 == hashCode && key.equals(key1)) {
++ V old = value1;
++ hash1 = 0;
++ key1 = null;
++ value1 = null;
++ size = 0;
++ return old;
++ }
++ }
++ }
++ }
++ return null;
++ }
++
++ /**
++ * Clears the map, resetting the size to zero and nullifying references
++ * to avoid garbage collection issues.
++ */
++ public void clear() {
++ if (delegateMap != null) {
++ delegateMap.clear(); // should aid gc
++ delegateMap = null; // switch back to flat mode
++ } else {
++ size = 0;
++ hash1 = hash2 = hash3 = 0;
++ key1 = key2 = key3 = null;
++ value1 = value2 = value3 = null;
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an iterator over the map.
++ * Changes made to the iterator affect this map.
++ * <p/>
++ * A MapIterator returns the keys in the map. It also provides convenient
++ * methods to get the key and value, and set the value.
++ * It avoids the need to create an entrySet/keySet/values object.
++ * It also avoids creating the Map Entry object.
++ *
++ * @return the map iterator
++ */
++ public MapIterator<K, V> mapIterator() {
++ if (delegateMap != null) {
++ return delegateMap.mapIterator();
++ }
++ if (size == 0) {
++ return EmptyMapIterator.INSTANCE;
++ }
++ return new FlatMapIterator<K, V>(this);
++ }
++
++ /**
++ * FlatMapIterator
++ */
++ static class FlatMapIterator <K,V> implements MapIterator<K, V>, ResettableIterator<K> {
++ private final Flat3Map<K, V> parent;
++ private int nextIndex = 0;
++ private boolean canRemove = false;
++
++ FlatMapIterator(Flat3Map<K, V> parent) {
++ super();
++ this.parent = parent;
++ }
++
++ public boolean hasNext() {
++ return (nextIndex < parent.size);
++ }
++
++ public K next() {
++ if (hasNext() == false) {
++ throw new NoSuchElementException(AbstractHashedMap.NO_NEXT_ENTRY);
++ }
++ canRemove = true;
++ nextIndex++;
++ return getKey();
++ }
++
++ public void remove() {
++ if (canRemove == false) {
++ throw new IllegalStateException(AbstractHashedMap.REMOVE_INVALID);
++ }
++ parent.remove(getKey());
++ nextIndex--;
++ canRemove = false;
++ }
++
++ public K getKey() {
++ if (canRemove == false) {
++ throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
++ }
++ switch (nextIndex) {
++ case 3:
++ return parent.key3;
++ case 2:
++ return parent.key2;
++ case 1:
++ return parent.key1;
++ }
++ throw new IllegalStateException("Invalid map index");
++ }
++
++ public V getValue() {
++ if (canRemove == false) {
++ throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
++ }
++ switch (nextIndex) {
++ case 3:
++ return parent.value3;
++ case 2:
++ return parent.value2;
++ case 1:
++ return parent.value1;
++ }
++ throw new IllegalStateException("Invalid map index");
++ }
++
++ public V setValue(V value) {
++ if (canRemove == false) {
++ throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
++ }
++ V old = getValue();
++ switch (nextIndex) {
++ case 3:
++ parent.value3 = value;
++ case 2:
++ parent.value2 = value;
++ case 1:
++ parent.value1 = value;
++ }
++ return old;
++ }
++
++ public void reset() {
++ nextIndex = 0;
++ canRemove = false;
++ }
++
++ public String toString() {
++ if (canRemove) {
++ return "Iterator[" + getKey() + "=" + getValue() + "]";
++ } else {
++ return "Iterator[]";
++ }
++ }
++ }
++
++ /**
++ * Gets the entrySet view of the map.
++ * Changes made to the view affect this map.
++ * The Map Entry is not an independent object and changes as the
++ * iterator progresses.
++ * To simply iterate through the entries, use {@link #mapIterator()}.
++ *
++ * @return the entrySet view
++ */
++ public Set<Map.Entry<K, V>> entrySet() {
++ if (delegateMap != null) {
++ return delegateMap.entrySet();
++ }
++ return new EntrySet<K, V>(this);
++ }
++
++ /**
++ * EntrySet
++ */
++ static class EntrySet <K,V> extends AbstractSet<Map.Entry<K, V>> {
++ private final Flat3Map<K, V> parent;
++
++ EntrySet(Flat3Map<K, V> parent) {
++ super();
++ this.parent = parent;
++ }
++
++ public int size() {
++ return parent.size();
++ }
++
++ public void clear() {
++ parent.clear();
++ }
++
++ public boolean remove(Object obj) {
++ if (obj instanceof Map.Entry == false) {
++ return false;
++ }
++ Map.Entry entry = (Map.Entry) obj;
++ Object key = entry.getKey();
++ boolean result = parent.containsKey(key);
++ parent.remove(key);
++ return result;
++ }
++
++ public Iterator<Map.Entry<K, V>> iterator() {
++ if (parent.delegateMap != null) {
++ return parent.delegateMap.entrySet().iterator();
++ }
++ if (parent.size() == 0) {
++ return EmptyIterator.INSTANCE;
++ }
++ return new EntrySetIterator<K, V>(parent);
++ }
++ }
++
++ static class EntrySetIterator <K,V> extends IteratorBase<K, V> implements Iterator<Map.Entry<K, V>> {
++
++ public EntrySetIterator(Flat3Map<K, V> flat3Map) {
++ super(flat3Map);
++ }
++
++ public Entry<K, V> next() {
++ return superNext(); //To change body of implemented methods use File | Settings | File Templates.
++ }
++
++ }
++
++ /**
++ * EntrySetIterator and MapEntry
++ */
++ static class IteratorBase <K,V> implements Map.Entry<K, V> {
++ private final Flat3Map<K, V> parent;
++ private int nextIndex = 0;
++ private boolean canRemove = false;
++
++ IteratorBase(Flat3Map<K, V> parent) {
++ super();
++ this.parent = parent;
++ }
++
++ public boolean hasNext() {
++ return (nextIndex < parent.size);
++ }
++
++ public void remove() {
++ if (canRemove == false) {
++ throw new IllegalStateException(AbstractHashedMap.REMOVE_INVALID);
++ }
++ parent.remove(getKey());
++ nextIndex--;
++ canRemove = false;
++ }
++
++ public K getKey() {
++ if (canRemove == false) {
++ throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
++ }
++ switch (nextIndex) {
++ case 3:
++ return parent.key3;
++ case 2:
++ return parent.key2;
++ case 1:
++ return parent.key1;
++ }
++ throw new IllegalStateException("Invalid map index");
++ }
++
++ public Map.Entry<K, V> superNext() {
++ if (hasNext() == false) {
++ throw new NoSuchElementException(AbstractHashedMap.NO_NEXT_ENTRY);
++ }
++ canRemove = true;
++ nextIndex++;
++ return this;
++ }
++
++ public V getValue() {
++ if (canRemove == false) {
++ throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
++ }
++ switch (nextIndex) {
++ case 3:
++ return parent.value3;
++ case 2:
++ return parent.value2;
++ case 1:
++ return parent.value1;
++ }
++ throw new IllegalStateException("Invalid map index");
++ }
++
++ public V setValue(V value) {
++ if (canRemove == false) {
++ throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
++ }
++ V old = getValue();
++ switch (nextIndex) {
++ case 3:
++ parent.value3 = value;
++ case 2:
++ parent.value2 = value;
++ case 1:
++ parent.value1 = value;
++ }
++ return old;
++ }
++
++ public boolean equals(Object obj) {
++ if (canRemove == false) {
++ return false;
++ }
++ if (obj instanceof Map.Entry == false) {
++ return false;
++ }
++ Map.Entry other = (Map.Entry) obj;
++ Object key = getKey();
++ Object value = getValue();
++ return (key == null ? other.getKey() == null : key.equals(other.getKey())) && (value == null ? other.getValue() == null : value.equals(other.getValue()));
++ }
++
++ public int hashCode() {
++ if (canRemove == false) {
++ return 0;
++ }
++ Object key = getKey();
++ Object value = getValue();
++ return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode());
++ }
++
++ public String toString() {
++ if (canRemove) {
++ return getKey() + "=" + getValue();
++ } else {
++ return "";
++ }
++ }
++ }
++
++ /**
++ * Gets the keySet view of the map.
++ * Changes made to the view affect this map.
++ * To simply iterate through the keys, use {@link #mapIterator()}.
++ *
++ * @return the keySet view
++ */
++ public Set keySet() {
++ if (delegateMap != null) {
++ return delegateMap.keySet();
++ }
++ return new KeySet(this);
++ }
++
++ /**
++ * KeySet
++ */
++ static class KeySet <K,V> extends AbstractSet<K> {
++ private final Flat3Map<K, V> parent;
++
++ KeySet(Flat3Map<K, V> parent) {
++ super();
++ this.parent = parent;
++ }
++
++ public int size() {
++ return parent.size();
++ }
++
++ public void clear() {
++ parent.clear();
++ }
++
++ public boolean contains(Object key) {
++ return parent.containsKey(key);
++ }
++
++ public boolean remove(Object key) {
++ boolean result = parent.containsKey(key);
++ parent.remove(key);
++ return result;
++ }
++
++ public Iterator<K> iterator() {
++ if (parent.delegateMap != null) {
++ return parent.delegateMap.keySet().iterator();
++ }
++ if (parent.size() == 0) {
++ return EmptyIterator.INSTANCE;
++ }
++ return new KeySetIterator<K, V>(parent);
++ }
++ }
++
++ /**
++ * KeySetIterator
++ */
++ static class KeySetIterator <K,V> extends IteratorBase<K, V> implements Iterator<K> {
++
++ KeySetIterator(Flat3Map<K, V> parent) {
++ super(parent);
++ }
++
++ public K next() {
++ superNext();
++ return getKey();
++ }
++ }
++
++ /**
++ * Gets the values view of the map.
++ * Changes made to the view affect this map.
++ * To simply iterate through the values, use {@link #mapIterator()}.
++ *
++ * @return the values view
++ */
++ public Collection<V> values() {
++ if (delegateMap != null) {
++ return delegateMap.values();
++ }
++ return new Values<K, V>(this);
++ }
++
++ /**
++ * Values
++ */
++ static class Values <K,V> extends AbstractCollection<V> {
++ private final Flat3Map<K, V> parent;
++
++ Values(Flat3Map<K, V> parent) {
++ super();
++ this.parent = parent;
++ }
++
++ public int size() {
++ return parent.size();
++ }
++
++ public void clear() {
++ parent.clear();
++ }
++
++ public boolean contains(Object value) {
++ return parent.containsValue(value);
++ }
++
++ public Iterator<V> iterator() {
++ if (parent.delegateMap != null) {
++ return parent.delegateMap.values().iterator();
++ }
++ if (parent.size() == 0) {
++ return EmptyIterator.INSTANCE;
++ }
++ return new ValuesIterator<K, V>(parent);
++ }
++ }
++
++ /**
++ * ValuesIterator
++ */
++ static class ValuesIterator <K,V> extends IteratorBase<K, V> implements Iterator<V> {
++
++ ValuesIterator(Flat3Map<K, V> parent) {
++ super(parent);
++ }
++
++ public V next() {
++ superNext();
++ return getValue();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeInt(size());
++ for (MapIterator it = mapIterator(); it.hasNext();) {
++ out.writeObject(it.next()); // key
++ out.writeObject(it.getValue()); // value
++ }
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ int count = in.readInt();
++ if (count > 3) {
++ delegateMap = createDelegateMap();
++ }
++ for (int i = count; i > 0; i--) {
++ put((K) in.readObject(), (V) in.readObject());
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Clones the map without cloning the keys or values.
++ *
++ * @return a shallow clone
++ * @since Commons Collections 3.1
++ */
++ public Object clone() {
++ try {
++ Flat3Map cloned = (Flat3Map) super.clone();
++ if (cloned.delegateMap != null) {
++ cloned.delegateMap = (HashedMap) cloned.delegateMap.clone();
++ }
++ return cloned;
++ } catch (CloneNotSupportedException ex) {
++ throw new InternalError();
++ }
++ }
++
++ /**
++ * Compares this map with another.
++ *
++ * @param obj the object to compare to
++ * @return true if equal
++ */
++ public boolean equals(Object obj) {
++ if (obj == this) {
++ return true;
++ }
++ if (delegateMap != null) {
++ return delegateMap.equals(obj);
++ }
++ if (obj instanceof Map == false) {
++ return false;
++ }
++ Map other = (Map) obj;
++ if (size != other.size()) {
++ return false;
++ }
++ if (size > 0) {
++ Object otherValue = null;
++ switch (size) { // drop through
++ case 3:
++ if (other.containsKey(key3) == false) {
++ otherValue = other.get(key3);
++ if (value3 == null ? otherValue != null : !value3.equals(otherValue)) {
++ return false;
++ }
++ }
++ case 2:
++ if (other.containsKey(key2) == false) {
++ otherValue = other.get(key2);
++ if (value2 == null ? otherValue != null : !value2.equals(otherValue)) {
++ return false;
++ }
++ }
++ case 1:
++ if (other.containsKey(key1) == false) {
++ otherValue = other.get(key1);
++ if (value1 == null ? otherValue != null : !value1.equals(otherValue)) {
++ return false;
++ }
++ }
++ }
++ }
++ return true;
++ }
++
++ /**
++ * Gets the standard Map hashCode.
++ *
++ * @return the hash code defined in the Map interface
++ */
++ public int hashCode() {
++ if (delegateMap != null) {
++ return delegateMap.hashCode();
++ }
++ int total = 0;
++ switch (size) { // drop through
++ case 3:
++ total += (hash3 ^ (value3 == null ? 0 : value3.hashCode()));
++ case 2:
++ total += (hash2 ^ (value2 == null ? 0 : value2.hashCode()));
++ case 1:
++ total += (hash1 ^ (value1 == null ? 0 : value1.hashCode()));
++ }
++ return total;
++ }
++
++ /**
++ * Gets the map as a String.
++ *
++ * @return a string version of the map
++ */
++ public String toString() {
++ if (delegateMap != null) {
++ return delegateMap.toString();
++ }
++ if (size == 0) {
++ return "{}";
++ }
++ StringBuffer buf = new StringBuffer(128);
++ buf.append('{');
++ switch (size) { // drop through
++ case 3:
++ buf.append(key3);
++ buf.append('=');
++ buf.append(value3);
++ buf.append(',');
++ case 2:
++ buf.append(key2);
++ buf.append('=');
++ buf.append(value2);
++ buf.append(',');
++ case 1:
++ buf.append(key1);
++ buf.append('=');
++ buf.append(value1);
++ }
++ buf.append('}');
++ return buf.toString();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/HashedMap.java
+@@ -0,0 +1,111 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Map;
++
++/**
++ * A <code>Map</code> implementation that is a general purpose alternative
++ * to <code>HashMap</code>.
++ * <p/>
++ * This implementation improves on the JDK1.4 HashMap by adding the
++ * {@link org.apache.commons.collections15.MapIterator MapIterator}
++ * functionality and many methods for subclassing.
++ * <p/>
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class HashedMap <K,V> extends AbstractHashedMap<K, V> implements Serializable, Cloneable {
++
++ /**
++ * Serialisation version
++ */
++ private static final long serialVersionUID = -1788199231038721040L;
++
++ /**
++ * Constructs a new empty map with default size and load factor.
++ */
++ public HashedMap() {
++ super(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_THRESHOLD);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity.
++ *
++ * @param initialCapacity the initial capacity
++ * @throws IllegalArgumentException if the initial capacity is less than one
++ */
++ public HashedMap(int initialCapacity) {
++ super(initialCapacity);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity and
++ * load factor.
++ *
++ * @param initialCapacity the initial capacity
++ * @param loadFactor the load factor
++ * @throws IllegalArgumentException if the initial capacity is less than one
++ * @throws IllegalArgumentException if the load factor is less than zero
++ */
++ public HashedMap(int initialCapacity, float loadFactor) {
++ super(initialCapacity, loadFactor);
++ }
++
++ /**
++ * Constructor copying elements from another map.
++ *
++ * @param map the map to copy
++ * @throws NullPointerException if the map is null
++ */
++ public HashedMap(Map<? extends K, ? extends V> map) {
++ super(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Clones the map without cloning the keys or values.
++ *
++ * @return a shallow clone
++ */
++ public Object clone() {
++ return super.clone();
++ }
++
++ /**
++ * Write the map out using a custom routine.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ doWriteObject(out);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ doReadObject(in);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/IdentityMap.java
+@@ -0,0 +1,186 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Map;
++
++/**
++ * A <code>Map</code> implementation that matches keys and values based
++ * on <code>==</code> not <code>equals()</code>.
++ * <p/>
++ * This map will violate the detail of various Map and map view contracts.
++ * As a general rule, don't compare this map to other maps.
++ *
++ * @author java util HashMap
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class IdentityMap <K,V> extends AbstractHashedMap<K, V> implements Serializable, Cloneable {
++
++ /**
++ * Serialisation version
++ */
++ private static final long serialVersionUID = 2028493495224302329L;
++
++ /**
++ * Constructs a new empty map with default size and load factor.
++ */
++ public IdentityMap() {
++ super(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_THRESHOLD);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity.
++ *
++ * @param initialCapacity the initial capacity
++ * @throws IllegalArgumentException if the initial capacity is less than one
++ */
++ public IdentityMap(int initialCapacity) {
++ super(initialCapacity);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity and
++ * load factor.
++ *
++ * @param initialCapacity the initial capacity
++ * @param loadFactor the load factor
++ * @throws IllegalArgumentException if the initial capacity is less than one
++ * @throws IllegalArgumentException if the load factor is less than zero
++ */
++ public IdentityMap(int initialCapacity, float loadFactor) {
++ super(initialCapacity, loadFactor);
++ }
++
++ /**
++ * Constructor copying elements from another map.
++ *
++ * @param map the map to copy
++ * @throws NullPointerException if the map is null
++ */
++ public IdentityMap(Map<? extends K, ? extends V> map) {
++ super(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the hash code for the key specified.
++ * This implementation uses the identity hash code.
++ *
++ * @param key the key to get a hash code for
++ * @return the hash code
++ */
++ protected int hash(Object key) {
++ return System.identityHashCode(key);
++ }
++
++ /**
++ * Compares two keys for equals.
++ * This implementation uses <code>==</code>.
++ *
++ * @param key1 the first key to compare
++ * @param key2 the second key to compare
++ * @return true if equal by identity
++ */
++ protected boolean isEqualKey(Object key1, Object key2) {
++ return (key1 == key2);
++ }
++
++ /**
++ * Compares two values for equals.
++ * This implementation uses <code>==</code>.
++ *
++ * @param value1 the first value to compare
++ * @param value2 the second value to compare
++ * @return true if equal by identity
++ */
++ protected boolean isEqualValue(Object value1, Object value2) {
++ return (value1 == value2);
++ }
++
++ /**
++ * Creates an entry to store the data.
++ * This implementation creates an IdentityEntry instance.
++ *
++ * @param next the next entry in sequence
++ * @param hashCode the hash code to use
++ * @param key the key to store
++ * @param value the value to store
++ * @return the newly created entry
++ */
++ protected HashEntry<K, V> createEntry(HashEntry<K, V> next, int hashCode, K key, V value) {
++ return new IdentityEntry<K, V>(next, hashCode, key, value);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * HashEntry
++ */
++ protected static class IdentityEntry <K,V> extends HashEntry<K, V> {
++
++ protected IdentityEntry(HashEntry<K, V> next, int hashCode, K key, V value) {
++ super(next, hashCode, key, 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() == other.getKey()) && (getValue() == other.getValue());
++ }
++
++ public int hashCode() {
++ return System.identityHashCode(getKey()) ^ System.identityHashCode(getValue());
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Clones the map without cloning the keys or values.
++ *
++ * @return a shallow clone
++ */
++ public Object clone() {
++ return super.clone();
++ }
++
++ /**
++ * Write the map out using a custom routine.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ doWriteObject(out);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ doReadObject(in);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/LRUMap.java
+@@ -0,0 +1,398 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.BoundedMap;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Map;
++
++/**
++ * A <code>Map</code> implementation with a fixed maximum size which removes
++ * the least recently used entry if an entry is added when full.
++ * <p/>
++ * The least recently used algorithm works on the get and put operations only.
++ * Iteration of any kind, including setting the value by iteration, does not
++ * change the order. Queries such as containsKey and containsValue or access
++ * via views also do not change the order.
++ * <p/>
++ * The map implements <code>OrderedMap</code> and entries may be queried using
++ * the bidirectional <code>OrderedMapIterator</code>. The order returned is
++ * least recently used to most recently used. Iterators from map views can
++ * also be cast to <code>OrderedIterator</code> if required.
++ * <p/>
++ * All the available iterators can be reset back to the start by casting to
++ * <code>ResettableIterator</code> and calling <code>reset()</code>.
++ *
++ * @author James Strachan
++ * @author Morgan Delagrange
++ * @author Stephen Colebourne
++ * @author Mike Pettypiece
++ * @author Matt Hall, John Watkinson, Mario Ivankovits
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0 (previously in main package v1.0)
++ */
++public class LRUMap <K,V> extends AbstractLinkedMap<K, V> implements BoundedMap<K, V>, Serializable, Cloneable {
++
++ /**
++ * Serialisation version
++ */
++ static final long serialVersionUID = -612114643488955218L;
++ /**
++ * Default maximum size
++ */
++ protected static final int DEFAULT_MAX_SIZE = 100;
++
++ /**
++ * Maximum size
++ */
++ private transient int maxSize;
++ /**
++ * Scan behaviour
++ */
++ private boolean scanUntilRemovable;
++
++ /**
++ * Constructs a new empty map with a maximum size of 100.
++ */
++ public LRUMap() {
++ this(DEFAULT_MAX_SIZE, DEFAULT_LOAD_FACTOR, false);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified maximum size.
++ *
++ * @param maxSize the maximum size of the map
++ * @throws IllegalArgumentException if the maximum size is less than one
++ */
++ public LRUMap(int maxSize) {
++ this(maxSize, DEFAULT_LOAD_FACTOR);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified maximum size.
++ *
++ * @param maxSize the maximum size of the map
++ * @param scanUntilRemovable scan until a removeable entry is found, default false
++ * @throws IllegalArgumentException if the maximum size is less than one
++ * @since Commons Collections 3.1
++ */
++ public LRUMap(int maxSize, boolean scanUntilRemovable) {
++ this(maxSize, DEFAULT_LOAD_FACTOR, scanUntilRemovable);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity and
++ * load factor.
++ *
++ * @param maxSize the maximum size of the map, -1 for no limit,
++ * @param loadFactor the load factor
++ * @throws IllegalArgumentException if the maximum size is less than one
++ * @throws IllegalArgumentException if the load factor is less than zero
++ */
++ public LRUMap(int maxSize, float loadFactor) {
++ this(maxSize, loadFactor, false);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity and
++ * load factor.
++ *
++ * @param maxSize the maximum size of the map, -1 for no limit,
++ * @param loadFactor the load factor
++ * @param scanUntilRemovable scan until a removeable entry is found, default false
++ * @throws IllegalArgumentException if the maximum size is less than one
++ * @throws IllegalArgumentException if the load factor is less than zero
++ * @since Commons Collections 3.1
++ */
++ public LRUMap(int maxSize, float loadFactor, boolean scanUntilRemovable) {
++ super((maxSize < 1 ? DEFAULT_CAPACITY : maxSize), loadFactor);
++ if (maxSize < 1) {
++ throw new IllegalArgumentException("LRUMap max size must be greater than 0");
++ }
++ this.maxSize = maxSize;
++ this.scanUntilRemovable = scanUntilRemovable;
++ }
++
++ /**
++ * Constructor copying elements from another map.
++ * <p/>
++ * The maximum size is set from the map's size.
++ *
++ * @param map the map to copy
++ * @throws NullPointerException if the map is null
++ * @throws IllegalArgumentException if the map is empty
++ */
++ public LRUMap(Map<? extends K, ? extends V> map) {
++ this(map, false);
++ }
++
++ /**
++ * Constructor copying elements from another map.
++ * <p/>
++ * The maximum size is set from the map's size.
++ *
++ * @param map the map to copy
++ * @param scanUntilRemovable scan until a removeable entry is found, default false
++ * @throws NullPointerException if the map is null
++ * @throws IllegalArgumentException if the map is empty
++ * @since Commons Collections 3.1
++ */
++ public LRUMap(Map<? extends K, ? extends V> map, boolean scanUntilRemovable) {
++ this(map.size(), DEFAULT_LOAD_FACTOR, scanUntilRemovable);
++ putAll(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the value mapped to the key specified.
++ * <p/>
++ * This operation changes the position of the key in the map to the
++ * most recently used position (first).
++ *
++ * @param key the key
++ * @return the mapped value, null if no match
++ */
++ public V get(Object key) {
++ LinkEntry<K, V> entry = (LinkEntry<K, V>) getEntry(key);
++ if (entry == null) {
++ return null;
++ }
++ moveToMRU(entry);
++ return entry.getValue();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Moves an entry to the MRU position at the end of the list.
++ * <p/>
++ * This implementation moves the updated entry to the end of the list.
++ *
++ * @param entry the entry to update
++ */
++ protected void moveToMRU(LinkEntry<K, V> entry) {
++ if (entry.after != header) {
++ modCount++;
++ // remove
++ entry.before.after = entry.after;
++ entry.after.before = entry.before;
++ // add first
++ entry.after = header;
++ entry.before = header.before;
++ header.before.after = entry;
++ header.before = entry;
++ }
++ }
++
++ /**
++ * Updates an existing key-value mapping.
++ * <p/>
++ * This implementation moves the updated entry to the top of the list
++ * using {@link #moveToMRU(org.apache.commons.collections15.map.AbstractLinkedMap.LinkEntry)}.
++ *
++ * @param entry the entry to update
++ * @param newValue the new value to store
++ */
++ protected void updateEntry(HashEntry<K, V> entry, V newValue) {
++ moveToMRU((LinkEntry<K, V>) entry); // handles modCount
++ entry.setValue(newValue);
++ }
++
++ /**
++ * Adds a new key-value mapping into this map.
++ * <p/>
++ * This implementation checks the LRU size and determines whether to
++ * discard an entry or not using {@link #removeLRU(org.apache.commons.collections15.map.AbstractLinkedMap.LinkEntry)}.
++ * <p/>
++ * From Commons Collections 3.1 this method uses {@link #isFull()} rather
++ * than accessing <code>size</code> and <code>maxSize</code> directly.
++ * It also handles the scanUntilRemovable functionality.
++ *
++ * @param hashIndex the index into the data array to store at
++ * @param hashCode the hash code of the key to add
++ * @param key the key to add
++ * @param value the value to add
++ */
++ protected void addMapping(int hashIndex, int hashCode, K key, V value) {
++ if (isFull()) {
++ LinkEntry reuse = header.after;
++ boolean removeLRUEntry = false;
++ if (scanUntilRemovable) {
++ while (reuse != header) {
++ if (removeLRU(reuse)) {
++ removeLRUEntry = true;
++ break;
++ }
++ reuse = reuse.after;
++ }
++ } else {
++ removeLRUEntry = removeLRU(reuse);
++ }
++
++ if (removeLRUEntry) {
++ reuseMapping(reuse, hashIndex, hashCode, key, value);
++ } else {
++ super.addMapping(hashIndex, hashCode, key, value);
++ }
++ } else {
++ super.addMapping(hashIndex, hashCode, key, value);
++ }
++ }
++
++ /**
++ * Reuses an entry by removing it and moving it to a new place in the map.
++ * <p/>
++ * This method uses {@link #removeEntry}, {@link #reuseEntry} and {@link #addEntry}.
++ *
++ * @param entry the entry to reuse
++ * @param hashIndex the index into the data array to store at
++ * @param hashCode the hash code of the key to add
++ * @param key the key to add
++ * @param value the value to add
++ */
++ protected void reuseMapping(LinkEntry<K, V> entry, int hashIndex, int hashCode, K key, V value) {
++ // find the entry before the entry specified in the hash table
++ // remember that the parameters (except the first) refer to the new entry,
++ // not the old one
++ int removeIndex = hashIndex(entry.hashCode, data.length);
++ HashEntry<K, V> loop = data[removeIndex];
++ HashEntry<K, V> previous = null;
++ while (loop != entry) {
++ previous = loop;
++ loop = loop.next;
++ }
++
++ // reuse the entry
++ modCount++;
++ removeEntry(entry, removeIndex, previous);
++ reuseEntry(entry, hashIndex, hashCode, key, value);
++ addEntry(entry, hashIndex);
++ }
++
++ /**
++ * Subclass method to control removal of the least recently used entry from the map.
++ * <p/>
++ * This method exists for subclasses to override. A subclass may wish to
++ * provide cleanup of resources when an entry is removed. For example:
++ * <pre>
++ * protected boolean removeLRU(LinkEntry entry) {
++ * releaseResources(entry.getValue()); // release resources held by entry
++ * return true; // actually delete entry
++ * }
++ * </pre>
++ * <p/>
++ * Alternatively, a subclass may choose to not remove the entry or selectively
++ * keep certain LRU entries. For example:
++ * <pre>
++ * protected boolean removeLRU(LinkEntry entry) {
++ * if (entry.getKey().toString().startsWith("System.")) {
++ * return false; // entry not removed from LRUMap
++ * } else {
++ * return true; // actually delete entry
++ * }
++ * }
++ * </pre>
++ * The effect of returning false is dependent on the scanUntilRemovable flag.
++ * If the flag is true, the next LRU entry will be passed to this method and so on
++ * until one returns false and is removed, or every entry in the map has been passed.
++ * If the scanUntilRemovable flag is false, the map will exceed the maximum size.
++ * <p/>
++ * NOTE: Commons Collections 3.0 passed the wrong entry to this method.
++ * This is fixed in version 3.1 onwards.
++ *
++ * @param entry the entry to be removed
++ */
++ protected boolean removeLRU(LinkEntry<K, V> entry) {
++ return true;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns true if this map is full and no new mappings can be added.
++ *
++ * @return <code>true</code> if the map is full
++ */
++ public boolean isFull() {
++ return (size >= maxSize);
++ }
++
++ /**
++ * Gets the maximum size of the map (the bound).
++ *
++ * @return the maximum number of elements the map can hold
++ */
++ public int maxSize() {
++ return maxSize;
++ }
++
++ /**
++ * Whether this LRUMap will scan until a removable entry is found when the
++ * map is full.
++ *
++ * @return true if this map scans
++ * @since Commons Collections 3.1
++ */
++ public boolean isScanUntilRemovable() {
++ return scanUntilRemovable;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Clones the map without cloning the keys or values.
++ *
++ * @return a shallow clone
++ */
++ public Object clone() {
++ return super.clone();
++ }
++
++ /**
++ * Write the map out using a custom routine.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ doWriteObject(out);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ doReadObject(in);
++ }
++
++ /**
++ * Writes the data necessary for <code>put()</code> to work in deserialization.
++ */
++ protected void doWriteObject(ObjectOutputStream out) throws IOException {
++ out.writeInt(maxSize);
++ super.doWriteObject(out);
++ }
++
++ /**
++ * Reads the data necessary for <code>put()</code> to work in the superclass.
++ */
++ protected void doReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ maxSize = in.readInt();
++ super.doReadObject(in);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/LazyMap.java
+@@ -0,0 +1,167 @@
++// GenericsNote: Converted -- Using a Transformer instead of a Factory is no longer allowed.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Map;
++
++import org.apache.commons.collections15.Factory;
++import org.apache.commons.collections15.Transformer;
++import org.apache.commons.collections15.functors.FactoryTransformer;
++
++/**
++ * Decorates another <code>Map</code> to create objects in the map on demand.
++ * <p/>
++ * When the {@link #get(Object)} method is called with a key that does not
++ * exist in the map, the factory is used to create the object. The created
++ * object will be added to the map using the requested key.
++ * <p/>
++ * For instance:
++ * <pre>
++ * Factory factory = new Factory() {
++ * public Object create() {
++ * return new Date();
++ * }
++ * }
++ * Map lazy = Lazy.map(new HashMap(), factory);
++ * Object obj = lazy.get("NOW");
++ * </pre>
++ * <p/>
++ * After the above code is executed, <code>obj</code> will contain
++ * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
++ * instance is mapped to the "NOW" key in the map.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class LazyMap <K,V> extends AbstractMapDecorator<K, V> implements Map<K, V>, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 7990956402564206740L;
++
++ /**
++ * The factory to use to construct elements
++ */
++ //protected final Factory<V> factory;
++
++ /**
++ * The factory to use to construct elements
++ */
++ protected final Transformer<K, V> transformer;
++
++ /**
++ * Factory method to create a lazily instantiated map.
++ *
++ * @param map the map to decorate, must not be null
++ * @param factory the factory to use, must not be null
++ * @throws IllegalArgumentException if map or factory is null
++ */
++ public static <K,V> Map<K, V> decorate(Map<K, V> map, Factory<V> factory) {
++ return new LazyMap<K, V>(map, factory);
++ }
++
++ /**
++ * Factory method to create a lazily instantiated map.
++ *
++ * @param map Map to decorate, must not be null
++ * @param transformer Transformer to use, must not be null
++ * @throws IllegalArgumentException if map or transformer is null
++ */
++ public static <K,V> Map<K, V> decorate(Map<K, V> map, Transformer<K, V> transformer) {
++ return new LazyMap<K, V>(map, transformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @param factory the factory to use, must not be null
++ * @throws IllegalArgumentException if map or factory is null
++ */
++ protected LazyMap(Map<K, V> map, Factory<V> factory) {
++ super(map);
++ if (factory == null) {
++ throw new IllegalArgumentException("Factory must not be null");
++ }
++ this.transformer = new FactoryTransformer<K, V>(factory);
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map Map to decorate, must not be null
++ * @param transformer Transformer to use, must not be null
++ * @throws IllegalArgumentException if map or factory is null
++ */
++ protected LazyMap(Map<K, V> map, Transformer<K, V> transformer) {
++ super(map);
++ if (transformer == null) {
++ throw new IllegalArgumentException("Transformer must not be null");
++ }
++ this.transformer = transformer;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ * @since Commons Collections 3.1
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(map);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ * @since Commons Collections 3.1
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ map = (Map<K, V>) in.readObject();
++ }
++
++ //-----------------------------------------------------------------------
++ public V get(Object key) {
++ // create value for key if key is not currently in the map
++ if (map.containsKey(key) == false) {
++ V value = this.transformer.transform((K) key);
++ map.put((K) key, value);
++ return value;
++ }
++ return map.get(key);
++ }
++
++ // no need to wrap keySet, entrySet or values as they are views of
++ // existing map entries - you can't do a map-style get on them.
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/LazySortedMap.java
+@@ -0,0 +1,144 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import java.util.Comparator;
++import java.util.SortedMap;
++
++import org.apache.commons.collections15.Factory;
++import org.apache.commons.collections15.Transformer;
++
++/**
++ * Decorates another <code>SortedMap</code> to create objects in the map on demand.
++ * <p/>
++ * When the {@link #get(Object)} method is called with a key that does not
++ * exist in the map, the factory is used to create the object. The created
++ * object will be added to the map using the requested key.
++ * <p/>
++ * For instance:
++ * <pre>
++ * Factory factory = new Factory() {
++ * public Object create() {
++ * return new Date();
++ * }
++ * }
++ * SortedMap lazy = Lazy.sortedMap(new HashMap(), factory);
++ * Object obj = lazy.get("NOW");
++ * </pre>
++ * <p/>
++ * After the above code is executed, <code>obj</code> will contain
++ * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
++ * instance is mapped to the "NOW" key in the map.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class LazySortedMap <K,V> extends LazyMap<K, V> implements SortedMap<K, V> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 2715322183617658933L;
++
++ /**
++ * Factory method to create a lazily instantiated sorted map.
++ *
++ * @param map the map to decorate, must not be null
++ * @param factory the factory to use, must not be null
++ * @throws IllegalArgumentException if map or factory is null
++ */
++ public static <K,V> SortedMap<K, V> decorate(SortedMap<K, V> map, Factory<V> factory) {
++ return new LazySortedMap<K, V>(map, factory);
++ }
++
++ /**
++ * Factory method to create a lazily instantiated sorted map.
++ *
++ * @param map Map to decorate, must not be null
++ * @param transformer Transformer to use, must not be null
++ * @throws IllegalArgumentException if map or transformer is null
++ */
++ public static <K,V> SortedMap<K, V> decorate(SortedMap<K, V> map, Transformer<K, V> transformer) {
++ return new LazySortedMap<K, V>(map, transformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @param factory the factory to use, must not be null
++ * @throws IllegalArgumentException if map or factory is null
++ */
++ protected LazySortedMap(SortedMap<K, V> map, Factory<V> factory) {
++ super(map, factory);
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map Map to decorate, must not be null
++ * @param transformer Transformer to use, must not be null
++ * @throws IllegalArgumentException if map or transformer is null
++ */
++ protected LazySortedMap(SortedMap<K, V> map, Transformer<K, V> transformer) {
++ super(map, transformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the map being decorated.
++ *
++ * @return the decorated map
++ */
++ protected SortedMap<K, V> getSortedMap() {
++ return (SortedMap<K, V>) map;
++ }
++
++ //-----------------------------------------------------------------------
++ public K firstKey() {
++ return getSortedMap().firstKey();
++ }
++
++ public K lastKey() {
++ return getSortedMap().lastKey();
++ }
++
++ public Comparator<? super K> comparator() {
++ return getSortedMap().comparator();
++ }
++
++ public SortedMap<K, V> subMap(K fromKey, K toKey) {
++ SortedMap<K, V> map = getSortedMap().subMap(fromKey, toKey);
++ return new LazySortedMap<K, V>(map, transformer);
++ }
++
++ public SortedMap<K, V> headMap(K toKey) {
++ SortedMap<K, V> map = getSortedMap().headMap(toKey);
++ return new LazySortedMap<K, V>(map, transformer);
++ }
++
++ public SortedMap<K, V> tailMap(K fromKey) {
++ SortedMap<K, V> map = getSortedMap().tailMap(fromKey);
++ return new LazySortedMap<K, V>(map, transformer);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/LinkedMap.java
+@@ -0,0 +1,276 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.iterators.UnmodifiableIterator;
++import org.apache.commons.collections15.iterators.UnmodifiableListIterator;
++import org.apache.commons.collections15.list.UnmodifiableList;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.*;
++
++/**
++ * A <code>Map</code> implementation that maintains the order of the entries.
++ * In this implementation order is maintained by original insertion.
++ * <p/>
++ * This implementation improves on the JDK1.4 LinkedHashMap by adding the
++ * {@link org.apache.commons.collections15.MapIterator MapIterator}
++ * functionality, additional convenience methods and allowing
++ * bidirectional iteration. It also implements <code>OrderedMap</code>.
++ * In addition, non-interface methods are provided to access the map by index.
++ * <p/>
++ * The <code>orderedMapIterator()</code> method provides direct access to a
++ * bidirectional iterator. The iterators from the other views can also be cast
++ * to <code>OrderedIterator</code> if required.
++ * <p/>
++ * All the available iterators can be reset back to the start by casting to
++ * <code>ResettableIterator</code> and calling <code>reset()</code>.
++ * <p/>
++ * The implementation is also designed to be subclassed, with lots of useful
++ * methods exposed.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class LinkedMap <K,V> extends AbstractLinkedMap<K, V> implements Serializable, Cloneable {
++
++ /**
++ * Serialisation version
++ */
++ private static final long serialVersionUID = 9077234323521161066L;
++
++ /**
++ * Constructs a new empty map with default size and load factor.
++ */
++ public LinkedMap() {
++ super(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_THRESHOLD);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity.
++ *
++ * @param initialCapacity the initial capacity
++ * @throws IllegalArgumentException if the initial capacity is less than one
++ */
++ public LinkedMap(int initialCapacity) {
++ super(initialCapacity);
++ }
++
++ /**
++ * Constructs a new, empty map with the specified initial capacity and
++ * load factor.
++ *
++ * @param initialCapacity the initial capacity
++ * @param loadFactor the load factor
++ * @throws IllegalArgumentException if the initial capacity is less than one
++ * @throws IllegalArgumentException if the load factor is less than zero
++ */
++ public LinkedMap(int initialCapacity, float loadFactor) {
++ super(initialCapacity, loadFactor);
++ }
++
++ /**
++ * Constructor copying elements from another map.
++ *
++ * @param map the map to copy
++ * @throws NullPointerException if the map is null
++ */
++ public LinkedMap(Map<? extends K, ? extends V> map) {
++ super(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Clones the map without cloning the keys or values.
++ *
++ * @return a shallow clone
++ */
++ public Object clone() {
++ return super.clone();
++ }
++
++ /**
++ * Write the map out using a custom routine.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ doWriteObject(out);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ doReadObject(in);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the key at the specified index.
++ *
++ * @param index the index to retrieve
++ * @return the key at the specified index
++ * @throws IndexOutOfBoundsException if the index is invalid
++ */
++ public K get(int index) {
++ return getEntry(index).getKey();
++ }
++
++ /**
++ * Gets the value at the specified index.
++ *
++ * @param index the index to retrieve
++ * @return the key at the specified index
++ * @throws IndexOutOfBoundsException if the index is invalid
++ */
++ public V getValue(int index) {
++ return getEntry(index).getValue();
++ }
++
++ /**
++ * Gets the index of the specified key.
++ *
++ * @param key the key to find the index of
++ * @return the index, or -1 if not found
++ */
++ public int indexOf(Object key) {
++ int i = 0;
++ for (LinkEntry entry = header.after; entry != header; entry = entry.after, i++) {
++ if (isEqualKey(key, entry.getKey())) {
++ return i;
++ }
++ }
++ return -1;
++ }
++
++ /**
++ * Removes the element at the specified index.
++ *
++ * @param index the index of the object to remove
++ * @return the previous value corresponding the <code>key</code>,
++ * or <code>null</code> if none existed
++ * @throws IndexOutOfBoundsException if the index is invalid
++ */
++ public V remove(int index) {
++ return remove(get(index));
++ }
++
++ /**
++ * Gets an unmodifiable List view of the keys.
++ * <p/>
++ * The returned list is unmodifiable because changes to the values of
++ * the list (using {@link java.util.ListIterator#set(Object)}) will
++ * effectively remove the value from the list and reinsert that value at
++ * the end of the list, which is an unexpected side effect of changing the
++ * value of a list. This occurs because changing the key, changes when the
++ * mapping is added to the map and thus where it appears in the list.
++ * <p/>
++ * An alternative to this method is to use {@link #keySet()}.
++ *
++ * @return The ordered list of keys.
++ * @see #keySet()
++ */
++ public List<K> asList() {
++ return new LinkedMapList<K, V>(this);
++ }
++
++ /**
++ * List view of map.
++ */
++ static class LinkedMapList <K,V> extends AbstractList<K> {
++
++ final LinkedMap<K, V> parent;
++
++ LinkedMapList(LinkedMap<K, V> parent) {
++ this.parent = parent;
++ }
++
++ public int size() {
++ return parent.size();
++ }
++
++ public K get(int index) {
++ return parent.get(index);
++ }
++
++ public boolean contains(Object obj) {
++ return parent.containsKey(obj);
++ }
++
++ public int indexOf(Object obj) {
++ return parent.indexOf(obj);
++ }
++
++ public int lastIndexOf(Object obj) {
++ return parent.indexOf(obj);
++ }
++
++ public boolean containsAll(Collection<?> coll) {
++ return parent.keySet().containsAll(coll);
++ }
++
++ public K remove(int index) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean remove(Object obj) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public Object[] toArray() {
++ return parent.keySet().toArray();
++ }
++
++ public <T> T[] toArray(T[] array) {
++ return parent.keySet().toArray(array);
++ }
++
++ public Iterator<K> iterator() {
++ return UnmodifiableIterator.decorate(parent.keySet().iterator());
++ }
++
++ public ListIterator<K> listIterator() {
++ return UnmodifiableListIterator.decorate(super.listIterator());
++ }
++
++ public ListIterator<K> listIterator(int fromIndex) {
++ return UnmodifiableListIterator.decorate(super.listIterator(fromIndex));
++ }
++
++ public List<K> subList(int fromIndexInclusive, int toIndexExclusive) {
++ return UnmodifiableList.decorate(super.subList(fromIndexInclusive, toIndexExclusive));
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/ListOrderedMap.java
+@@ -0,0 +1,592 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.OrderedMap;
++import org.apache.commons.collections15.OrderedMapIterator;
++import org.apache.commons.collections15.ResettableIterator;
++import org.apache.commons.collections15.iterators.AbstractIteratorDecorator;
++import org.apache.commons.collections15.keyvalue.AbstractMapEntry;
++import org.apache.commons.collections15.list.UnmodifiableList;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.*;
++
++/**
++ * Decorates a <code>Map</code> to ensure that the order of addition is retained
++ * using a <code>List</code> to maintain order.
++ * <p/>
++ * The order will be used via the iterators and toArray methods on the views.
++ * The order is also returned by the <code>MapIterator</code>.
++ * The <code>orderedMapIterator()</code> method accesses an iterator that can
++ * iterate both forwards and backwards through the map.
++ * In addition, non-interface methods are provided to access the map by index.
++ * <p/>
++ * If an object is added to the Map for a second time, it will remain in the
++ * original position in the iteration.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Henri Yandell
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class ListOrderedMap <K,V> extends AbstractMapDecorator<K, V> implements OrderedMap<K, V>, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 2728177751851003750L;
++
++ /**
++ * Internal list to hold the sequence of objects
++ */
++ protected final List<K> insertOrder = new ArrayList<K>();
++
++ /**
++ * Factory method to create an ordered map.
++ * <p/>
++ * An <code>ArrayList</code> is used to retain order.
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ public static <K,V> OrderedMap<K, V> decorate(Map<K, V> map) {
++ return new ListOrderedMap<K, V>(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructs a new empty <code>ListOrderedMap</code> that decorates
++ * a <code>HashMap</code>.
++ *
++ * @since Commons Collections 3.1
++ */
++ public ListOrderedMap() {
++ this(new HashMap<K, V>());
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ protected ListOrderedMap(Map<K, V> map) {
++ super(map);
++ insertOrder.addAll(getMap().keySet());
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ * @since Commons Collections 3.1
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(map);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ * @since Commons Collections 3.1
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ map = (Map<K, V>) in.readObject();
++ }
++
++ // Implement OrderedMap
++ //-----------------------------------------------------------------------
++ public MapIterator<K, V> mapIterator() {
++ return orderedMapIterator();
++ }
++
++ public OrderedMapIterator<K, V> orderedMapIterator() {
++ return new ListOrderedMapIterator<K, V>(this);
++ }
++
++ /**
++ * Gets the first key in this map by insert order.
++ *
++ * @return the first key currently in this map
++ * @throws NoSuchElementException if this map is empty
++ */
++ public K firstKey() {
++ if (size() == 0) {
++ throw new NoSuchElementException("Map is empty");
++ }
++ return insertOrder.get(0);
++ }
++
++ /**
++ * Gets the last key in this map by insert order.
++ *
++ * @return the last key currently in this map
++ * @throws NoSuchElementException if this map is empty
++ */
++ public K lastKey() {
++ if (size() == 0) {
++ throw new NoSuchElementException("Map is empty");
++ }
++ return insertOrder.get(size() - 1);
++ }
++
++ /**
++ * Gets the next key to the one specified using insert order.
++ * This method performs a list search to find the key and is O(n).
++ *
++ * @param key the key to find previous for
++ * @return the next key, null if no match or at start
++ */
++ public K nextKey(K key) {
++ int index = insertOrder.indexOf(key);
++ if (index >= 0 && index < size() - 1) {
++ return insertOrder.get(index + 1);
++ }
++ return null;
++ }
++
++ /**
++ * Gets the previous key to the one specified using insert order.
++ * This method performs a list search to find the key and is O(n).
++ *
++ * @param key the key to find previous for
++ * @return the previous key, null if no match or at start
++ */
++ public K previousKey(K key) {
++ int index = insertOrder.indexOf(key);
++ if (index > 0) {
++ return insertOrder.get(index - 1);
++ }
++ return null;
++ }
++
++ //-----------------------------------------------------------------------
++ public V put(K key, V value) {
++ if (getMap().containsKey(key)) {
++ // re-adding doesn't change order
++ return getMap().put(key, value);
++ } else {
++ // first add, so add to both map and list
++ V result = getMap().put(key, value);
++ insertOrder.add(key);
++ return result;
++ }
++ }
++
++ public void putAll(Map<? extends K, ? extends V> map) {
++ for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
++ Map.Entry entry = (Map.Entry) it.next();
++ put((K) entry.getKey(), (V) entry.getValue());
++ }
++ }
++
++ public V remove(Object key) {
++ V result = getMap().remove(key);
++ insertOrder.remove(key);
++ return result;
++ }
++
++ public void clear() {
++ getMap().clear();
++ insertOrder.clear();
++ }
++
++ //-----------------------------------------------------------------------
++ public Set<K> keySet() {
++ return new KeySetView<K, V>(this);
++ }
++
++ public Collection<V> values() {
++ return new ValuesView<K, V>(this);
++ }
++
++ public Set<Map.Entry<K,V>> entrySet() {
++ return new EntrySetView<K,V>(this, this.insertOrder);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Returns the Map as a string.
++ *
++ * @return the Map as a String
++ */
++ public String toString() {
++ if (isEmpty()) {
++ return "{}";
++ }
++ StringBuffer buf = new StringBuffer();
++ buf.append('{');
++ boolean first = true;
++ Iterator it = entrySet().iterator();
++ while (it.hasNext()) {
++ Map.Entry entry = (Map.Entry) it.next();
++ Object key = entry.getKey();
++ Object value = entry.getValue();
++ if (first) {
++ first = false;
++ } else {
++ buf.append(", ");
++ }
++ buf.append(key == this ? "(this Map)" : key);
++ buf.append('=');
++ buf.append(value == this ? "(this Map)" : value);
++ }
++ buf.append('}');
++ return buf.toString();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the key at the specified index.
++ *
++ * @param index the index to retrieve
++ * @return the key at the specified index
++ * @throws IndexOutOfBoundsException if the index is invalid
++ */
++ public K get(int index) {
++ return insertOrder.get(index);
++ }
++
++ /**
++ * Gets the value at the specified index.
++ *
++ * @param index the index to retrieve
++ * @return the key at the specified index
++ * @throws IndexOutOfBoundsException if the index is invalid
++ */
++ public V getValue(int index) {
++ return get(insertOrder.get(index));
++ }
++
++ /**
++ * Gets the index of the specified key.
++ *
++ * @param key the key to find the index of
++ * @return the index, or -1 if not found
++ */
++ public int indexOf(Object key) {
++ return insertOrder.indexOf(key);
++ }
++
++ /**
++ * Removes the element at the specified index.
++ *
++ * @param index the index of the object to remove
++ * @return the previous value corresponding the <code>key</code>,
++ * or <code>null</code> if none existed
++ * @throws IndexOutOfBoundsException if the index is invalid
++ */
++ public Object remove(int index) {
++ return remove(get(index));
++ }
++
++ /**
++ * Gets an unmodifiable List view of the keys which changes as the map changes.
++ * <p/>
++ * The returned list is unmodifiable because changes to the values of
++ * the list (using {@link java.util.ListIterator#set(Object)}) will
++ * effectively remove the value from the list and reinsert that value at
++ * the end of the list, which is an unexpected side effect of changing the
++ * value of a list. This occurs because changing the key, changes when the
++ * mapping is added to the map and thus where it appears in the list.
++ * <p/>
++ * An alternative to this method is to use {@link #keySet()}.
++ *
++ * @return The ordered list of keys.
++ * @see #keySet()
++ */
++ public List<K> asList() {
++ return UnmodifiableList.decorate(insertOrder);
++ }
++
++ //-----------------------------------------------------------------------
++ static class ValuesView <K,V> extends AbstractCollection<V> {
++ private final ListOrderedMap<K, V> parent;
++
++ ValuesView(ListOrderedMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ }
++
++ public int size() {
++ return this.parent.size();
++ }
++
++ public boolean contains(Object value) {
++ return this.parent.containsValue(value);
++ }
++
++ public void clear() {
++ this.parent.clear();
++ }
++
++ public Iterator<V> iterator() {
++ return new AbstractIteratorDecorator(parent.entrySet().iterator()) {
++ public Object next() {
++ return ((Map.Entry) iterator.next()).getValue();
++ }
++ };
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ static class KeySetView <K,V> extends AbstractSet<K> {
++ private final ListOrderedMap<K, V> parent;
++
++ KeySetView(ListOrderedMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ }
++
++ public int size() {
++ return this.parent.size();
++ }
++
++ public boolean contains(Object value) {
++ return this.parent.containsKey(value);
++ }
++
++ public void clear() {
++ this.parent.clear();
++ }
++
++ public Iterator<K> iterator() {
++ final Iterator<Map.Entry<K, V>> entryIterator = parent.entrySet().iterator();
++ return new Iterator<K>() {
++ public K next() {
++ return entryIterator.next().getKey();
++ }
++
++ public boolean hasNext() {
++ return entryIterator.hasNext();
++ }
++
++ public void remove() {
++ entryIterator.remove();
++ }
++ };
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ static class EntrySetView <K,V> extends AbstractSet<Map.Entry<K, V>> {
++ private final ListOrderedMap<K, V> parent;
++ private final List<K> insertOrder;
++ private Set<Map.Entry<K, V>> entrySet;
++
++ public EntrySetView(ListOrderedMap<K, V> parent, List<K> insertOrder) {
++ super();
++ this.parent = parent;
++ this.insertOrder = insertOrder;
++ }
++
++ private Set<Map.Entry<K, V>> getEntrySet() {
++ if (entrySet == null) {
++ entrySet = parent.getMap().entrySet();
++ }
++ return entrySet;
++ }
++
++ public int size() {
++ return this.parent.size();
++ }
++
++ public boolean isEmpty() {
++ return this.parent.isEmpty();
++ }
++
++ public boolean contains(Object obj) {
++ return getEntrySet().contains(obj);
++ }
++
++ public boolean containsAll(Collection<?> coll) {
++ return getEntrySet().containsAll(coll);
++ }
++
++ public boolean remove(Object obj) {
++ if (obj instanceof Map.Entry == false) {
++ return false;
++ }
++ if (getEntrySet().contains(obj)) {
++ Object key = ((Map.Entry) obj).getKey();
++ parent.remove(key);
++ return true;
++ }
++ return false;
++ }
++
++ public void clear() {
++ this.parent.clear();
++ }
++
++ public boolean equals(Object obj) {
++ if (obj == this) {
++ return true;
++ }
++ return getEntrySet().equals(obj);
++ }
++
++ public int hashCode() {
++ return getEntrySet().hashCode();
++ }
++
++ public String toString() {
++ return getEntrySet().toString();
++ }
++
++ public Iterator<Map.Entry<K, V>> iterator() {
++ return new ListOrderedIterator<K, V>(parent, insertOrder);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ static class ListOrderedIterator <K,V> implements Iterator<Map.Entry<K, V>> {
++ private final ListOrderedMap<K, V> parent;
++ private K last = null;
++ private Iterator<K> listIterator;
++
++ ListOrderedIterator(ListOrderedMap<K, V> parent, List<K> insertOrder) {
++ listIterator = insertOrder.iterator();
++ this.parent = parent;
++ }
++
++ public Map.Entry<K, V> next() {
++ last = listIterator.next();
++ return new ListOrderedMapEntry<K, V>(parent, last);
++ }
++
++ public void remove() {
++ listIterator.remove();
++ parent.getMap().remove(last);
++ }
++
++ public boolean hasNext() {
++ return listIterator.hasNext();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ static class ListOrderedMapEntry <K,V> extends AbstractMapEntry<K, V> {
++ private final ListOrderedMap<K, V> parent;
++
++ ListOrderedMapEntry(ListOrderedMap<K, V> parent, K key) {
++ super(key, null);
++ this.parent = parent;
++ }
++
++ public V getValue() {
++ return parent.get(key);
++ }
++
++ public V setValue(V value) {
++ return parent.getMap().put(key, value);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ static class ListOrderedMapIterator <K,V> implements OrderedMapIterator<K, V>, ResettableIterator<K> {
++ private final ListOrderedMap<K, V> parent;
++ private ListIterator<K> iterator;
++ private K last = null;
++ private boolean readable = false;
++
++ ListOrderedMapIterator(ListOrderedMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ this.iterator = parent.insertOrder.listIterator();
++ }
++
++ public boolean hasNext() {
++ return iterator.hasNext();
++ }
++
++ public K next() {
++ last = iterator.next();
++ readable = true;
++ return last;
++ }
++
++ public boolean hasPrevious() {
++ return iterator.hasPrevious();
++ }
++
++ public K previous() {
++ last = iterator.previous();
++ readable = true;
++ return last;
++ }
++
++ public void remove() {
++ if (readable == false) {
++ throw new IllegalStateException(AbstractHashedMap.REMOVE_INVALID);
++ }
++ iterator.remove();
++ parent.map.remove(last);
++ readable = false;
++ }
++
++ public K getKey() {
++ if (readable == false) {
++ throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
++ }
++ return last;
++ }
++
++ public V getValue() {
++ if (readable == false) {
++ throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
++ }
++ return parent.get(last);
++ }
++
++ public V setValue(V value) {
++ if (readable == false) {
++ throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
++ }
++ return parent.map.put(last, value);
++ }
++
++ public void reset() {
++ iterator = parent.insertOrder.listIterator();
++ last = null;
++ readable = false;
++ }
++
++ public String toString() {
++ if (readable == true) {
++ return "Iterator[" + getKey() + "=" + getValue() + "]";
++ } else {
++ return "Iterator[]";
++ }
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/MultiKeyMap.java
+@@ -0,0 +1,488 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.IterableMap;
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.keyvalue.MultiKey;
++
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * A <code>Map</code> implementation that uses multiple keys to map the value.
++ * <p/>
++ * This class is the most efficient way to uses multiple keys to map to a value.
++ * The best way to use this class is via the additional map-style methods.
++ * These provide <code>get</code>, <code>containsKey</code>, <code>put</code> and
++ * <code>remove</code> for individual keys which operate without extra object creation.
++ * <p/>
++ * The additional methods are the main interface of this map.
++ * As such, you will not normally hold this map in a variable of type <code>Map</code>.
++ * <p/>
++ * The normal map methods take in and return a {@link MultiKey}.
++ * If you try to use <code>put()</code> with any other object type a
++ * <code>ClassCastException</code> is thrown. If you try to use <code>null</code> as
++ * the key in <code>put()</code> a <code>NullPointerException</code> is thrown.
++ * <p/>
++ * This map is implemented as a decorator of a <code>AbstractHashedMap</code> which
++ * enables extra behaviour to be added easily.
++ * <ul>
++ * <li><code>MultiKeyMap.decorate(new LinkedMap())</code> creates an ordered map.
++ * <li><code>MultiKeyMap.decorate(new LRUMap())</code> creates an least recently used map.
++ * <li><code>MultiKeyMap.decorate(new ReferenceMap())</code> creates a garbage collector sensitive map.
++ * </ul>
++ * Note that <code>IdentityMap</code> and <code>ReferenceIdentityMap</code> are unsuitable
++ * for use as the key comparison would work on the whole MultiKey, not the elements within.
++ * <p/>
++ * As an example, consider a least recently used cache that uses a String airline code
++ * and a Locale to lookup the airline's name:
++ * <pre>
++ * private MultiKeyMap cache = MultiKeyMap.decorate(new LRUMap(50));
++ * <p/>
++ * public String getAirlineName(String code, String locale) {
++ * String name = (String) cache.get(code, locale);
++ * if (name == null) {
++ * name = getAirlineNameFromDB(code, locale);
++ * cache.put(code, locale, name);
++ * }
++ * return name;
++ * }
++ * </pre>
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.1
++ */
++public class MultiKeyMap <K,V> implements IterableMap<MultiKey<K>, V>, Serializable {
++
++ /**
++ * Serialisation version
++ */
++ private static final long serialVersionUID = -1788199231038721040L;
++
++ /**
++ * The decorated map
++ */
++ protected final AbstractHashedMap<MultiKey<K>, V> map;
++
++ //-----------------------------------------------------------------------
++ /**
++ * Decorates the specified map to add the MultiKeyMap API and fast query.
++ * The map must not be null and must be empty.
++ *
++ * @param map the map to decorate, not null
++ * @throws IllegalArgumentException if the map is null or not empty
++ */
++ public static <K,V> MultiKeyMap<K, V> decorate(AbstractHashedMap<MultiKey<K>, V> map) {
++ if (map == null) {
++ throw new IllegalArgumentException("Map must not be null");
++ }
++ if (map.size() > 0) {
++ throw new IllegalArgumentException("Map must be empty");
++ }
++ return new MultiKeyMap<K, V>(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructs a new MultiKeyMap that decorates a <code>HashedMap</code>.
++ */
++ public MultiKeyMap() {
++ super();
++ map = new HashedMap<MultiKey<K>, V>();
++ }
++
++ /**
++ * Constructor that decorates the specified map and is called from
++ * {@link #decorate(AbstractHashedMap)}.
++ * The map must not be null and should be empty or only contain valid keys.
++ * This constructor performs no validation.
++ *
++ * @param map the map to decorate
++ */
++ protected MultiKeyMap(AbstractHashedMap<MultiKey<K>, V> map) {
++ super();
++ this.map = map;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the value mapped to the specified multi-key.
++ *
++ * @param keys the keys
++ * @return the mapped value, null if no match
++ */
++ public V get(K... keys) {
++ int hashCode = hash(keys);
++ AbstractHashedMap.HashEntry<MultiKey<K>, V> entry = map.data[map.hashIndex(hashCode, map.data.length)];
++ while (entry != null) {
++ if (entry.hashCode == hashCode && isEqualKey(entry, keys)) {
++ return entry.getValue();
++ }
++ entry = entry.next;
++ }
++ return null;
++ }
++
++ /**
++ * Checks whether the map contains the specified multi-key.
++ *
++ * @param keys the keys
++ * @return true if the map contains the key
++ */
++ public boolean containsKey(K... keys) {
++ int hashCode = hash(keys);
++ AbstractHashedMap.HashEntry<MultiKey<K>, V> entry = map.data[map.hashIndex(hashCode, map.data.length)];
++ while (entry != null) {
++ if (entry.hashCode == hashCode && isEqualKey(entry, keys)) {
++ return true;
++ }
++ entry = entry.next;
++ }
++ return false;
++ }
++
++ /**
++ * For backwards compatibility, makes a call to the new varargs {@link MultiKeyMap#putMultiKey}
++ */
++ public V put(K key1, K key2, V value) {
++ return putMultiKey(value, key1, key2);
++ }
++
++ /**
++ * For backwards compatibility, makes a call to the new varargs {@link MultiKeyMap#putMultiKey}
++ */
++ public V put(K key1, K key2, K key3, V value) {
++ return putMultiKey(value, key1, key2, key3);
++ }
++
++ /**
++ * For backwards compatibility, makes a call to the new varargs {@link MultiKeyMap#putMultiKey}
++ */
++ public V put(K key1, K key2, K key3, K key4, V value) {
++ return putMultiKey(value, key1, key2, key3, key4);
++ }
++
++ /**
++ * For backwards compatibility, makes a call to the new varargs {@link MultiKeyMap#putMultiKey}
++ */
++ public V put(K key1, K key2, K key3, K key4, K key5, V value) {
++ return putMultiKey(value, key1, key2, key3, key4, key5);
++ }
++
++ /**
++ * Stores the value against the specified multi-key.
++ *
++ * @param value the value to store
++ * @param keys the keys
++ * @return the value previously mapped to this combined key, null if none
++ */
++ public V putMultiKey(V value, K... keys) {
++ int hashCode = hash(keys);
++ int index = map.hashIndex(hashCode, map.data.length);
++ AbstractHashedMap.HashEntry<MultiKey<K>, V> entry = map.data[index];
++ while (entry != null) {
++ if (entry.hashCode == hashCode && isEqualKey(entry, keys)) {
++ V oldValue = entry.getValue();
++ map.updateEntry(entry, value);
++ return oldValue;
++ }
++ entry = entry.next;
++ }
++
++ map.addMapping(index, hashCode, new MultiKey<K>(keys), value);
++ return null;
++ }
++
++ /**
++ * Removes the specified multi-key from this map.
++ *
++ * @param keys the keys
++ * @return the value mapped to the removed key, null if key not in map
++ */
++ public Object remove(K... keys) {
++ int hashCode = hash(keys);
++ int index = map.hashIndex(hashCode, map.data.length);
++ AbstractHashedMap.HashEntry<MultiKey<K>, V> entry = map.data[index];
++ AbstractHashedMap.HashEntry<MultiKey<K>, V> previous = null;
++ while (entry != null) {
++ if (entry.hashCode == hashCode && isEqualKey(entry, keys)) {
++ Object oldValue = entry.getValue();
++ map.removeMapping(entry, index, previous);
++ return oldValue;
++ }
++ previous = entry;
++ entry = entry.next;
++ }
++ return null;
++ }
++
++ /**
++ * Gets the hash code for the specified multi-key.
++ *
++ * @param keys the keys
++ * @return the hash code
++ */
++ protected int hash(K... keys) {
++ int h = 0;
++ for (int i = 0; i < keys.length; i++) {
++ K key = keys[i];
++ if (key != null) {
++ h ^= key.hashCode();
++ }
++ }
++ h += ~(h << 9);
++ h ^= (h >>> 14);
++ h += (h << 4);
++ h ^= (h >>> 10);
++ return h;
++ }
++
++ /**
++ * Is the key equal to the combined key.
++ *
++ * @param entry the entry to compare to
++ * @param keys the keys
++ * @return true if the key matches
++ */
++ protected boolean isEqualKey(AbstractHashedMap.HashEntry<MultiKey<K>, V> entry, K... keys) {
++ MultiKey multi = (MultiKey) entry.getKey();
++ if (multi.size() != keys.length) {
++ return false;
++ } else {
++ for (int i = 0; i < keys.length; i++) {
++ K key = keys[i];
++ if ((key == null ? multi.getKey(i) != null : !key.equals(multi.getKey(i)))) {
++ return false;
++ }
++ }
++ }
++ return true;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Removes all mappings where the first key is that specified.
++ * <p/>
++ * This method removes all the mappings where the <code>MultiKey</code>
++ * has one or more keys, and the first matches that specified.
++ *
++ * @param key1 the first key
++ * @return true if any elements were removed
++ */
++ public boolean removeAll(Object key1) {
++ boolean modified = false;
++ MapIterator it = mapIterator();
++ while (it.hasNext()) {
++ MultiKey multi = (MultiKey) it.next();
++ if (multi.size() >= 1 && (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0)))) {
++ it.remove();
++ modified = true;
++ }
++ }
++ return modified;
++ }
++
++ /**
++ * Removes all mappings where the first two keys are those specified.
++ * <p/>
++ * This method removes all the mappings where the <code>MultiKey</code>
++ * has two or more keys, and the first two match those specified.
++ *
++ * @param key1 the first key
++ * @param key2 the second key
++ * @return true if any elements were removed
++ */
++ public boolean removeAll(Object key1, Object key2) {
++ boolean modified = false;
++ MapIterator it = mapIterator();
++ while (it.hasNext()) {
++ MultiKey multi = (MultiKey) it.next();
++ if (multi.size() >= 2 && (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1)))) {
++ it.remove();
++ modified = true;
++ }
++ }
++ return modified;
++ }
++
++ /**
++ * Removes all mappings where the first three keys are those specified.
++ * <p/>
++ * This method removes all the mappings where the <code>MultiKey</code>
++ * has three or more keys, and the first three match those specified.
++ *
++ * @param key1 the first key
++ * @param key2 the second key
++ * @param key3 the third key
++ * @return true if any elements were removed
++ */
++ public boolean removeAll(Object key1, Object key2, Object key3) {
++ boolean modified = false;
++ MapIterator it = mapIterator();
++ while (it.hasNext()) {
++ MultiKey multi = (MultiKey) it.next();
++ if (multi.size() >= 3 && (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) && (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2)))) {
++ it.remove();
++ modified = true;
++ }
++ }
++ return modified;
++ }
++
++ /**
++ * Removes all mappings where the first four keys are those specified.
++ * <p/>
++ * This method removes all the mappings where the <code>MultiKey</code>
++ * has four or more keys, and the first four match those specified.
++ *
++ * @param key1 the first key
++ * @param key2 the second key
++ * @param key3 the third key
++ * @param key4 the fourth key
++ * @return true if any elements were removed
++ */
++ public boolean removeAll(Object key1, Object key2, Object key3, Object key4) {
++ boolean modified = false;
++ MapIterator it = mapIterator();
++ while (it.hasNext()) {
++ MultiKey multi = (MultiKey) it.next();
++ if (multi.size() >= 4 && (key1 == null ? multi.getKey(0) == null : key1.equals(multi.getKey(0))) && (key2 == null ? multi.getKey(1) == null : key2.equals(multi.getKey(1))) && (key3 == null ? multi.getKey(2) == null : key3.equals(multi.getKey(2))) && (key4 == null ? multi.getKey(3) == null : key4.equals(multi.getKey(3)))) {
++ it.remove();
++ modified = true;
++ }
++ }
++ return modified;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Check to ensure that input keys are valid MultiKey objects.
++ *
++ * @param key the key to check
++ */
++ protected void checkKey(Object key) {
++ if (key == null) {
++ throw new NullPointerException("Key must not be null");
++ }
++ }
++
++ /**
++ * Clones the map without cloning the keys or values.
++ *
++ * @return a shallow clone
++ */
++ public Object clone() {
++ return new MultiKeyMap((AbstractHashedMap) map.clone());
++ }
++
++ /**
++ * Puts the key and value into the map, where the key must be a non-null
++ * MultiKey object.
++ *
++ * @param key the non-null MultiKey object
++ * @param value the value to store
++ * @return the previous value for the key
++ * @throws NullPointerException if the key is null
++ * @throws ClassCastException if the key is not a MultiKey
++ */
++ public V put(MultiKey<K> key, V value) {
++ checkKey(key);
++ return map.put(key, value);
++ }
++
++ /**
++ * Puts all the keys and values into this map.
++ * Each key must be non-null and a MultiKey object.
++ *
++ * @param mapToCopy the map to copy in.
++ * @throws NullPointerException if the mapToCopy or any key within is null
++ * @throws ClassCastException if any key is not a MultiKey
++ */
++ public void putAll(Map<? extends MultiKey<K>, ? extends V> mapToCopy) {
++ for (Iterator it = mapToCopy.keySet().iterator(); it.hasNext();) {
++ Object key = it.next();
++ checkKey(key);
++ }
++ map.putAll(mapToCopy);
++ }
++
++ //-----------------------------------------------------------------------
++ public MapIterator mapIterator() {
++ return map.mapIterator();
++ }
++
++ public int size() {
++ return map.size();
++ }
++
++ public boolean isEmpty() {
++ return map.isEmpty();
++ }
++
++ public boolean containsKey(Object key) {
++ return map.containsKey(key);
++ }
++
++ public boolean containsValue(Object value) {
++ return map.containsValue(value);
++ }
++
++ public V get(Object key) {
++ return map.get(key);
++ }
++
++ public V remove(Object key) {
++ return map.remove(key);
++ }
++
++ public void clear() {
++ map.clear();
++ }
++
++ public Set keySet() {
++ return map.keySet();
++ }
++
++ public Collection values() {
++ return map.values();
++ }
++
++ public Set entrySet() {
++ return map.entrySet();
++ }
++
++ public boolean equals(Object obj) {
++ if (obj == this) {
++ return true;
++ }
++ return map.equals(obj);
++ }
++
++ public int hashCode() {
++ return map.hashCode();
++ }
++
++ public String toString() {
++ return map.toString();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/PredicatedMap.java
+@@ -0,0 +1,184 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Iterator;
++import java.util.Map;
++
++/**
++ * Decorates another <code>Map</code> to validate that additions
++ * match a specified predicate.
++ * <p/>
++ * This map exists to provide validation for the decorated map.
++ * It is normally created to decorate an empty map.
++ * If an object cannot be added to the map, an IllegalArgumentException is thrown.
++ * <p/>
++ * One usage would be to ensure that no null keys are added to the map.
++ * <pre>Map map = PredicatedSet.decorate(new HashMap(), NotNullPredicate.INSTANCE, null);</pre>
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class PredicatedMap <K,V> extends AbstractInputCheckedMapDecorator<K, V> implements Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 7412622456128415156L;
++
++ /**
++ * The key predicate to use
++ */
++ protected final Predicate<? super K> keyPredicate;
++ /**
++ * The value predicate to use
++ */
++ protected final Predicate<? super V> valuePredicate;
++
++ /**
++ * Factory method to create a predicated (validating) map.
++ * <p/>
++ * If there are any elements already in the list being decorated, they
++ * are validated.
++ *
++ * @param map the map to decorate, must not be null
++ * @param keyPredicate the predicate to validate the keys, null means no check
++ * @param valuePredicate the predicate to validate to values, null means no check
++ * @throws IllegalArgumentException if the map is null
++ */
++ public static <K,V> Map<K, V> decorate(Map<K, V> map, Predicate<? super K> keyPredicate, Predicate<? super V> valuePredicate) {
++ return new PredicatedMap<K, V>(map, keyPredicate, valuePredicate);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @param keyPredicate the predicate to validate the keys, null means no check
++ * @param valuePredicate the predicate to validate to values, null means no check
++ * @throws IllegalArgumentException if the map is null
++ */
++ protected PredicatedMap(Map<K, V> map, Predicate<? super K> keyPredicate, Predicate<? super V> valuePredicate) {
++ super(map);
++ this.keyPredicate = keyPredicate;
++ this.valuePredicate = valuePredicate;
++
++ Iterator<Map.Entry<K, V>> it = map.entrySet().iterator();
++ while (it.hasNext()) {
++ Map.Entry<K, V> entry = it.next();
++ K key = entry.getKey();
++ V value = entry.getValue();
++ validate(key, value);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ * @since Commons Collections 3.1
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(map);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ * @since Commons Collections 3.1
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ map = (Map<K, V>) in.readObject();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Validates a key value pair.
++ *
++ * @param key the key to validate
++ * @param value the value to validate
++ * @throws IllegalArgumentException if invalid
++ */
++ protected void validate(K key, V value) {
++ if (keyPredicate != null && keyPredicate.evaluate(key) == false) {
++ throw new IllegalArgumentException("Cannot add key - Predicate rejected it");
++ }
++ if (valuePredicate != null && valuePredicate.evaluate(value) == false) {
++ throw new IllegalArgumentException("Cannot add value - Predicate rejected it");
++ }
++ }
++
++ /**
++ * Override to validate an object set into the map via <code>setValue</code>.
++ *
++ * @param value the value to validate
++ * @throws IllegalArgumentException if invalid
++ * @since Commons Collections 3.1
++ */
++ protected V checkSetValue(V value) {
++ if (valuePredicate.evaluate(value) == false) {
++ throw new IllegalArgumentException("Cannot set value - Predicate rejected it");
++ }
++ return value;
++ }
++
++ /**
++ * Override to only return true when there is a value transformer.
++ *
++ * @return true if a value predicate is in use
++ * @since Commons Collections 3.1
++ */
++ protected boolean isSetValueChecking() {
++ return (valuePredicate != null);
++ }
++
++ //-----------------------------------------------------------------------
++ public V put(K key, V value) {
++ validate(key, value);
++ return map.put(key, value);
++ }
++
++ public void putAll(Map<? extends K, ? extends V> mapToCopy) {
++ Iterator it = mapToCopy.entrySet().iterator();
++ while (it.hasNext()) {
++ Map.Entry entry = (Map.Entry) it.next();
++ K key = (K) entry.getKey();
++ V value = (V) entry.getValue();
++ validate(key, value);
++ }
++ map.putAll(mapToCopy);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/PredicatedSortedMap.java
+@@ -0,0 +1,115 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.util.Comparator;
++import java.util.SortedMap;
++
++/**
++ * Decorates another <code>SortedMap </code> to validate that additions
++ * match a specified predicate.
++ * <p/>
++ * This map exists to provide validation for the decorated map.
++ * It is normally created to decorate an empty map.
++ * If an object cannot be added to the map, an IllegalArgumentException is thrown.
++ * <p/>
++ * One usage would be to ensure that no null keys are added to the map.
++ * <pre>SortedMap map = PredicatedSortedSet.decorate(new TreeMap(), NotNullPredicate.INSTANCE, null);</pre>
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class PredicatedSortedMap <K,V> extends PredicatedMap<K, V> implements SortedMap<K, V> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 3359846175935304332L;
++
++ /**
++ * Factory method to create a predicated (validating) sorted map.
++ * <p/>
++ * If there are any elements already in the list being decorated, they
++ * are validated.
++ *
++ * @param map the map to decorate, must not be null
++ * @param keyPredicate the predicate to validate the keys, null means no check
++ * @param valuePredicate the predicate to validate to values, null means no check
++ * @throws IllegalArgumentException if the map is null
++ */
++ public static <K,V> SortedMap<K, V> decorate(SortedMap<K, V> map, Predicate<? super K> keyPredicate, Predicate<? super V> valuePredicate) {
++ return new PredicatedSortedMap<K, V>(map, keyPredicate, valuePredicate);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @param keyPredicate the predicate to validate the keys, null means no check
++ * @param valuePredicate the predicate to validate to values, null means no check
++ * @throws IllegalArgumentException if the map is null
++ */
++ protected PredicatedSortedMap(SortedMap<K, V> map, Predicate<? super K> keyPredicate, Predicate<? super V> valuePredicate) {
++ super(map, keyPredicate, valuePredicate);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the map being decorated.
++ *
++ * @return the decorated map
++ */
++ protected SortedMap<K, V> getSortedMap() {
++ return (SortedMap<K, V>) map;
++ }
++
++ //-----------------------------------------------------------------------
++ public K firstKey() {
++ return getSortedMap().firstKey();
++ }
++
++ public K lastKey() {
++ return getSortedMap().lastKey();
++ }
++
++ public Comparator<? super K> comparator() {
++ return getSortedMap().comparator();
++ }
++
++ public SortedMap<K, V> subMap(K fromKey, K toKey) {
++ SortedMap<K, V> map = getSortedMap().subMap(fromKey, toKey);
++ return new PredicatedSortedMap<K, V>(map, keyPredicate, valuePredicate);
++ }
++
++ public SortedMap<K, V> headMap(K toKey) {
++ SortedMap map = getSortedMap().headMap(toKey);
++ return new PredicatedSortedMap<K, V>(map, keyPredicate, valuePredicate);
++ }
++
++ public SortedMap<K, V> tailMap(K fromKey) {
++ SortedMap<K, V> map = getSortedMap().tailMap(fromKey);
++ return new PredicatedSortedMap<K, V>(map, keyPredicate, valuePredicate);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/ReferenceIdentityMap.java
+@@ -0,0 +1,212 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.lang.ref.Reference;
++
++/**
++ * A <code>Map</code> implementation that allows mappings to be
++ * removed by the garbage collector and matches keys and values based
++ * on <code>==</code> not <code>equals()</code>.
++ * <p/>
++ * <p/>
++ * When you construct a <code>ReferenceIdentityMap</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 default constructor uses hard keys and soft values, providing a
++ * memory-sensitive cache.
++ * <p/>
++ * This map is similar to
++ * {@link org.apache.commons.collections15.map.ReferenceMap ReferenceMap}.
++ * It differs in that keys and values in this class are compared using <code>==</code>.
++ * <p/>
++ * This map will violate the detail of various Map and map view contracts.
++ * As a general rule, don't compare this map to other maps.
++ * <p/>
++ * This {@link java.util.Map} implementation does <i>not</i> allow null elements.
++ * Attempting to add a null key or value to the map will raise a <code>NullPointerException</code>.
++ * <p/>
++ * This implementation is not synchronized.
++ * You can use {@link java.util.Collections#synchronizedMap} to
++ * provide synchronized access to a <code>ReferenceIdentityMap</code>.
++ * Remember that synchronization will not stop the garbage collecter removing entries.
++ * <p/>
++ * All the available iterators can be reset back to the start by casting to
++ * <code>ResettableIterator</code> and calling <code>reset()</code>.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @see java.lang.ref.Reference
++ * @since Commons Collections 3.0 (previously in main package v2.1)
++ */
++public class ReferenceIdentityMap <K,V> extends AbstractReferenceMap<K, V> implements Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -1266190134568365852L;
++
++ /**
++ * Constructs a new <code>ReferenceIdentityMap</code> that will
++ * use hard references to keys and soft references to values.
++ */
++ public ReferenceIdentityMap() {
++ super(HARD, SOFT, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
++ }
++
++ /**
++ * Constructs a new <code>ReferenceIdentityMap</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 ReferenceIdentityMap(int keyType, int valueType) {
++ super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
++ }
++
++ /**
++ * Constructs a new <code>ReferenceIdentityMap</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 ReferenceIdentityMap(int keyType, int valueType, boolean purgeValues) {
++ super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, purgeValues);
++ }
++
++ /**
++ * Constructs a new <code>ReferenceIdentityMap</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 ReferenceIdentityMap(int keyType, int valueType, int capacity, float loadFactor) {
++ super(keyType, valueType, capacity, loadFactor, false);
++ }
++
++ /**
++ * Constructs a new <code>ReferenceIdentityMap</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 ReferenceIdentityMap(int keyType, int valueType, int capacity, float loadFactor, boolean purgeValues) {
++ super(keyType, valueType, capacity, loadFactor, purgeValues);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the hash code for the key specified.
++ * <p/>
++ * This implementation uses the identity hash code.
++ *
++ * @param key the key to get a hash code for
++ * @return the hash code
++ */
++ protected int hash(Object key) {
++ return System.identityHashCode(key);
++ }
++
++ /**
++ * Gets the hash code for a MapEntry.
++ * <p/>
++ * This implementation uses the identity hash code.
++ *
++ * @param key the key to get a hash code for, may be null
++ * @param value the value to get a hash code for, may be null
++ * @return the hash code, as per the MapEntry specification
++ */
++ protected int hashEntry(Object key, Object value) {
++ return System.identityHashCode(key) ^ System.identityHashCode(value);
++ }
++
++ /**
++ * Compares two keys for equals.
++ * <p/>
++ * This implementation converts the key from the entry to a real reference
++ * before comparison and uses <code>==</code>.
++ *
++ * @param key1 the first key to compare passed in from outside
++ * @param key2 the second key extracted from the entry via <code>entry.key</code>
++ * @return true if equal by identity
++ */
++ protected boolean isEqualKey(Object key1, Object key2) {
++ // GenericsNote: I am disabled this line because of the new way that reference maps work, the getKey() method dereferences them for us.
++ //key2 = (keyType > HARD ? ((Reference) key2).get() : key2);
++ return (key1 == key2);
++ }
++
++ /**
++ * Compares two values for equals.
++ * <p/>
++ * This implementation uses <code>==</code>.
++ *
++ * @param value1 the first value to compare passed in from outside
++ * @param value2 the second value extracted from the entry via <code>getValue()</code>
++ * @return true if equal by identity
++ */
++ protected boolean isEqualValue(Object value1, Object value2) {
++ return (value1 == value2);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ doWriteObject(out);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ doReadObject(in);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/ReferenceMap.java
+@@ -0,0 +1,162 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++
++/**
++ * A <code>Map</code> 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 java.lang.ref.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/>
++ * This map is similar to
++ * {@link org.apache.commons.collections15.map.ReferenceIdentityMap ReferenceIdentityMap}.
++ * It differs in that keys and values in this class are compared using <code>equals()</code>.
++ * <p/>
++ * This {@link java.util.Map} implementation does <i>not</i> allow null elements.
++ * Attempting to add a null key or value to the map will raise a <code>NullPointerException</code>.
++ * <p/>
++ * This implementation is not synchronized.
++ * You can use {@link java.util.Collections#synchronizedMap} to
++ * provide synchronized access to a <code>ReferenceMap</code>.
++ * Remember that synchronization will not stop the garbage collecter removing entries.
++ * <p/>
++ * All the available iterators can be reset back to the start by casting to
++ * <code>ResettableIterator</code> and calling <code>reset()</code>.
++ * <p/>
++ * NOTE: As from Commons Collections 3.1 this map extends <code>AbstractReferenceMap</code>
++ * (previously it extended AbstractMap). As a result, the implementation is now
++ * extensible and provides a <code>MapIterator</code>.
++ *
++ * @author Paul Jack
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @see java.lang.ref.Reference
++ * @since Commons Collections 3.0 (previously in main package v2.1)
++ */
++public class ReferenceMap <K,V> extends AbstractReferenceMap<K, V> implements Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 1555089888138299607L;
++
++ /**
++ * Constructs a new <code>ReferenceMap</code> that will
++ * use hard references to keys and soft references to values.
++ */
++ public ReferenceMap() {
++ super(HARD, SOFT, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
++ }
++
++ /**
++ * 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) {
++ super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false);
++ }
++
++ /**
++ * 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) {
++ super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, 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(keyType, valueType, capacity, loadFactor, false);
++ }
++
++ /**
++ * 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) {
++ super(keyType, valueType, capacity, loadFactor, purgeValues);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ doWriteObject(out);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ doReadObject(in);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/SingletonMap.java
+@@ -0,0 +1,583 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.*;
++import org.apache.commons.collections15.iterators.SingletonIterator;
++import org.apache.commons.collections15.keyvalue.TiedMapEntry;
++
++import java.io.Serializable;
++import java.util.*;
++
++/**
++ * A <code>Map</code> implementation that holds a single item and is fixed size.
++ * <p/>
++ * The single key/value pair is specified at creation.
++ * The map is fixed size so any action that would change the size is disallowed.
++ * However, the <code>put</code> or <code>setValue</code> methods can <i>change</i>
++ * the value associated with the key.
++ * <p/>
++ * If trying to remove or clear the map, an UnsupportedOperationException is thrown.
++ * If trying to put a new mapping into the map, an IllegalArgumentException is thrown.
++ * The put method will only suceed if the key specified is the same as the
++ * singleton key.
++ * <p/>
++ * The key and value can be obtained by:
++ * <ul>
++ * <li>normal Map methods and views
++ * <li>the <code>MapIterator</code>, see {@link #mapIterator()}
++ * <li>the <code>KeyValue</code> interface (just cast - no object creation)
++ * </ul>
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.1
++ */
++public class SingletonMap <K,V> implements OrderedMap<K, V>, BoundedMap<K, V>, KeyValue<K, V>, Serializable, Cloneable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -8931271118676803261L;
++
++ /**
++ * Singleton key
++ */
++ private final K key;
++ /**
++ * Singleton value
++ */
++ private V value;
++
++ /**
++ * Constructor that creates a map of <code>null</code> to <code>null</code>.
++ */
++ public SingletonMap() {
++ super();
++ this.key = null;
++ }
++
++ /**
++ * Constructor specifying the key and value.
++ *
++ * @param key the key to use
++ * @param value the value to use
++ */
++ public SingletonMap(K key, V value) {
++ super();
++ this.key = key;
++ this.value = value;
++ }
++
++ /**
++ * Constructor specifying the key and value as a <code>KeyValue</code>.
++ *
++ * @param keyValue the key value pair to use
++ */
++ public SingletonMap(KeyValue<K, V> keyValue) {
++ super();
++ this.key = keyValue.getKey();
++ this.value = keyValue.getValue();
++ }
++
++ /**
++ * Constructor specifying the key and value as a <code>MapEntry</code>.
++ *
++ * @param entry the key value pair to use
++ */
++ public SingletonMap(Map.Entry<K, V> entry) {
++ super();
++ this.key = entry.getKey();
++ this.value = entry.getValue();
++ }
++
++ /**
++ * Constructor copying elements from another map.
++ *
++ * @param map the map to copy, must be size 1
++ * @throws NullPointerException if the map is null
++ * @throws IllegalArgumentException if the size is not 1
++ */
++ public SingletonMap(Map<? extends K, ? extends V> map) {
++ super();
++ if (map.size() != 1) {
++ throw new IllegalArgumentException("The map size must be 1");
++ }
++ Map.Entry<? extends K, ? extends V> entry = map.entrySet().iterator().next();
++ this.key = entry.getKey();
++ this.value = entry.getValue();
++ }
++
++ // KeyValue
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the key.
++ *
++ * @return the key
++ */
++ public K getKey() {
++ return key;
++ }
++
++ /**
++ * Gets the value.
++ *
++ * @return the value
++ */
++ public V getValue() {
++ return value;
++ }
++
++ /**
++ * Sets the value.
++ *
++ * @param value the new value to set
++ * @return the old value
++ */
++ public V setValue(V value) {
++ V old = this.value;
++ this.value = value;
++ return old;
++ }
++
++ // BoundedMap
++ //-----------------------------------------------------------------------
++ /**
++ * Is the map currently full, always true.
++ *
++ * @return true always
++ */
++ public boolean isFull() {
++ return true;
++ }
++
++ /**
++ * Gets the maximum size of the map, always 1.
++ *
++ * @return 1 always
++ */
++ public int maxSize() {
++ return 1;
++ }
++
++ // Map
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the value mapped to the key specified.
++ *
++ * @param key the key
++ * @return the mapped value, null if no match
++ */
++ public V get(Object key) {
++ if (isEqualKey(key)) {
++ return value;
++ }
++ return null;
++ }
++
++ /**
++ * Gets the size of the map, always 1.
++ *
++ * @return the size of 1
++ */
++ public int size() {
++ return 1;
++ }
++
++ /**
++ * Checks whether the map is currently empty, which it never is.
++ *
++ * @return false always
++ */
++ public boolean isEmpty() {
++ return false;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Checks whether the map contains the specified key.
++ *
++ * @param key the key to search for
++ * @return true if the map contains the key
++ */
++ public boolean containsKey(Object key) {
++ return (isEqualKey(key));
++ }
++
++ /**
++ * Checks whether the map contains the specified value.
++ *
++ * @param value the value to search for
++ * @return true if the map contains the key
++ */
++ public boolean containsValue(Object value) {
++ return (isEqualValue(value));
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Puts a key-value mapping into this map where the key must match the existing key.
++ * <p/>
++ * An IllegalArgumentException is thrown if the key does not match as the map
++ * is fixed size.
++ *
++ * @param key the key to set, must be the key of the map
++ * @param value the value to set
++ * @return the value previously mapped to this key, null if none
++ * @throws IllegalArgumentException if the key does not match
++ */
++ public V put(K key, V value) {
++ if (isEqualKey(key)) {
++ return setValue(value);
++ }
++ throw new IllegalArgumentException("Cannot put new key/value pair - Map is fixed size singleton");
++ }
++
++ /**
++ * Puts the values from the specified map into this map.
++ * <p/>
++ * The map must be of size 0 or size 1.
++ * If it is size 1, the key must match the key of this map otherwise an
++ * IllegalArgumentException is thrown.
++ *
++ * @param map the map to add, must be size 0 or 1, and the key must match
++ * @throws NullPointerException if the map is null
++ * @throws IllegalArgumentException if the key does not match
++ */
++ public void putAll(Map<? extends K, ? extends V> map) {
++ switch (map.size()) {
++ case 0:
++ return;
++
++ case 1:
++ Map.Entry<? extends K, ? extends V> entry = map.entrySet().iterator().next();
++ put(entry.getKey(), entry.getValue());
++ return;
++
++ default:
++ throw new IllegalArgumentException("The map size must be 0 or 1");
++ }
++ }
++
++ /**
++ * Unsupported operation.
++ *
++ * @param key the mapping to remove
++ * @return the value mapped to the removed key, null if key not in map
++ * @throws UnsupportedOperationException always
++ */
++ public V remove(Object key) {
++ throw new UnsupportedOperationException();
++ }
++
++ /**
++ * Unsupported operation.
++ */
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the entrySet view of the map.
++ * Changes made via <code>setValue</code> affect this map.
++ * To simply iterate through the entries, use {@link #mapIterator()}.
++ *
++ * @return the entrySet view
++ */
++ public Set<Map.Entry<K, V>> entrySet() {
++ Map.Entry<K, V> entry = new TiedMapEntry<K, V>(this, getKey());
++ return Collections.singleton(entry);
++ }
++
++ /**
++ * Gets the unmodifiable keySet view of the map.
++ * Changes made to the view affect this map.
++ * To simply iterate through the keys, use {@link #mapIterator()}.
++ *
++ * @return the keySet view
++ */
++ public Set<K> keySet() {
++ return Collections.singleton(key);
++ }
++
++ /**
++ * Gets the unmodifiable values view of the map.
++ * Changes made to the view affect this map.
++ * To simply iterate through the values, use {@link #mapIterator()}.
++ *
++ * @return the values view
++ */
++ public Collection<V> values() {
++ return new SingletonValues(this);
++ }
++
++ /**
++ * Gets an iterator over the map.
++ * Changes made to the iterator using <code>setValue</code> affect this map.
++ * The <code>remove</code> method is unsupported.
++ * <p/>
++ * A MapIterator returns the keys in the map. It also provides convenient
++ * methods to get the key and value, and set the value.
++ * It avoids the need to create an entrySet/keySet/values object.
++ * It also avoids creating the Map Entry object.
++ *
++ * @return the map iterator
++ */
++ public MapIterator<K, V> mapIterator() {
++ return new SingletonMapIterator<K, V>(this);
++ }
++
++ // OrderedMap
++ //-----------------------------------------------------------------------
++ /**
++ * Obtains an <code>OrderedMapIterator</code> over the map.
++ * <p/>
++ * A ordered map iterator is an efficient way of iterating over maps
++ * in both directions.
++ *
++ * @return an ordered map iterator
++ */
++ public OrderedMapIterator<K, V> orderedMapIterator() {
++ return new SingletonMapIterator<K, V>(this);
++ }
++
++ /**
++ * Gets the first (and only) key in the map.
++ *
++ * @return the key
++ */
++ public K firstKey() {
++ return getKey();
++ }
++
++ /**
++ * Gets the last (and only) key in the map.
++ *
++ * @return the key
++ */
++ public K lastKey() {
++ return getKey();
++ }
++
++ /**
++ * Gets the next key after the key specified, always null.
++ *
++ * @param key the next key
++ * @return null always
++ */
++ public K nextKey(K key) {
++ return null;
++ }
++
++ /**
++ * Gets the previous key before the key specified, always null.
++ *
++ * @param key the next key
++ * @return null always
++ */
++ public K previousKey(K key) {
++ return null;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Compares the specified key to the stored key.
++ *
++ * @param key the key to compare
++ * @return true if equal
++ */
++ protected boolean isEqualKey(Object key) {
++ return (key == null ? getKey() == null : key.equals(getKey()));
++ }
++
++ /**
++ * Compares the specified value to the stored value.
++ *
++ * @param value the value to compare
++ * @return true if equal
++ */
++ protected boolean isEqualValue(Object value) {
++ return (value == null ? getValue() == null : value.equals(getValue()));
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * SingletonMapIterator.
++ */
++ static class SingletonMapIterator <K,V> implements OrderedMapIterator<K, V>, ResettableIterator<K> {
++ private final SingletonMap<K, V> parent;
++ private boolean hasNext = true;
++ private boolean canGetSet = false;
++
++ SingletonMapIterator(SingletonMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ }
++
++ public boolean hasNext() {
++ return hasNext;
++ }
++
++ public K next() {
++ if (hasNext == false) {
++ throw new NoSuchElementException(AbstractHashedMap.NO_NEXT_ENTRY);
++ }
++ hasNext = false;
++ canGetSet = true;
++ return parent.getKey();
++ }
++
++ public boolean hasPrevious() {
++ return (hasNext == false);
++ }
++
++ public K previous() {
++ if (hasNext == true) {
++ throw new NoSuchElementException(AbstractHashedMap.NO_PREVIOUS_ENTRY);
++ }
++ hasNext = true;
++ return parent.getKey();
++ }
++
++ public void remove() {
++ throw new UnsupportedOperationException();
++ }
++
++ public K getKey() {
++ if (canGetSet == false) {
++ throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID);
++ }
++ return parent.getKey();
++ }
++
++ public V getValue() {
++ if (canGetSet == false) {
++ throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID);
++ }
++ return parent.getValue();
++ }
++
++ public V setValue(V value) {
++ if (canGetSet == false) {
++ throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID);
++ }
++ return parent.setValue(value);
++ }
++
++ public void reset() {
++ hasNext = true;
++ }
++
++ public String toString() {
++ if (hasNext) {
++ return "Iterator[]";
++ } else {
++ return "Iterator[" + getKey() + "=" + getValue() + "]";
++ }
++ }
++ }
++
++ /**
++ * Values implementation for the SingletonMap.
++ * This class is needed as values is a view that must update as the map updates.
++ */
++ static class SingletonValues <K,V> extends AbstractSet<V> implements Serializable {
++ private static final long serialVersionUID = -3689524741863047872L;
++ private final SingletonMap<K, V> parent;
++
++ SingletonValues(SingletonMap<K, V> parent) {
++ super();
++ this.parent = parent;
++ }
++
++ public int size() {
++ return 1;
++ }
++
++ public boolean isEmpty() {
++ return false;
++ }
++
++ public boolean contains(Object object) {
++ return parent.containsValue(object);
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public Iterator<V> iterator() {
++ return new SingletonIterator<V>(parent.getValue(), false);
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Clones the map without cloning the key or value.
++ *
++ * @return a shallow clone
++ */
++ public Object clone() {
++ try {
++ SingletonMap cloned = (SingletonMap) super.clone();
++ return cloned;
++ } catch (CloneNotSupportedException ex) {
++ throw new InternalError();
++ }
++ }
++
++ /**
++ * Compares this map with another.
++ *
++ * @param obj the object to compare to
++ * @return true if equal
++ */
++ public boolean equals(Object obj) {
++ if (obj == this) {
++ return true;
++ }
++ if (obj instanceof Map == false) {
++ return false;
++ }
++ Map other = (Map) obj;
++ if (other.size() != 1) {
++ return false;
++ }
++ Map.Entry entry = (Map.Entry) other.entrySet().iterator().next();
++ return isEqualKey(entry.getKey()) && isEqualValue(entry.getValue());
++ }
++
++ /**
++ * Gets the standard Map hashCode.
++ *
++ * @return the hash code defined in the Map interface
++ */
++ public int hashCode() {
++ return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode());
++ }
++
++ /**
++ * Gets the map as a String.
++ *
++ * @return a string version of the map
++ */
++ public String toString() {
++ return new StringBuffer(128).append('{').append(getKey()).append('=').append(getValue()).append('}').toString();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/StaticBucketMap.java
+@@ -0,0 +1,702 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2002-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.KeyValue;
++
++import java.util.*;
++
++/**
++ * 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>
++ * <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
++ * <p/>
++ * <pre>
++ * staticBucketMapInstance.putAll(map);
++ * </pre>
++ * <p/>
++ * and
++ * <p/>
++ * <pre>
++ * staticBucketMapInstance.entrySet().removeAll(map.entrySet());
++ * </pre>
++ * <p/>
++ * 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>
++ * <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>
++ * <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>
++ * <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>
++ * <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}.
++ * <p/>
++ * 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>
++ *
++ * @author Berin Loritsch
++ * @author Gerhard Froehlich
++ * @author Michael A. Smith
++ * @author Paul Jack
++ * @author Leo Sutic
++ * @author Matt Hall, John Watkinson, Janek Bogucki
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0 (previously in main package v2.1)
++ */
++public final class StaticBucketMap <K,V> implements Map<K, V> {
++
++ /**
++ * The default number of buckets to use
++ */
++ private static final int DEFAULT_BUCKETS = 255;
++ /**
++ * The array of buckets, where the actual data is held
++ */
++ private Node<K, V>[] buckets;
++ /**
++ * The matching array of locks
++ */
++ private Lock[] 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--;
++ }
++
++ buckets = new Node[size];
++ locks = new Lock[size];
++
++ for (int i = 0; i < size; i++) {
++ locks[i] = new Lock();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Determine the exact hash entry for the key. The hash algorithm
++ * is rather simplistic, but it does the job:
++ * <p/>
++ * <pre>
++ * He = |Hk mod n|
++ * </pre>
++ * <p/>
++ * <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 %= buckets.length;
++ return (hash < 0) ? hash * -1 : hash;
++ }
++
++ /**
++ * Gets the current size of the map.
++ * The value is computed fresh each time the method is called.
++ *
++ * @return the current size
++ */
++ public int size() {
++ int cnt = 0;
++
++ for (int i = 0; i < buckets.length; i++) {
++ cnt += locks[i].size;
++ }
++ return cnt;
++ }
++
++ /**
++ * Checks if the size is currently zero.
++ *
++ * @return true if empty
++ */
++ public boolean isEmpty() {
++ return (size() == 0);
++ }
++
++ /**
++ * Gets the value associated with the key.
++ *
++ * @param key the key to retrieve
++ * @return the associated value
++ */
++ public V get(final Object key) {
++ int hash = getHash(key);
++
++ synchronized (locks[hash]) {
++ Node<K, V> n = buckets[hash];
++
++ while (n != null) {
++ if (n.key == key || (n.key != null && n.key.equals(key))) {
++ return n.value;
++ }
++
++ n = n.next;
++ }
++ }
++ return null;
++ }
++
++ /**
++ * Checks if the map contains the specified key.
++ *
++ * @param key the key to check
++ * @return true if found
++ */
++ public boolean containsKey(final Object key) {
++ int hash = getHash(key);
++
++ synchronized (locks[hash]) {
++ Node n = buckets[hash];
++
++ while (n != null) {
++ if (n.key == null || (n.key != null && n.key.equals(key))) {
++ return true;
++ }
++
++ n = n.next;
++ }
++ }
++ return false;
++ }
++
++ /**
++ * Checks if the map contains the specified value.
++ *
++ * @param value the value to check
++ * @return true if found
++ */
++ public boolean containsValue(final Object value) {
++ for (int i = 0; i < buckets.length; i++) {
++ synchronized (locks[i]) {
++ Node n = buckets[i];
++
++ while (n != null) {
++ if (n.value == value || (n.value != null && n.value.equals(value))) {
++ return true;
++ }
++
++ n = n.next;
++ }
++ }
++ }
++ return false;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Puts a new key value mapping into the map.
++ *
++ * @param key the key to use
++ * @param value the value to use
++ * @return the previous mapping for the key
++ */
++ public V put(final K key, final V value) {
++ int hash = getHash(key);
++
++ synchronized (locks[hash]) {
++ Node<K, V> n = buckets[hash];
++
++ if (n == null) {
++ n = new Node<K, V>();
++ n.key = key;
++ n.value = value;
++ buckets[hash] = n;
++ 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<K, V> next = n; next != null; next = next.next) {
++ n = next;
++
++ if (n.key == key || (n.key != null && n.key.equals(key))) {
++ V 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<K, V> newNode = new Node<K, V>();
++ newNode.key = key;
++ newNode.value = value;
++ n.next = newNode;
++ locks[hash].size++;
++ }
++ return null;
++ }
++
++ /**
++ * Removes the specified key from the map.
++ *
++ * @param key the key to remove
++ * @return the previous value at this key
++ */
++ public V remove(Object key) {
++ int hash = getHash(key);
++
++ synchronized (locks[hash]) {
++ Node<K, V> n = buckets[hash];
++ Node<K, V> 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.
++ buckets[hash] = n.next;
++ } else {
++ // Set the next node of the previous node to be the node after this one.
++ prev.next = n.next;
++ }
++ locks[hash].size--;
++ return n.value;
++ }
++
++ prev = n;
++ n = n.next;
++ }
++ }
++ return null;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the key set.
++ *
++ * @return the key set
++ */
++ public Set<K> keySet() {
++ return new KeySet();
++ }
++
++ /**
++ * Gets the values.
++ *
++ * @return the values
++ */
++ public Collection<V> values() {
++ return new Values();
++ }
++
++ /**
++ * Gets the entry set.
++ *
++ * @return the entry set
++ */
++ public Set<Map.Entry<K, V>> entrySet() {
++ return new EntrySet();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Puts all the entries from the specified map into this map.
++ * This operation is <b>not atomic</b> and may have undesired effects.
++ *
++ * @param map the map of entries to add
++ */
++ public void putAll(Map<? extends K, ? extends V> map) {
++ Iterator i = map.keySet().iterator();
++
++ while (i.hasNext()) {
++ K key = (K) i.next();
++ put(key, (V) map.get(key));
++ }
++ }
++
++ /**
++ * Clears the map of all entries.
++ */
++ public void clear() {
++ for (int i = 0; i < buckets.length; i++) {
++ Lock lock = locks[i];
++ synchronized (lock) {
++ buckets[i] = null;
++ lock.size = 0;
++ }
++ }
++ }
++
++ /**
++ * Compares this map to another, as per the Map specification.
++ *
++ * @param obj the object to compare to
++ * @return true if equal
++ */
++ public boolean equals(Object obj) {
++ if (obj == this) {
++ return true;
++ }
++ if (obj instanceof Map == false) {
++ return false;
++ }
++ Map other = (Map) obj;
++ return entrySet().equals(other.entrySet());
++ }
++
++ /**
++ * Gets the hash code, as per the Map specification.
++ *
++ * @return the hash code
++ */
++ public int hashCode() {
++ int hashCode = 0;
++
++ for (int i = 0; i < buckets.length; i++) {
++ synchronized (locks[i]) {
++ Node n = buckets[i];
++
++ while (n != null) {
++ hashCode += n.hashCode();
++ n = n.next;
++ }
++ }
++ }
++ return hashCode;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * The Map.Entry for the StaticBucketMap.
++ */
++ private static final class Node <K,V> implements Map.Entry<K, V>, KeyValue<K, V> {
++ protected K key;
++ protected V value;
++ protected Node<K, V> next;
++
++ public K getKey() {
++ return key;
++ }
++
++ public V getValue() {
++ return value;
++ }
++
++ public int hashCode() {
++ return ((key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()));
++ }
++
++ public boolean equals(Object obj) {
++ if (obj == this) {
++ return true;
++ }
++ if (obj instanceof Map.Entry == false) {
++ return false;
++ }
++
++ Map.Entry e2 = (Map.Entry) obj;
++ return ((key == null ? e2.getKey() == null : key.equals(e2.getKey())) && (value == null ? e2.getValue() == null : value.equals(e2.getValue())));
++ }
++
++ public V setValue(V obj) {
++ V retVal = value;
++ value = obj;
++ return retVal;
++ }
++ }
++
++
++ /**
++ * The lock object, which also includes a count of the nodes in this lock.
++ */
++ private final static class Lock {
++ public int size;
++ }
++
++ private class EntryIterator extends IteratorBase implements Iterator<Map.Entry<K, V>> {
++
++ public Entry<K, V> next() {
++ return superNext();
++ }
++
++ }
++
++ //-----------------------------------------------------------------------
++ private class IteratorBase {
++
++ private ArrayList<Map.Entry<K, V>> current = new ArrayList<Map.Entry<K, V>>();
++ private int bucket;
++ private Map.Entry<K, V> last;
++
++
++ public boolean hasNext() {
++ if (current.size() > 0) return true;
++ while (bucket < buckets.length) {
++ synchronized (locks[bucket]) {
++ Node<K, V> n = buckets[bucket];
++ while (n != null) {
++ current.add(n);
++ n = n.next;
++ }
++ bucket++;
++ if (current.size() > 0) return true;
++ }
++ }
++ return false;
++ }
++
++ protected Map.Entry<K, V> nextEntry() {
++ if (!hasNext()) throw new NoSuchElementException();
++ last = current.remove(current.size() - 1);
++ return last;
++ }
++
++ public Map.Entry<K, V> superNext() {
++ return nextEntry();
++ }
++
++ public void remove() {
++ if (last == null) throw new IllegalStateException();
++ StaticBucketMap.this.remove(last.getKey());
++ last = null;
++ }
++
++ }
++
++ private class ValueIterator extends IteratorBase implements Iterator<V> {
++
++ public V next() {
++ return nextEntry().getValue();
++ }
++
++ }
++
++ private class KeyIterator extends IteratorBase implements Iterator<K> {
++
++ public K next() {
++ return nextEntry().getKey();
++ }
++
++ }
++
++ private class EntrySet extends AbstractSet<Map.Entry<K, V>> {
++
++ public int size() {
++ return StaticBucketMap.this.size();
++ }
++
++ public void clear() {
++ StaticBucketMap.this.clear();
++ }
++
++ public Iterator<Map.Entry<K, V>> iterator() {
++ return new EntryIterator();
++ }
++
++ public boolean contains(Object obj) {
++ Map.Entry entry = (Map.Entry) obj;
++ int hash = getHash(entry.getKey());
++ synchronized (locks[hash]) {
++ for (Node n = 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 (locks[hash]) {
++ for (Node n = 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<K> {
++
++ public int size() {
++ return StaticBucketMap.this.size();
++ }
++
++ public void clear() {
++ StaticBucketMap.this.clear();
++ }
++
++ public Iterator<K> iterator() {
++ return new KeyIterator();
++ }
++
++ public boolean contains(Object obj) {
++ return StaticBucketMap.this.containsKey(obj);
++ }
++
++ public boolean remove(Object obj) {
++ int hash = getHash(obj);
++ synchronized (locks[hash]) {
++ for (Node n = buckets[hash]; n != null; n = n.next) {
++ Object k = n.getKey();
++ if ((k == obj) || ((k != null) && k.equals(obj))) {
++ StaticBucketMap.this.remove(k);
++ return true;
++ }
++ }
++ }
++ return false;
++
++ }
++
++ }
++
++
++ private class Values extends AbstractCollection<V> {
++
++ public int size() {
++ return StaticBucketMap.this.size();
++ }
++
++ public void clear() {
++ StaticBucketMap.this.clear();
++ }
++
++ public Iterator<V> 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:
++ * <p/>
++ * <pre>
++ * staticBucketMapInstance.atomic(new Runnable() {
++ * public void run() {
++ * staticBucketMapInstance.putAll(map);
++ * }
++ * });
++ * </pre>
++ * <p/>
++ * It can also be used if you need a reliable iterator:
++ * <p/>
++ * <pre>
++ * staticBucketMapInstance.atomic(new Runnable() {
++ * public void run() {
++ * Iterator iterator = staticBucketMapInstance.iterator();
++ * while (iterator.hasNext()) {
++ * foo(iterator.next();
++ * }
++ * }
++ * });
++ * </pre>
++ * <p/>
++ * <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 >= buckets.length) {
++ r.run();
++ return;
++ }
++ synchronized (locks[bucket]) {
++ atomic(r, bucket + 1);
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/TransformedMap.java
+@@ -0,0 +1,200 @@
++// TODO: Not yet converted, deprecated (by me).
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.Transformer;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Iterator;
++import java.util.Map;
++
++/**
++ * Decorates another <code>Map</code> to transform objects that are added.
++ * <p/>
++ * The Map put methods and Map.Entry setValue method are affected by this class.
++ * Thus objects must be removed or searched for using their transformed form.
++ * For example, if the transformation converts Strings to Integers, you must
++ * use the Integer form to remove objects.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ * <p>
++ * Note: This class cannot support generics without breaking the Map contract.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class TransformedMap extends AbstractInputCheckedMapDecorator implements Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 7023152376788900464L;
++
++ /**
++ * The transformer to use for the key
++ */
++ protected final Transformer keyTransformer;
++ /**
++ * The transformer to use for the value
++ */
++ protected final Transformer valueTransformer;
++
++ /**
++ * Factory method to create a transforming map.
++ * <p/>
++ * If there are any elements already in the map being decorated, they
++ * are NOT transformed.
++ *
++ * @param map the map to decorate, must not be null
++ * @param keyTransformer the transformer to use for key conversion, null means no conversion
++ * @param valueTransformer the transformer to use for value conversion, null means no conversion
++ * @throws IllegalArgumentException if map is null
++ */
++ public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) {
++ return new TransformedMap(map, keyTransformer, valueTransformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the collection being decorated, they
++ * are NOT transformed.
++ *
++ * @param map the map to decorate, must not be null
++ * @param keyTransformer the transformer to use for key conversion, null means no conversion
++ * @param valueTransformer the transformer to use for value conversion, null means no conversion
++ * @throws IllegalArgumentException if map is null
++ */
++ protected TransformedMap(Map map, Transformer keyTransformer, Transformer valueTransformer) {
++ super(map);
++ this.keyTransformer = keyTransformer;
++ this.valueTransformer = valueTransformer;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ * @since Commons Collections 3.1
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(map);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ * @since Commons Collections 3.1
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ map = (Map) in.readObject();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Transforms a key.
++ * <p/>
++ * The transformer itself may throw an exception if necessary.
++ *
++ * @param object the object to transform
++ * @throws the transformed object
++ */
++ protected Object transformKey(Object object) {
++ if (keyTransformer == null) {
++ return object;
++ }
++ return keyTransformer.transform(object);
++ }
++
++ /**
++ * Transforms a value.
++ * <p/>
++ * The transformer itself may throw an exception if necessary.
++ *
++ * @param object the object to transform
++ * @throws the transformed object
++ */
++ protected Object transformValue(Object object) {
++ if (valueTransformer == null) {
++ return object;
++ }
++ return valueTransformer.transform(object);
++ }
++
++ /**
++ * Transforms a map.
++ * <p/>
++ * The transformer itself may throw an exception if necessary.
++ *
++ * @param map the map to transform
++ * @throws the transformed object
++ */
++ protected Map transformMap(Map map) {
++ Map result = new LinkedMap(map.size());
++ for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
++ Map.Entry entry = (Map.Entry) it.next();
++ result.put(transformKey(entry.getKey()), transformValue(entry.getValue()));
++ }
++ return result;
++ }
++
++ /**
++ * Override to transform the value when using <code>setValue</code>.
++ *
++ * @param value the value to transform
++ * @return the transformed value
++ * @since Commons Collections 3.1
++ */
++ protected Object checkSetValue(Object value) {
++ return valueTransformer.transform(value);
++ }
++
++ /**
++ * Override to only return true when there is a value transformer.
++ *
++ * @return true if a value transformer is in use
++ * @since Commons Collections 3.1
++ */
++ protected boolean isSetValueChecking() {
++ return (valueTransformer != null);
++ }
++
++ //-----------------------------------------------------------------------
++ public Object put(Object key, Object value) {
++ key = transformKey(key);
++ value = transformValue(value);
++ return getMap().put(key, value);
++ }
++
++ public void putAll(Map mapToCopy) {
++ mapToCopy = transformMap(mapToCopy);
++ getMap().putAll(mapToCopy);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/TransformedSortedMap.java
+@@ -0,0 +1,116 @@
++// TODO: Not yet converted, deprecated (by me).
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.Transformer;
++
++import java.util.Comparator;
++import java.util.SortedMap;
++
++/**
++ * Decorates another <code>SortedMap </code> to transform objects that are added.
++ * <p/>
++ * The Map put methods and Map.Entry setValue method are affected by this class.
++ * Thus objects must be removed or searched for using their transformed form.
++ * For example, if the transformation converts Strings to Integers, you must
++ * use the Integer form to remove objects.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ * <p>
++ * Note: This class cannot support generics without breaking the Map contract.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public class TransformedSortedMap extends TransformedMap implements SortedMap {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -8751771676410385778L;
++
++ /**
++ * Factory method to create a transforming sorted map.
++ * <p/>
++ * If there are any elements already in the map being decorated, they
++ * are NOT transformed.
++ *
++ * @param map the map to decorate, must not be null
++ * @param keyTransformer the predicate to validate the keys, null means no transformation
++ * @param valueTransformer the predicate to validate to values, null means no transformation
++ * @throws IllegalArgumentException if the map is null
++ */
++ public static SortedMap decorate(SortedMap map, Transformer keyTransformer, Transformer valueTransformer) {
++ return new TransformedSortedMap(map, keyTransformer, valueTransformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the collection being decorated, they
++ * are NOT transformed.</p>
++ *
++ * @param map the map to decorate, must not be null
++ * @param keyTransformer the predicate to validate the keys, null means no transformation
++ * @param valueTransformer the predicate to validate to values, null means no transformation
++ * @throws IllegalArgumentException if the map is null
++ */
++ protected TransformedSortedMap(SortedMap map, Transformer keyTransformer, Transformer valueTransformer) {
++ super(map, keyTransformer, valueTransformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets the map being decorated.
++ *
++ * @return the decorated map
++ */
++ protected SortedMap getSortedMap() {
++ return (SortedMap) map;
++ }
++
++ //-----------------------------------------------------------------------
++ public Object firstKey() {
++ return getSortedMap().firstKey();
++ }
++
++ public Object lastKey() {
++ return getSortedMap().lastKey();
++ }
++
++ public Comparator comparator() {
++ return getSortedMap().comparator();
++ }
++
++ public SortedMap subMap(Object fromKey, Object toKey) {
++ SortedMap map = getSortedMap().subMap(fromKey, toKey);
++ return new TransformedSortedMap(map, keyTransformer, valueTransformer);
++ }
++
++ public SortedMap headMap(Object toKey) {
++ SortedMap map = getSortedMap().headMap(toKey);
++ return new TransformedSortedMap(map, keyTransformer, valueTransformer);
++ }
++
++ public SortedMap tailMap(Object fromKey) {
++ SortedMap map = getSortedMap().tailMap(fromKey);
++ return new TransformedSortedMap(map, keyTransformer, valueTransformer);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/TypedMap.java
+@@ -0,0 +1,63 @@
++// TODO: Not yet converted, deprecated (by me).
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.functors.InstanceofPredicate;
++
++import java.util.Map;
++
++/**
++ * Decorates another <code>Map</code> to validate that elements added
++ * are of a specific type.
++ * <p/>
++ * The validation of additions is performed via an instanceof test against
++ * a specified <code>Class</code>. If an object cannot be added to the
++ * collection, an IllegalArgumentException is thrown.
++ * <p/>
++ * The returned implementation is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Matthew Hawthorne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ * @deprecated no longer needed with Java generics.
++ */
++public class TypedMap {
++
++ /**
++ * Factory method to create a typed map.
++ * <p/>
++ * If there are any elements already in the map being decorated, they
++ * are validated.
++ *
++ * @param map the map to decorate, must not be null
++ * @param keyType the type to allow as keys, must not be null
++ * @param valueType the type to allow as values, must not be null
++ * @throws IllegalArgumentException if list or type is null
++ * @throws IllegalArgumentException if the list contains invalid elements
++ */
++ public static Map decorate(Map map, Class keyType, Class valueType) {
++ return new PredicatedMap(map, InstanceofPredicate.getInstance(keyType), InstanceofPredicate.getInstance(valueType));
++ }
++
++ /**
++ * Restrictive constructor.
++ */
++ protected TypedMap() {
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/TypedSortedMap.java
+@@ -0,0 +1,63 @@
++// TODO: Not yet converted, deprecated (by me).
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.functors.InstanceofPredicate;
++
++import java.util.SortedMap;
++
++/**
++ * Decorates another <code>SortedMap</code> to validate that elements added
++ * are of a specific type.
++ * <p/>
++ * The validation of additions is performed via an instanceof test against
++ * a specified <code>Class</code>. If an object cannot be added to the
++ * collection, an IllegalArgumentException is thrown.
++ * <p/>
++ * The returned implementation is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Matthew Hawthorne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ * @deprecated no longer needed with Java generics.
++ */
++public class TypedSortedMap {
++
++ /**
++ * Factory method to create a typed sorted map.
++ * <p/>
++ * If there are any elements already in the map being decorated, they
++ * are validated.
++ *
++ * @param map the map to decorate, must not be null
++ * @param keyType the type to allow as keys, must not be null
++ * @param valueType the type to allow as values, must not be null
++ * @throws IllegalArgumentException if list or type is null
++ * @throws IllegalArgumentException if the list contains invalid elements
++ */
++ public static SortedMap decorate(SortedMap map, Class keyType, Class valueType) {
++ return new PredicatedSortedMap(map, InstanceofPredicate.getInstance(keyType), InstanceofPredicate.getInstance(valueType));
++ }
++
++ /**
++ * Restrictive constructor.
++ */
++ protected TypedSortedMap() {
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/UnmodifiableEntrySet.java
+@@ -0,0 +1,161 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.Unmodifiable;
++import org.apache.commons.collections15.iterators.AbstractIteratorDecorator;
++import org.apache.commons.collections15.keyvalue.AbstractMapEntryDecorator;
++import org.apache.commons.collections15.set.AbstractSetDecorator;
++
++import java.lang.reflect.Array;
++import java.util.*;
++
++/**
++ * Decorates a map entry <code>Set</code> to ensure it can't be altered.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableEntrySet <K,V> extends AbstractSetDecorator<Map.Entry<K, V>> implements Unmodifiable {
++
++ /**
++ * Factory method to create an unmodifiable set of Map Entry objects.
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ public static <K,V> Set<Map.Entry<K, V>> decorate(Set<Map.Entry<K, V>> set) {
++ if (set instanceof Unmodifiable) {
++ return set;
++ }
++ return new UnmodifiableEntrySet<K, V>(set);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ private UnmodifiableEntrySet(Set<Map.Entry<K, V>> set) {
++ super(set);
++ }
++
++ //-----------------------------------------------------------------------
++ public boolean add(Map.Entry<K, V> object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean addAll(Collection<? extends Map.Entry<K, V>> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean remove(Object object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ //-----------------------------------------------------------------------
++ public Iterator<Map.Entry<K, V>> iterator() {
++ return new UnmodifiableEntrySetIterator<K, V>(collection.iterator());
++ }
++
++ public Object[] toArray() {
++ Object[] array = collection.toArray();
++ for (int i = 0; i < array.length; i++) {
++ array[i] = new UnmodifiableEntry((Map.Entry) array[i]);
++ }
++ return array;
++ }
++
++ public <T> T[] toArray(T array[]) {
++ T[] result = array;
++ if (array.length > 0) {
++ // we must create a new array to handle multi-threaded situations
++ // where another thread could access data before we decorate it
++ result = (T[]) Array.newInstance(array.getClass().getComponentType(), 0);
++ }
++ result = collection.toArray(result);
++ Collection<UnmodifiableEntry<K, V>> newCollection = new ArrayList<UnmodifiableEntry<K, V>>();
++ for (int i = 0; i < result.length; i++) {
++ // result[i] = new UnmodifiableEntry<K,V>((Map.Entry) result[i]);
++ newCollection.add(new UnmodifiableEntry<K, V>((Map.Entry) result[i]));
++ }
++ result = newCollection.toArray(result);
++
++ // check to see if result should be returned straight
++ if (result.length > array.length) {
++ return result;
++ }
++
++ // copy back into input array to fulfil the method contract
++ System.arraycopy(result, 0, array, 0, result.length);
++ if (array.length > result.length) {
++ array[result.length] = null;
++ }
++ return array;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Implementation of an entry set iterator.
++ */
++ final static class UnmodifiableEntrySetIterator <K,V> extends AbstractIteratorDecorator<Map.Entry<K, V>> {
++
++ protected UnmodifiableEntrySetIterator(Iterator<Map.Entry<K, V>> iterator) {
++ super(iterator);
++ }
++
++ public Map.Entry<K, V> next() {
++ Map.Entry entry = (Map.Entry) iterator.next();
++ return new UnmodifiableEntry<K, V>(entry);
++ }
++
++ public void remove() {
++ throw new UnsupportedOperationException();
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Implementation of a map entry that is unmodifiable.
++ */
++ final static class UnmodifiableEntry <K,V> extends AbstractMapEntryDecorator<K, V> {
++
++ protected UnmodifiableEntry(Map.Entry<K, V> entry) {
++ super(entry);
++ }
++
++ public V setValue(V obj) {
++ throw new UnsupportedOperationException();
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/UnmodifiableMap.java
+@@ -0,0 +1,143 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.IterableMap;
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.Unmodifiable;
++import org.apache.commons.collections15.collection.UnmodifiableCollection;
++import org.apache.commons.collections15.iterators.EntrySetMapIterator;
++import org.apache.commons.collections15.iterators.UnmodifiableMapIterator;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * Decorates another <code>Map</code> to ensure it can't be altered.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableMap <K,V> extends AbstractMapDecorator<K, V> implements IterableMap<K, V>, Unmodifiable, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 2737023427269031941L;
++
++ /**
++ * Factory method to create an unmodifiable map.
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ public static <K,V> Map<K, V> decorate(Map<K, V> map) {
++ if (map instanceof Unmodifiable) {
++ return map;
++ }
++ return new UnmodifiableMap<K, V>(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ private UnmodifiableMap(Map<K, V> map) {
++ super(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ * @since Commons Collections 3.1
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(map);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ * @since Commons Collections 3.1
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ map = (Map) in.readObject();
++ }
++
++ //-----------------------------------------------------------------------
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public V put(K key, V value) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void putAll(Map<? extends K, ? extends V> mapToCopy) {
++ throw new UnsupportedOperationException();
++ }
++
++ public V remove(Object key) {
++ throw new UnsupportedOperationException();
++ }
++
++ public MapIterator<K, V> mapIterator() {
++ if (map instanceof IterableMap) {
++ MapIterator<K, V> it = ((IterableMap<K, V>) map).mapIterator();
++ return UnmodifiableMapIterator.decorate(it);
++ } else {
++ MapIterator<K, V> it = new EntrySetMapIterator<K, V>(map);
++ return UnmodifiableMapIterator.decorate(it);
++ }
++ }
++
++ public Set<Map.Entry<K, V>> entrySet() {
++ Set<Map.Entry<K, V>> set = super.entrySet();
++ return UnmodifiableEntrySet.decorate(set);
++ }
++
++ public Set<K> keySet() {
++ Set<K> set = super.keySet();
++ return UnmodifiableSet.decorate(set);
++ }
++
++ public Collection<V> values() {
++ Collection<V> coll = super.values();
++ return UnmodifiableCollection.decorate(coll);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/UnmodifiableOrderedMap.java
+@@ -0,0 +1,144 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.MapIterator;
++import org.apache.commons.collections15.OrderedMap;
++import org.apache.commons.collections15.OrderedMapIterator;
++import org.apache.commons.collections15.Unmodifiable;
++import org.apache.commons.collections15.collection.UnmodifiableCollection;
++import org.apache.commons.collections15.iterators.UnmodifiableMapIterator;
++import org.apache.commons.collections15.iterators.UnmodifiableOrderedMapIterator;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * Decorates another <code>OrderedMap</code> to ensure it can't be altered.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableOrderedMap <K,V> extends AbstractOrderedMapDecorator<K, V> implements Unmodifiable, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 8136428161720526266L;
++
++ /**
++ * Factory method to create an unmodifiable sorted map.
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ public static <K,V> OrderedMap<K, V> decorate(OrderedMap<K, V> map) {
++ if (map instanceof Unmodifiable) {
++ return map;
++ }
++ return new UnmodifiableOrderedMap<K, V>(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ private UnmodifiableOrderedMap(OrderedMap<K, V> map) {
++ super(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ * @since Commons Collections 3.1
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(map);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ * @since Commons Collections 3.1
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ map = (Map<K, V>) in.readObject();
++ }
++
++ //-----------------------------------------------------------------------
++ public MapIterator<K, V> mapIterator() {
++ MapIterator<K, V> it = getOrderedMap().mapIterator();
++ return UnmodifiableMapIterator.decorate(it);
++ }
++
++ public OrderedMapIterator<K, V> orderedMapIterator() {
++ OrderedMapIterator<K, V> it = getOrderedMap().orderedMapIterator();
++ return UnmodifiableOrderedMapIterator.decorate(it);
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public V put(K key, V value) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void putAll(Map<? extends K, ? extends V> mapToCopy) {
++ throw new UnsupportedOperationException();
++ }
++
++ public V remove(Object key) {
++ throw new UnsupportedOperationException();
++ }
++
++ public Set<Map.Entry<K, V>> entrySet() {
++ Set<Map.Entry<K, V>> set = super.entrySet();
++ return UnmodifiableEntrySet.decorate(set);
++ }
++
++ public Set<K> keySet() {
++ Set<K> set = super.keySet();
++ return UnmodifiableSet.decorate(set);
++ }
++
++ public Collection<V> values() {
++ Collection<V> coll = super.values();
++ return UnmodifiableCollection.decorate(coll);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/UnmodifiableSortedMap.java
+@@ -0,0 +1,155 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.map;
++
++import org.apache.commons.collections15.Unmodifiable;
++import org.apache.commons.collections15.collection.UnmodifiableCollection;
++import org.apache.commons.collections15.set.UnmodifiableSet;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.*;
++
++/**
++ * Decorates another <code>SortedMap</code> to ensure it can't be altered.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableSortedMap <K,V> extends AbstractSortedMapDecorator<K, V> implements Unmodifiable, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 5805344239827376360L;
++
++ /**
++ * Factory method to create an unmodifiable sorted map.
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ public static <K,V> SortedMap<K, V> decorate(SortedMap<K, V> map) {
++ if (map instanceof Unmodifiable) {
++ return map;
++ }
++ return new UnmodifiableSortedMap<K, V>(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if map is null
++ */
++ private UnmodifiableSortedMap(SortedMap<K, V> map) {
++ super(map);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the map out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ * @since Commons Collections 3.1
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(map);
++ }
++
++ /**
++ * Read the map in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ * @since Commons Collections 3.1
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ map = (Map<K, V>) in.readObject();
++ }
++
++ //-----------------------------------------------------------------------
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public V put(K key, V value) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void putAll(Map<? extends K, ? extends V> mapToCopy) {
++ throw new UnsupportedOperationException();
++ }
++
++ public V remove(Object key) {
++ throw new UnsupportedOperationException();
++ }
++
++ public Set<Map.Entry<K, V>> entrySet() {
++ Set<Map.Entry<K, V>> set = super.entrySet();
++ return UnmodifiableEntrySet.decorate(set);
++ }
++
++ public Set<K> keySet() {
++ Set<K> set = super.keySet();
++ return UnmodifiableSet.decorate(set);
++ }
++
++ public Collection<V> values() {
++ Collection<V> coll = super.values();
++ return UnmodifiableCollection.decorate(coll);
++ }
++
++ //-----------------------------------------------------------------------
++ public K firstKey() {
++ return getSortedMap().firstKey();
++ }
++
++ public K lastKey() {
++ return getSortedMap().lastKey();
++ }
++
++ public Comparator<? super K> comparator() {
++ return getSortedMap().comparator();
++ }
++
++ public SortedMap<K, V> subMap(K fromKey, K toKey) {
++ SortedMap<K, V> map = getSortedMap().subMap(fromKey, toKey);
++ return new UnmodifiableSortedMap<K, V>(map);
++ }
++
++ public SortedMap<K, V> headMap(K toKey) {
++ SortedMap<K, V> map = getSortedMap().headMap(toKey);
++ return new UnmodifiableSortedMap<K, V>(map);
++ }
++
++ public SortedMap<K, V> tailMap(K fromKey) {
++ SortedMap<K, V> map = getSortedMap().tailMap(fromKey);
++ return new UnmodifiableSortedMap<K, V>(map);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/map/package.html
+@@ -0,0 +1,54 @@
++<!-- $Id: package.html,v 1.1 2005/10/11 17:05:32 pents90 Exp $ -->
++ <!--
++ Copyright 2003-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<BODY>
++<p>
++This package contains implementations of the
++{@link java.util.Map Map},
++{@link org.apache.commons.collections.IterableMap IterableMap},
++{@link org.apache.commons.collections.OrderedMap OrderedMap} and
++{@link java.util.SortedMap SortedMap} interfaces.
++A Map provides a lookup from a key to a value.
++A number of implementations also support the new MapIterator interface that enables
++simple iteration of map keys and values.
++<p>
++The following implementations are provided:
++<ul>
++<li>CaseInsensitiveMap - map that compares keys in a case insensitive way
++<li>CompositeMap - map that combines multiple maps into a single view
++<li>HashedMap - general purpose HashMap replacement supporting MapIterator
++<li>IdentityMap - map that uses == for comparison instead of equals()
++<li>Flat3Map - designed for good performance at size 3 or less
++<li>LinkedMap - a hash map that maintains insertion order, supporting OrderedMapIterator
++<li>MultiKeyMap - map that provides special methods for using more than one key to access the value
++<li>ReferenceMap - allows the garbage collector to collect keys and values using equals() for comparison
++<li>ReferenceIdentityMap - allows the garbage collector to collect keys and values using == for comparison
++<li>SingletonMap - a fully featured map to hold one key-value pair
++<li>StaticBucketMap - internally synchronized and designed for thread-contentious environments
++</ul>
++<p>
++The following decorators are provided:
++<ul>
++<li>Unmodifiable - ensures the collection cannot be altered
++<li>Predicated - ensures that only elements that are valid according to a predicate can be added
++<li>Typed - ensures that only elements that are of a specific type can be added
++<li>Transformed - transforms each element added
++<li>FixedSize - ensures that the size of the map cannot change
++<li>Lazy - creates objects in the map on demand
++<li>ListOrdered - ensures that insertion order is retained
++</ul>
++</pre>
++</BODY>
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/multimap/MultiHashMap.java
+@@ -0,0 +1,524 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2001-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.multimap;
++
++import org.apache.commons.collections15.iterators.EmptyIterator;
++import org.apache.commons.collections15.MultiMap;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.Serializable;
++import java.util.*;
++
++/**
++ * <code>MultiHashMap</code> is the default implementation of the
++ * {@link org.apache.commons.collections15.MultiMap MultiMap} interface.
++ * <p/>
++ * A <code>MultiMap</code> is like a Map, but 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>
++ * Number key = new Integer(5);
++ * MultiMap<Number,String> mhm = new MultiHashMap<Number,String>();
++ * mhm.put(key, "A");
++ * mhm.put(key, "B");
++ * mhm.put(key, "C");
++ * Collection<String> coll = mhm.get(key);</pre>
++ * <p/>
++ * <code>list</code> will be a list containing "A", "B", "C".
++ *
++ * @author Christopher Berry
++ * @author James Strachan
++ * @author Steve Downey
++ * @author Stephen Colebourne
++ * @author Julien Buret
++ * @author Matt Hall, John Watkinson, Serhiy Yevtushenko
++ * @version $Revision: 1.2 $ $Date: 2006/06/08 15:19:55 $
++ * @since Commons Collections 2.0
++ */
++public class MultiHashMap<K,V> implements MultiMap<K,V>, Serializable, Cloneable {
++
++ // backed values collection
++ private transient Collection values = null;
++
++ // compatibility with commons-collection releases 2.0/2.1
++ private static final long serialVersionUID = 1943563828307035349L;
++
++ private HashMap<K,Collection<V>> internalMap;
++
++ /**
++ * Constructor.
++ */
++ public MultiHashMap() {
++ internalMap = new HashMap<K, Collection<V>>();
++ }
++
++ /**
++ * Constructor.
++ *
++ * @param initialCapacity the initial map capacity
++ */
++ public MultiHashMap(int initialCapacity) {
++ internalMap = new HashMap<K, Collection<V>>(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) {
++ internalMap = new HashMap<K, Collection<V>>(initialCapacity, loadFactor);
++ }
++
++ /**
++ * Constructor that copies the input map creating an independent copy.
++ * <p/>
++ * The values are not cloned.
++ * <p/>
++ *
++ * @param mapToCopy a Map to copy
++ */
++ public MultiHashMap(Map<K, V> mapToCopy) {
++ // be careful of JDK 1.3 vs 1.4 differences
++ internalMap = new HashMap<K, Collection<V>>((int) (mapToCopy.size() * 1.4f));
++ putAll(mapToCopy);
++ }
++
++ /**
++ * Constructor that copies the input MultiMap creating an independent copy.
++ * <p/>
++ * Each internal collection is also cloned.
++ * <p/>
++ * NOTE: From Commons Collections 3.1 this method correctly copies a MultiMap
++ * to form a truly independent new map.
++ *
++ * @param mapToCopy a Map to copy
++ */
++ public MultiHashMap(MultiMap<K,V> mapToCopy) {
++ internalMap = new HashMap<K, Collection<V>>((int) (mapToCopy.size() * 1.4f));
++ for (Iterator<Map.Entry<K,Collection<V>>> it = mapToCopy.entrySet().iterator(); it.hasNext();) {
++ Map.Entry<K,Collection<V>> entry = it.next();
++ Collection<V> coll = entry.getValue();
++ Collection<V> newColl = createCollection(coll);
++ internalMap.put(entry.getKey(), newColl);
++ }
++
++ }
++
++ /**
++ * 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<Map.Entry<K,Collection<V>>> iterator = entrySet().iterator(); iterator.hasNext();) {
++ Map.Entry<K,Collection<V>> entry = iterator.next();
++ // put has created a extra collection level, remove it
++ internalMap.put(entry.getKey(), entry.getValue());
++ }
++ }
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * 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<Collection<V>> values = internalMap.values();
++ for (Iterator<Collection<V>> it = values.iterator(); it.hasNext();) {
++ Collection<V> coll = 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<V> getCollection(Object key) {
++ return internalMap.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<V> 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<V> iterator(Object key) {
++ Collection<V> 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 V put(K key, V value) {
++ // NOTE:: put is called during deserialization in JDK < 1.4 !!!!!!
++ // so we must have a readObject()
++ Collection<V> coll = getCollection(key);
++ if (coll == null) {
++ coll = createCollection(null);
++ internalMap.put(key, coll);
++ }
++ boolean results = coll.add(value);
++ return results ? value : null;
++ }
++
++ /**
++ * 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(K key, Collection<? extends V> values) {
++ if (values == null || values.size() == 0) {
++ return false;
++ }
++ Collection<V> coll = getCollection(key);
++ if (coll == null) {
++ coll = createCollection(values);
++ if (coll.size() == 0) {
++ return false;
++ }
++ internalMap.put(key, coll);
++ return true;
++ } else {
++ return coll.addAll(values);
++ }
++ }
++
++ /**
++ * Checks whether the map contains the value specified.
++ * <p/>
++ * This checks all collections15 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<Map.Entry<K,Collection<V>>> pairs = internalMap.entrySet();
++
++ if (pairs == null) {
++ return false;
++ }
++ Iterator<Map.Entry<K,Collection<V>>> pairsIterator = pairs.iterator();
++ while (pairsIterator.hasNext()) {
++ Map.Entry<K,Collection<V>> keyValuePair = pairsIterator.next();
++ Collection<V> coll = 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<V> 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 V remove(Object key, Object item) {
++ Collection valuesForKey = getCollection(key);
++ if (valuesForKey == null) {
++ return null;
++ }
++ valuesForKey.remove(item);
++
++ // remove the list if it is now empty
++ // (saves space, and allows equals to work)
++ if (valuesForKey.isEmpty()) {
++ remove(key);
++ }
++ return (V)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<Map.Entry<K,Collection<V>>> pairs = internalMap.entrySet();
++ Iterator<Map.Entry<K,Collection<V>>> pairsIterator = pairs.iterator();
++ while (pairsIterator.hasNext()) {
++ Map.Entry<K,Collection<V>> keyValuePair = pairsIterator.next();
++ Collection<V> coll = keyValuePair.getValue();
++ coll.clear();
++ }
++ internalMap.clear();
++ }
++
++ public int size() {
++ return internalMap.size();
++ }
++
++ public Collection<V> get(Object key) {
++ return internalMap.get(key);
++ }
++
++ public Collection<V> remove(Object key) {
++ return internalMap.remove(key);
++ }
++
++ public boolean isEmpty() {
++ return internalMap.isEmpty();
++ }
++
++ public boolean containsKey(Object key) {
++ return internalMap.containsKey(key);
++ }
++
++ public void putAll(Map<? extends K, ? extends V> map) {
++ for (K key : map.keySet()) {
++ put(key, map.get(key));
++ }
++ }
++
++ public void putAll(MultiMap<? extends K, ? extends V> map) {
++ for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
++ Map.Entry<? extends K, Collection<? extends V>> entry = (Map.Entry<? extends K, Collection<? extends V>>) it.next();
++ for (V v : entry.getValue()) {
++ put(entry.getKey(), v);
++ }
++ }
++ }
++
++ public Set<K> keySet() {
++ return internalMap.keySet();
++ }
++
++ public Set<Map.Entry<K, Collection<V>>> entrySet() {
++ return internalMap.entrySet();
++ }
++
++ public Map<K, Collection<V>> map() {
++ return internalMap;
++ }
++
++ /**
++ * 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<V> values() {
++ Collection vs = values;
++ return vs != null ? vs : (values = new Values<V>());
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Inner class to view the elements.
++ */
++ private class Values<T> extends AbstractCollection<V> {
++
++ public Iterator<V> iterator() {
++ return new ValueIterator<V>();
++ }
++
++ 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<T> implements Iterator<V> {
++ private Iterator<Collection<V>> backedIterator;
++ private Iterator<V> tempIterator;
++
++ private ValueIterator() {
++ backedIterator = internalMap.values().iterator();
++ }
++
++ private boolean searchNextIterator() {
++ while (tempIterator == null || tempIterator.hasNext() == false) {
++ if (backedIterator.hasNext() == false) {
++ return false;
++ }
++ tempIterator = backedIterator.next().iterator();
++ }
++ return true;
++ }
++
++ public boolean hasNext() {
++ return searchNextIterator();
++ }
++
++ public V 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 collections15 as well as the map.
++ *
++ * @return the cloned map
++ */
++ public Object clone() {
++ MultiHashMap<K,V> cloned = new MultiHashMap<K, V>();
++ for (Iterator<Map.Entry<K,Collection<V>>> it = internalMap.entrySet().iterator(); it.hasNext();) {
++ Map.Entry<K,Collection<V>> entry = it.next();
++ for (V v : entry.getValue()) {
++ cloned.put(entry.getKey(), v);
++ }
++ }
++ return cloned;
++ }
++
++ public boolean equals(Object obj) {
++ if (obj instanceof MultiHashMap) {
++ return internalMap.equals(((MultiHashMap)obj).map());
++ } else return false;
++ }
++
++ public int hashCode() {
++ return internalMap.hashCode();
++ }
++
++ /**
++ * 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<V> createCollection(Collection<? extends V> coll) {
++ if (coll == null) {
++ return new ArrayList<V>();
++ } else {
++ return new ArrayList<V>(coll);
++ }
++ }
++
++ public String toString() {
++ return internalMap.toString();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/overview.html
+@@ -0,0 +1,112 @@
++<!-- $Id: overview.html,v 1.1 2005/10/11 17:05:19 pents90 Exp $ -->
++ <!--
++ Copyright 2003-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<body>
++ <p>
++ Commons-Collections contains implementations, enhancements and utilities
++ that complement the Java Collections Framework.
++ </p>
++ <p>
++ The Apache Jakarta Commons Collections Framework component adds a significant
++ amount of enhancements to the standard JDK collections. These enhancements
++ come in the form of new interfaces, new implementations and utility classes.
++ </p>
++ <p>
++ See also the <code>java.util</code> package for the standard Java collections.
++ </p>
++
++ <h4>Main features</h4>
++ <p>
++ Commons-Collections defines a number of key interfaces:
++ </p>
++ <table border="1" cellspacing="0" cellpadding="3">
++ <tr bgcolor="#CCCCFF" class="TableHeadingColor">
++ <th>Interface</th><th>Description</th>
++ </tr>
++ <tr>
++ <td>
++ {@link org.apache.commons.collections.Bag}
++ </td>
++ <td valign="top">
++ A new <code>Collection</code> subinterface that stores each object together
++ with the number of occurances. Methods are provided to get the number of
++ occurances, and to add and remove a certain number of that object.
++ </td>
++ </tr>
++ <tr>
++ <td>
++ {@link org.apache.commons.collections.Buffer}
++ </td>
++ <td valign="top">
++ A new <code>Collection</code> subinterface that allows objects to be removed
++ in some well-defined order. Methods enable the next item to be peeked and removed.
++ </td>
++ </tr>
++ <tr>
++ <td>
++ {@link org.apache.commons.collections.BidiMap}
++ </td>
++ <td valign="top">
++ A new <code>Map</code> subinterface that allows lookup from key to value and
++ from value to key with equal ease.
++ </td>
++ </tr>
++ <tr>
++ <td>
++ {@link org.apache.commons.collections.OrderedMap}
++ </td>
++ <td valign="top">
++ A new <code>Map</code> subinterface that is used when a map has an order, but is
++ not sorted. Methods enable bidriectional iteration through the map.
++ </td>
++ </tr>
++ <tr>
++ <td>
++ {@link org.apache.commons.collections.MapIterator}
++ </td>
++ <td valign="top">
++ A new <code>Iterator</code> subinterface specially designed for maps. This iterator
++ avoids the need for entrySet iteration of a map, and is simpler to use.
++ </td>
++ </tr>
++ <tr>
++ <td>
++ {@link org.apache.commons.collections.ResettableIterator}
++ </td>
++ <td valign="top">
++ A new <code>Iterator</code> subinterface that allows the iteration to be reset back
++ to the start. Many iterators in this library have this functionality.
++ </td>
++ </tr>
++ <tr>
++ <td>
++ {@link org.apache.commons.collections.Closure}<br />
++ {@link org.apache.commons.collections.Predicate}<br />
++ {@link org.apache.commons.collections.Transformer}<br />
++ {@link org.apache.commons.collections.Factory}<br />
++ </td>
++ <td valign="top">
++ A group of <i>functor</i> interfaces that provide plugin behaviour to various
++ collections and utilities.
++ </td>
++ </tr>
++ </table>
++ <p>
++ In addition to the interfaces, there are many implementations.
++ Consult each subpackage for full details of these.
++ </p>
++
++</body>
+\ No newline at end of file
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/package.html
+@@ -0,0 +1,31 @@
++<!-- $Id: package.html,v 1.1 2005/10/11 17:05:19 pents90 Exp $ -->
++ <!--
++ Copyright 2003-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<body>
++<p>
++This package contains the interfaces and utilities shared across all the subpackages of this component.
++</p>
++<p>
++The following collection implementations are provided in the package:
++<ul>
++<li>ArrayStack - a non synchronized Stack that follows the same API as java util Stack
++<li>BeanMap - a map that wraps a JavaBean, representing its properties as map keys and values
++<li>ExtendedProperties - extends the Properties class to add extra functionality
++<li>MultiHashMap - an map that stores multiple values against each key
++</ul>
++<p>
++
++</body>
+\ No newline at end of file
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/AbstractSerializableSetDecorator.java
+@@ -0,0 +1,70 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Set;
++
++/**
++ * Serializable subclass of AbstractSetDecorator.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @since Commons Collections 3.1
++ */
++public abstract class AbstractSerializableSetDecorator <E> extends AbstractSetDecorator<E> implements Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 1229469966212206107L;
++
++ /**
++ * Constructor.
++ */
++ protected AbstractSerializableSetDecorator(Set<E> set) {
++ super(set);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the set out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(collection);
++ }
++
++ /**
++ * Read the set in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ collection = (Collection<E>) in.readObject();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/AbstractSetDecorator.java
+@@ -0,0 +1,62 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.collection.AbstractCollectionDecorator;
++
++import java.util.Set;
++
++/**
++ * Decorates another <code>Set</code> to provide additional behaviour.
++ * <p/>
++ * Methods are forwarded directly to the decorated set.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractSetDecorator <E> extends AbstractCollectionDecorator<E> implements Set<E> {
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ *
++ * @since Commons Collections 3.1
++ */
++ protected AbstractSetDecorator() {
++ super();
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ protected AbstractSetDecorator(Set<E> set) {
++ super(set);
++ }
++
++ /**
++ * Gets the set being decorated.
++ *
++ * @return the decorated set
++ */
++ protected Set<E> getSet() {
++ return (Set<E>) getCollection();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/AbstractSortedSetDecorator.java
+@@ -0,0 +1,87 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import java.util.Comparator;
++import java.util.Set;
++import java.util.SortedSet;
++
++/**
++ * Decorates another <code>SortedSet</code> to provide additional behaviour.
++ * <p/>
++ * Methods are forwarded directly to the decorated set.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public abstract class AbstractSortedSetDecorator <E> extends AbstractSetDecorator<E> implements SortedSet<E> {
++
++ /**
++ * Constructor only used in deserialization, do not use otherwise.
++ *
++ * @since Commons Collections 3.1
++ */
++ protected AbstractSortedSetDecorator() {
++ super();
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ protected AbstractSortedSetDecorator(Set<E> set) {
++ super(set);
++ }
++
++ /**
++ * Gets the sorted set being decorated.
++ *
++ * @return the decorated set
++ */
++ protected SortedSet<E> getSortedSet() {
++ return (SortedSet<E>) getCollection();
++ }
++
++ //-----------------------------------------------------------------------
++ public SortedSet<E> subSet(E fromElement, E toElement) {
++ return getSortedSet().subSet(fromElement, toElement);
++ }
++
++ public SortedSet<E> headSet(E toElement) {
++ return getSortedSet().headSet(toElement);
++ }
++
++ public SortedSet<E> tailSet(E fromElement) {
++ return getSortedSet().tailSet(fromElement);
++ }
++
++ public E first() {
++ return getSortedSet().first();
++ }
++
++ public E last() {
++ return getSortedSet().last();
++ }
++
++ public Comparator<? super E> comparator() {
++ return getSortedSet().comparator();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/CompositeSet.java
+@@ -0,0 +1,197 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.CollectionUtils;
++import org.apache.commons.collections15.collection.CompositeCollection;
++
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.Set;
++
++/**
++ * Decorates a set of other sets to provide a single unified view.
++ * <p/>
++ * Changes made to this set will actually be made on the decorated set.
++ * Add and remove operations require the use of a pluggable strategy. If no
++ * strategy is provided then add and remove are unsupported.
++ *
++ * @author Matt Hall, John Watkinson, Brian McCallister
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public class CompositeSet <E> extends CompositeCollection<E> implements Set<E> {
++ /**
++ * Create an empty CompositeSet
++ */
++ public CompositeSet() {
++ super();
++ }
++
++ /**
++ * Create a CompositeSet with just <code>set</code> composited
++ *
++ * @param set The initial set in the composite
++ */
++ public CompositeSet(Set<E> set) {
++ super(set);
++ }
++
++ /**
++ * Create a composite set with sets as the initial set of composited Sets
++ */
++ public CompositeSet(Set<E>... sets) {
++ super(sets);
++ }
++
++ /**
++ * Add a Set to this composite
++ *
++ * @param c Must implement Set
++ * @throws IllegalArgumentException if c does not implement java.util.Set
++ * or if a SetMutator is set, but fails to resolve a collision
++ * @throws UnsupportedOperationException if there is no SetMutator set, or
++ * a CollectionMutator is set instead of a SetMutator
++ * @see org.apache.commons.collections15.collection.CompositeCollection.CollectionMutator
++ * @see SetMutator
++ */
++ public synchronized void addComposited(Collection<? extends E> c) {
++ if (!(c instanceof Set)) {
++ throw new IllegalArgumentException("Collections added must implement java.util.Set");
++ }
++
++ for (Iterator i = this.getCollections().iterator(); i.hasNext();) {
++ Set set = (Set) i.next();
++ Collection intersects = CollectionUtils.intersection(set, c);
++ if (intersects.size() > 0) {
++ if (this.mutator == null) {
++ throw new UnsupportedOperationException("Collision adding composited collection with no SetMutator set");
++ } else if (!(this.mutator instanceof SetMutator)) {
++ throw new UnsupportedOperationException("Collision adding composited collection to a CompositeSet with a CollectionMutator instead of a SetMutator");
++ }
++ ((SetMutator) this.mutator).resolveCollision(this, set, (Set) c, intersects);
++ if (CollectionUtils.intersection(set, c).size() > 0) {
++ throw new IllegalArgumentException("Attempt to add illegal entry unresolved by SetMutator.resolveCollision()");
++ }
++ }
++ }
++ super.addComposited((Collection<E>[]) new Collection[]{c});
++ }
++
++ /**
++ * Add two sets to this composite
++ *
++ * @deprecated Superceded by the variable argument implementation of addComposited()
++ * @throws IllegalArgumentException if c or d does not implement java.util.Set
++ */
++ public synchronized void addComposited(Collection<? extends E> c, Collection<? extends E> d) {
++ if (!(c instanceof Set)) throw new IllegalArgumentException("Argument must implement java.util.Set");
++ if (!(d instanceof Set)) throw new IllegalArgumentException("Argument must implement java.util.Set");
++ this.addComposited(new Set[]{(Set) c, (Set) d});
++ }
++
++ /**
++ * Add an array of sets to this composite
++ *
++ * @param comps
++ * @throws IllegalArgumentException if any of the collections15 in comps do not implement Set
++ */
++ public synchronized void addComposited(Collection<? extends E>... comps) {
++ for (int i = comps.length - 1; i >= 0; --i) {
++ this.addComposited(comps[i]);
++ }
++ }
++
++ /**
++ * This can receive either a <code>CompositeCollection.CollectionMutator</code>
++ * or a <code>CompositeSet.SetMutator</code>. If a
++ * <code>CompositeCollection.CollectionMutator</code> is used than conflicts when adding
++ * composited sets will throw IllegalArgumentException
++ * <p/>
++ */
++ public void setMutator(CollectionMutator<E> mutator) {
++ super.setMutator(mutator);
++ }
++
++ /* Set operations */
++
++ /**
++ * If a <code>CollectionMutator</code> is defined for this CompositeSet then this
++ * method will be called anyway.
++ *
++ * @param obj Object to be removed
++ * @return true if the object is removed, false otherwise
++ */
++ public boolean remove(Object obj) {
++ for (Iterator i = this.getCollections().iterator(); i.hasNext();) {
++ Set set = (Set) i.next();
++ if (set.contains(obj)) return set.remove(obj);
++ }
++ return false;
++ }
++
++
++ /**
++ * @see Set#equals
++ */
++ public boolean equals(Object obj) {
++ if (obj instanceof Set) {
++ Set set = (Set) obj;
++ if (set.containsAll(this) && set.size() == this.size()) {
++ return true;
++ }
++ }
++ return false;
++ }
++
++ /**
++ * @see Set#hashCode
++ */
++ public int hashCode() {
++ int code = 0;
++ for (Iterator i = this.iterator(); i.hasNext();) {
++ Object next = i.next();
++ code += (next != null ? next.hashCode() : 0);
++ }
++ return code;
++ }
++
++ /**
++ * Define callbacks for mutation operations.
++ * <p/>
++ * Defining remove() on implementations of SetMutator is pointless
++ * as they are never called by CompositeSet.
++ */
++ public static interface SetMutator <E> extends CompositeCollection.CollectionMutator<E> {
++ /**
++ * <p/>
++ * Called when a Set is added to the CompositeSet and there is a
++ * collision between existing and added sets.
++ * </p>
++ * <p/>
++ * If <code>added</code> and <code>existing</code> still have any intersects
++ * after this method returns an IllegalArgumentException will be thrown.
++ * </p>
++ *
++ * @param comp The CompositeSet being modified
++ * @param existing The Set already existing in the composite
++ * @param added the Set being added to the composite
++ * @param intersects the intersection of th existing and added sets
++ */
++ public void resolveCollision(CompositeSet<E> comp, Set<E> existing, Set<E> added, Collection<E> intersects);
++ }
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/ListOrderedSet.java
+@@ -0,0 +1,310 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.iterators.AbstractIteratorDecorator;
++import org.apache.commons.collections15.list.UnmodifiableList;
++
++import java.util.*;
++
++/**
++ * Decorates another <code>Set</code> to ensure that the order of addition
++ * is retained and used by the iterator.
++ * <p/>
++ * If an object is added to the set for a second time, it will remain in the
++ * original position in the iteration.
++ * The order can be observed from the set via the iterator or toArray methods.
++ * <p/>
++ * The ListOrderedSet also has various useful direct methods. These include many
++ * from <code>List</code>, such as <code>get(int)</code>, <code>remove(int)</code>
++ * and <code>indexOf(int)</code>. An unmodifiable <code>List</code> view of
++ * the set can be obtained via <code>asList()</code>.
++ * <p/>
++ * This class cannot implement the <code>List</code> interface directly as
++ * various interface methods (notably equals/hashCode) are incompatable with a set.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @author Henning P. Schmiedehausen
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public class ListOrderedSet <E> extends AbstractSerializableSetDecorator<E> implements Set<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -228664372470420141L;
++
++ /**
++ * Internal list to hold the sequence of objects
++ */
++ protected final List<E> setOrder;
++
++ /**
++ * Factory method to create an ordered set specifying the list and set to use.
++ *
++ * @param set the set to decorate, must be empty and not null
++ * @param list the list to decorate, must be empty and not null
++ * @throws IllegalArgumentException if set or list is null
++ * @throws IllegalArgumentException if either the set or list is not empty
++ * @since Commons Collections 3.1
++ */
++ public static <E> ListOrderedSet<E> decorate(Set<E> set, List<E> list) {
++ if (set == null) {
++ throw new IllegalArgumentException("Set must not be null");
++ }
++ if (list == null) {
++ throw new IllegalArgumentException("List must not be null");
++ }
++ if (set.size() > 0 || list.size() > 0) {
++ throw new IllegalArgumentException("Set and List must be empty");
++ }
++ return new ListOrderedSet<E>(set, list);
++ }
++
++ /**
++ * Factory method to create an ordered set.
++ * <p/>
++ * An <code>ArrayList</code> is used to retain order.
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ public static <E> ListOrderedSet<E> decorate(Set<E> set) {
++ return new ListOrderedSet<E>(set);
++ }
++
++ /**
++ * Factory method to create an ordered set using the supplied list to retain order.
++ * <p/>
++ * A <code>HashSet</code> is used for the set behaviour.
++ *
++ * @param list the list to decorate, must not be null
++ * @throws IllegalArgumentException if list is null
++ */
++ public static <E> ListOrderedSet<E> decorate(List<E> list) {
++ if (list == null) {
++ throw new IllegalArgumentException("List must not be null");
++ }
++ Set<E> set = new HashSet<E>(list);
++ list.retainAll(set);
++
++ return new ListOrderedSet<E>(set, list);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructs a new empty <code>ListOrderedSet</code> using
++ * a <code>HashSet</code> and an <code>ArrayList</code> internally.
++ *
++ * @since Commons Collections 3.1
++ */
++ public ListOrderedSet() {
++ super(new HashSet<E>());
++ setOrder = new ArrayList<E>();
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ protected ListOrderedSet(Set<E> set) {
++ super(set);
++ setOrder = new ArrayList<E>(set);
++ }
++
++ /**
++ * Constructor that wraps (not copies) the Set and specifies the list to use.
++ * <p/>
++ * The set and list must both be correctly initialised to the same elements.
++ *
++ * @param set the set to decorate, must not be null
++ * @param list the list to decorate, must not be null
++ * @throws IllegalArgumentException if set or list is null
++ */
++ protected ListOrderedSet(Set<E> set, List<E> list) {
++ super(set);
++ if (list == null) {
++ throw new IllegalArgumentException("List must not be null");
++ }
++ setOrder = list;
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Gets an unmodifiable view of the order of the Set.
++ *
++ * @return an unmodifiable list view
++ */
++ public List<E> asList() {
++ return UnmodifiableList.decorate(setOrder);
++ }
++
++ //-----------------------------------------------------------------------
++ public void clear() {
++ collection.clear();
++ setOrder.clear();
++ }
++
++ public Iterator<E> iterator() {
++ return new OrderedSetIterator<E>(setOrder.iterator(), collection);
++ }
++
++ public boolean add(E object) {
++ if (collection.contains(object)) {
++ // re-adding doesn't change order
++ return collection.add(object);
++ } else {
++ // first add, so add to both set and list
++ boolean result = collection.add(object);
++ setOrder.add(object);
++ return result;
++ }
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ boolean result = false;
++ for (Iterator<? extends E> it = coll.iterator(); it.hasNext();) {
++ E object = it.next();
++ result = result | add(object);
++ }
++ return result;
++ }
++
++ public boolean remove(Object object) {
++ boolean result = collection.remove(object);
++ setOrder.remove(object);
++ return result;
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ boolean result = false;
++ for (Iterator it = coll.iterator(); it.hasNext();) {
++ Object object = it.next();
++ result = result | remove(object);
++ }
++ return result;
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ boolean result = collection.retainAll(coll);
++ if (result == false) {
++ return false;
++ } else if (collection.size() == 0) {
++ setOrder.clear();
++ } else {
++ for (Iterator it = setOrder.iterator(); it.hasNext();) {
++ Object object = it.next();
++ if (collection.contains(object) == false) {
++ it.remove();
++ }
++ }
++ }
++ return result;
++ }
++
++ public Object[] toArray() {
++ return setOrder.toArray();
++ }
++
++ public <T> T[] toArray(T[] a) {
++ return setOrder.toArray(a);
++ }
++
++ //-----------------------------------------------------------------------
++ public E get(int index) {
++ return setOrder.get(index);
++ }
++
++ public int indexOf(E object) {
++ return setOrder.indexOf(object);
++ }
++
++ public void add(int index, E object) {
++ if (contains(object) == false) {
++ collection.add(object);
++ setOrder.add(index, object);
++ }
++ }
++
++ public boolean addAll(int index, Collection<? extends E> coll) {
++ boolean changed = false;
++ for (Iterator<? extends E> it = coll.iterator(); it.hasNext();) {
++ E object = it.next();
++ if (contains(object) == false) {
++ collection.add(object);
++ setOrder.add(index, object);
++ index++;
++ changed = true;
++ }
++ }
++ return changed;
++ }
++
++ public E remove(int index) {
++ E obj = setOrder.remove(index);
++ remove(obj);
++ return obj;
++ }
++
++ /**
++ * Uses the underlying List's toString so that order is achieved.
++ * This means that the decorated Set's toString is not used, so
++ * any custom toStrings will be ignored.
++ */
++ // Fortunately List.toString and Set.toString look the same
++ public String toString() {
++ return setOrder.toString();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Internal iterator handle remove.
++ */
++ static class OrderedSetIterator <E> extends AbstractIteratorDecorator<E> {
++
++ /**
++ * Object we iterate on
++ */
++ protected final Collection<E> set;
++ /**
++ * Last object retrieved
++ */
++ protected E last;
++
++ private OrderedSetIterator(Iterator<E> iterator, Collection<E> set) {
++ super(iterator);
++ this.set = set;
++ }
++
++ public E next() {
++ last = iterator.next();
++ return last;
++ }
++
++ public void remove() {
++ set.remove(last);
++ iterator.remove();
++ last = null;
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/MapBackedSet.java
+@@ -0,0 +1,163 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.Map;
++import java.util.Set;
++
++/**
++ * Decorates a <code>Map</code> to obtain <code>Set</code> behaviour.
++ * <p/>
++ * This class is used to create a <code>Set</code> with the same properties as
++ * the key set of any map. Thus, a ReferenceSet can be created by wrapping a
++ * <code>ReferenceMap</code> in an instance of this class.
++ * <p/>
++ * Most map implementation can be used to create a set by passing in dummy values.
++ * Exceptions include <code>BidiMap</code> implementations, as they require unique values.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.1
++ */
++public final class MapBackedSet <K,V> implements Set<K>, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 6723912213766056587L;
++
++ /**
++ * The map being used as the backing store
++ */
++ protected final Map<K, V> map;
++ /**
++ * The dummyValue to use
++ */
++ protected final V dummyValue;
++
++ /**
++ * Factory method to create a set from a map.
++ *
++ * @param map the map to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ public static <K,V> Set<K> decorate(Map<K, V> map) {
++ return decorate(map, null);
++ }
++
++ /**
++ * Factory method to create a set from a map.
++ *
++ * @param map the map to decorate, must not be null
++ * @param dummyValue the dummy value to use
++ * @throws IllegalArgumentException if map is null
++ */
++ public static <K,V> Set<K> decorate(Map<K, V> map, V dummyValue) {
++ if (map == null) {
++ throw new IllegalArgumentException("The map must not be null");
++ }
++ return new MapBackedSet<K, V>(map, dummyValue);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param map the map to decorate, must not be null
++ * @param dummyValue the dummy value to use
++ * @throws IllegalArgumentException if map is null
++ */
++ private MapBackedSet(Map<K, V> map, V dummyValue) {
++ super();
++ this.map = map;
++ this.dummyValue = dummyValue;
++ }
++
++ //-----------------------------------------------------------------------
++ public int size() {
++ return map.size();
++ }
++
++ public boolean isEmpty() {
++ return map.isEmpty();
++ }
++
++ public Iterator<K> iterator() {
++ return map.keySet().iterator();
++ }
++
++ public boolean contains(Object obj) {
++ return map.containsKey(obj);
++ }
++
++ public boolean containsAll(Collection<?> coll) {
++ return map.keySet().containsAll(coll);
++ }
++
++ public boolean add(K obj) {
++ int size = map.size();
++ map.put(obj, dummyValue);
++ return (map.size() != size);
++ }
++
++ public boolean addAll(Collection<? extends K> coll) {
++ int size = map.size();
++ for (Iterator<? extends K> it = coll.iterator(); it.hasNext();) {
++ K obj = it.next();
++ map.put(obj, dummyValue);
++ }
++ return (map.size() != size);
++ }
++
++ public boolean remove(Object obj) {
++ int size = map.size();
++ map.remove(obj);
++ return (map.size() != size);
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ return map.keySet().removeAll(coll);
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ return map.keySet().retainAll(coll);
++ }
++
++ public void clear() {
++ map.clear();
++ }
++
++ public Object[] toArray() {
++ return map.keySet().toArray();
++ }
++
++ public <T> T[] toArray(T[] array) {
++ return map.keySet().toArray(array);
++ }
++
++ public boolean equals(Object obj) {
++ return map.keySet().equals(obj);
++ }
++
++ public int hashCode() {
++ return map.keySet().hashCode();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/PredicatedSet.java
+@@ -0,0 +1,89 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.Predicate;
++import org.apache.commons.collections15.collection.PredicatedCollection;
++
++import java.util.Set;
++
++/**
++ * Decorates another <code>Set</code> to validate that all additions
++ * match a specified predicate.
++ * <p/>
++ * This set exists to provide validation for the decorated set.
++ * It is normally created to decorate an empty set.
++ * If an object cannot be added to the set, an IllegalArgumentException is thrown.
++ * <p/>
++ * One usage would be to ensure that no null entries are added to the set.
++ * <pre>Set set = PredicatedSet.decorate(new HashSet(), NotNullPredicate.INSTANCE);</pre>
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public class PredicatedSet <E> extends PredicatedCollection<E> implements Set<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -684521469108685117L;
++
++ /**
++ * Factory method to create a predicated (validating) set.
++ * <p/>
++ * If there are any elements already in the set being decorated, they
++ * are validated.
++ *
++ * @param set the set to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @throws IllegalArgumentException if set or predicate is null
++ * @throws IllegalArgumentException if the set contains invalid elements
++ */
++ public static <E> Set<E> decorate(Set<E> set, Predicate<? super E> predicate) {
++ return new PredicatedSet<E>(set, predicate);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the set being decorated, they
++ * are validated.
++ *
++ * @param set the set to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @throws IllegalArgumentException if set or predicate is null
++ * @throws IllegalArgumentException if the set contains invalid elements
++ */
++ protected PredicatedSet(Set<E> set, Predicate<? super E> predicate) {
++ super(set, predicate);
++ }
++
++ /**
++ * Gets the set being decorated.
++ *
++ * @return the decorated set
++ */
++ protected Set<E> getSet() {
++ return (Set<E>) getCollection();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/PredicatedSortedSet.java
+@@ -0,0 +1,117 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.Predicate;
++
++import java.util.Comparator;
++import java.util.SortedSet;
++
++/**
++ * Decorates another <code>SortedSet</code> to validate that all additions
++ * match a specified predicate.
++ * <p/>
++ * This set exists to provide validation for the decorated set.
++ * It is normally created to decorate an empty set.
++ * If an object cannot be added to the set, an IllegalArgumentException is thrown.
++ * <p/>
++ * One usage would be to ensure that no null entries are added to the set.
++ * <pre>SortedSet set = PredicatedSortedSet.decorate(new TreeSet(), NotNullPredicate.INSTANCE);</pre>
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Paul Jack
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public class PredicatedSortedSet <E> extends PredicatedSet<E> implements SortedSet<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -9110948148132275052L;
++
++ /**
++ * Factory method to create a predicated (validating) sorted set.
++ * <p/>
++ * If there are any elements already in the set being decorated, they
++ * are validated.
++ *
++ * @param set the set to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @throws IllegalArgumentException if set or predicate is null
++ * @throws IllegalArgumentException if the set contains invalid elements
++ */
++ public static <E> SortedSet<E> decorate(SortedSet<E> set, Predicate<? super E> predicate) {
++ return new PredicatedSortedSet<E>(set, predicate);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the set being decorated, they
++ * are validated.
++ *
++ * @param set the set to decorate, must not be null
++ * @param predicate the predicate to use for validation, must not be null
++ * @throws IllegalArgumentException if set or predicate is null
++ * @throws IllegalArgumentException if the set contains invalid elements
++ */
++ protected PredicatedSortedSet(SortedSet<E> set, Predicate<? super E> predicate) {
++ super(set, predicate);
++ }
++
++ /**
++ * Gets the sorted set being decorated.
++ *
++ * @return the decorated sorted set
++ */
++ private SortedSet<E> getSortedSet() {
++ return (SortedSet<E>) getCollection();
++ }
++
++ //-----------------------------------------------------------------------
++ public SortedSet<E> subSet(E fromElement, E toElement) {
++ SortedSet sub = getSortedSet().subSet(fromElement, toElement);
++ return new PredicatedSortedSet<E>(sub, predicate);
++ }
++
++ public SortedSet<E> headSet(E toElement) {
++ SortedSet sub = getSortedSet().headSet(toElement);
++ return new PredicatedSortedSet<E>(sub, predicate);
++ }
++
++ public SortedSet<E> tailSet(E fromElement) {
++ SortedSet sub = getSortedSet().tailSet(fromElement);
++ return new PredicatedSortedSet<E>(sub, predicate);
++ }
++
++ public E first() {
++ return getSortedSet().first();
++ }
++
++ public E last() {
++ return getSortedSet().last();
++ }
++
++ public Comparator<? super E> comparator() {
++ return getSortedSet().comparator();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/SynchronizedSet.java
+@@ -0,0 +1,83 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.collection.SynchronizedCollection;
++
++import java.util.Set;
++
++/**
++ * Decorates another <code>Set</code> to synchronize its behaviour for a
++ * multi-threaded environment.
++ * <p/>
++ * Methods are synchronized, then forwarded to the decorated set.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public class SynchronizedSet <E> extends SynchronizedCollection<E> implements Set<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -8304417378626543635L;
++
++ /**
++ * Factory method to create a synchronized set.
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ public static <E> Set<E> decorate(Set<E> set) {
++ return new SynchronizedSet<E>(set);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ protected SynchronizedSet(Set<E> set) {
++ super(set);
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param set the set to decorate, must not be null
++ * @param lock the lock object to use, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ protected SynchronizedSet(Set<E> set, Object lock) {
++ super(set, lock);
++ }
++
++ /**
++ * Gets the decorated set.
++ *
++ * @return the decorated set
++ */
++ protected Set<E> getSet() {
++ return (Set<E>) collection;
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/SynchronizedSortedSet.java
+@@ -0,0 +1,130 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.collection.SynchronizedCollection;
++
++import java.util.Comparator;
++import java.util.SortedSet;
++
++/**
++ * Decorates another <code>SortedSet</code> to synchronize its behaviour
++ * for a multi-threaded environment.
++ * <p/>
++ * Methods are synchronized, then forwarded to the decorated set.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public class SynchronizedSortedSet <E> extends SynchronizedCollection<E> implements SortedSet<E> {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 2775582861954500111L;
++
++ /**
++ * Factory method to create a synchronized set.
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ public static <E> SortedSet<E> decorate(SortedSet<E> set) {
++ return new SynchronizedSortedSet<E>(set);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ protected SynchronizedSortedSet(SortedSet<E> set) {
++ super(set);
++ }
++
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param set the set to decorate, must not be null
++ * @param lock the lock object to use, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ protected SynchronizedSortedSet(SortedSet<E> set, Object lock) {
++ super(set, lock);
++ }
++
++ /**
++ * Gets the decorated set.
++ *
++ * @return the decorated set
++ */
++ protected SortedSet<E> getSortedSet() {
++ return (SortedSet<E>) collection;
++ }
++
++ //-----------------------------------------------------------------------
++ public SortedSet<E> subSet(E fromElement, E toElement) {
++ synchronized (lock) {
++ SortedSet set = getSortedSet().subSet(fromElement, toElement);
++ // the lock is passed into the constructor here to ensure that the
++ // subset is synchronized on the same lock as the parent
++ return new SynchronizedSortedSet<E>(set, lock);
++ }
++ }
++
++ public SortedSet<E> headSet(E toElement) {
++ synchronized (lock) {
++ SortedSet set = getSortedSet().headSet(toElement);
++ // the lock is passed into the constructor here to ensure that the
++ // headset is synchronized on the same lock as the parent
++ return new SynchronizedSortedSet<E>(set, lock);
++ }
++ }
++
++ public SortedSet<E> tailSet(E fromElement) {
++ synchronized (lock) {
++ SortedSet<E> set = getSortedSet().tailSet(fromElement);
++ // the lock is passed into the constructor here to ensure that the
++ // tailset is synchronized on the same lock as the parent
++ return new SynchronizedSortedSet<E>(set, lock);
++ }
++ }
++
++ public E first() {
++ synchronized (lock) {
++ return getSortedSet().first();
++ }
++ }
++
++ public E last() {
++ synchronized (lock) {
++ return getSortedSet().last();
++ }
++ }
++
++ public Comparator<? super E> comparator() {
++ synchronized (lock) {
++ return getSortedSet().comparator();
++ }
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/TransformedSet.java
+@@ -0,0 +1,76 @@
++// TODO: Not yet converted - deprecated (by me).
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.Transformer;
++import org.apache.commons.collections15.collection.TransformedCollection;
++
++import java.util.Set;
++
++/**
++ * Decorates another <code>Set</code> to transform objects that are added.
++ * <p/>
++ * The add methods are affected by this class.
++ * Thus objects must be removed or searched for using their transformed form.
++ * For example, if the transformation converts Strings to Integers, you must
++ * use the Integer form to remove objects.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ * <p>
++ * Note: This class cannot support generics without breaking the Collection contract.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public class TransformedSet extends TransformedCollection implements Set {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 306127383500410386L;
++
++ /**
++ * Factory method to create a transforming set.
++ * <p/>
++ * If there are any elements already in the set being decorated, they
++ * are NOT transformed.
++ *
++ * @param set the set to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @throws IllegalArgumentException if set or transformer is null
++ */
++ public static <I,O> Set<O> decorate(Set<I> set, Transformer<? super I, ? extends O> transformer) {
++ return new TransformedSet(set, transformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the set being decorated, they
++ * are NOT transformed.
++ *
++ * @param set the set to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @throws IllegalArgumentException if set or transformer is null
++ */
++ protected TransformedSet(Set set, Transformer transformer) {
++ super(set, transformer);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/TransformedSortedSet.java
+@@ -0,0 +1,112 @@
++// TODO: Not yet converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.Transformer;
++
++import java.util.Comparator;
++import java.util.SortedSet;
++
++/**
++ * Decorates another <code>SortedSet</code> to transform objects that are added.
++ * <p/>
++ * The add methods are affected by this class.
++ * Thus objects must be removed or searched for using their transformed form.
++ * For example, if the transformation converts Strings to Integers, you must
++ * use the Integer form to remove objects.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public class TransformedSortedSet extends TransformedSet implements SortedSet {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -1675486811351124386L;
++
++ /**
++ * Factory method to create a transforming sorted set.
++ * <p/>
++ * If there are any elements already in the set being decorated, they
++ * are NOT transformed.
++ *
++ * @param set the set to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @throws IllegalArgumentException if set or transformer is null
++ */
++ public static <I,O> SortedSet<O> decorate(SortedSet<I> set, Transformer<? super I, ? extends O> transformer) {
++ return new TransformedSortedSet(set, transformer);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ * <p/>
++ * If there are any elements already in the set being decorated, they
++ * are NOT transformed.
++ *
++ * @param set the set to decorate, must not be null
++ * @param transformer the transformer to use for conversion, must not be null
++ * @throws IllegalArgumentException if set or transformer is null
++ */
++ protected TransformedSortedSet(SortedSet set, Transformer transformer) {
++ super(set, transformer);
++ }
++
++ /**
++ * Gets the decorated set.
++ *
++ * @return the decorated set
++ */
++ protected SortedSet getSortedSet() {
++ return (SortedSet) collection;
++ }
++
++ //-----------------------------------------------------------------------
++ public Object first() {
++ return getSortedSet().first();
++ }
++
++ public Object last() {
++ return getSortedSet().last();
++ }
++
++ public Comparator comparator() {
++ return getSortedSet().comparator();
++ }
++
++ //-----------------------------------------------------------------------
++ public SortedSet subSet(Object fromElement, Object toElement) {
++ SortedSet set = getSortedSet().subSet(fromElement, toElement);
++ return new TransformedSortedSet(set, transformer);
++ }
++
++ public SortedSet headSet(Object toElement) {
++ SortedSet set = getSortedSet().headSet(toElement);
++ return new TransformedSortedSet(set, transformer);
++ }
++
++ public SortedSet tailSet(Object fromElement) {
++ SortedSet set = getSortedSet().tailSet(fromElement);
++ return new TransformedSortedSet(set, transformer);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/TypedSet.java
+@@ -0,0 +1,59 @@
++// TODO: Not yet converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.functors.InstanceofPredicate;
++
++import java.util.Set;
++
++/**
++ * Decorates another <code>Set</code> to validate that elements
++ * added are of a specific type.
++ * <p/>
++ * The validation of additions is performed via an instanceof test against
++ * a specified <code>Class</code>. If an object cannot be added to the
++ * collection, an IllegalArgumentException is thrown.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @author Matthew Hawthorne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public class TypedSet {
++
++ /**
++ * Factory method to create a typed set.
++ * <p/>
++ * If there are any elements already in the set being decorated, they
++ * are validated.
++ *
++ * @param set the set to decorate, must not be null
++ * @param type the type to allow into the collection, must not be null
++ * @throws IllegalArgumentException if set or type is null
++ * @throws IllegalArgumentException if the set contains invalid elements
++ */
++ public static Set decorate(Set set, Class type) {
++ return new PredicatedSet(set, InstanceofPredicate.getInstance(type));
++ }
++
++ /**
++ * Restrictive constructor.
++ */
++ protected TypedSet() {
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/TypedSortedSet.java
+@@ -0,0 +1,59 @@
++// TODO: Not yet converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.functors.InstanceofPredicate;
++
++import java.util.SortedSet;
++
++/**
++ * Decorates another <code>SortedSet</code> to validate that elements
++ * added are of a specific type.
++ * <p/>
++ * The validation of additions is performed via an instanceof test against
++ * a specified <code>Class</code>. If an object cannot be added to the
++ * collection, an IllegalArgumentException is thrown.
++ *
++ * @author Stephen Colebourne
++ * @author Matt Hall, John Watkinson, Matthew Hawthorne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public class TypedSortedSet {
++
++ /**
++ * Factory method to create a typed sorted set.
++ * <p/>
++ * If there are any elements already in the set being decorated, they
++ * are validated.
++ *
++ * @param set the set to decorate, must not be null
++ * @param type the type to allow into the collection, must not be null
++ * @throws IllegalArgumentException if set or type is null
++ * @throws IllegalArgumentException if the set contains invalid elements
++ */
++ public static SortedSet decorate(SortedSet set, Class type) {
++ return new PredicatedSortedSet(set, InstanceofPredicate.getInstance(type));
++ }
++
++ /**
++ * Restrictive constructor.
++ */
++ protected TypedSortedSet() {
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/UnmodifiableSet.java
+@@ -0,0 +1,95 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.Unmodifiable;
++import org.apache.commons.collections15.iterators.UnmodifiableIterator;
++
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.Set;
++
++/**
++ * Decorates another <code>Set</code> to ensure it can't be altered.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableSet <E> extends AbstractSerializableSetDecorator<E> implements Unmodifiable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = 6499119872185240161L;
++
++ /**
++ * Factory method to create an unmodifiable set.
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ public static <E> Set<E> decorate(Set<E> set) {
++ if (set instanceof Unmodifiable) {
++ return set;
++ }
++ return new UnmodifiableSet<E>(set);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ private UnmodifiableSet(Set<E> set) {
++ super(set);
++ }
++
++ //-----------------------------------------------------------------------
++ public Iterator<E> iterator() {
++ return UnmodifiableIterator.decorate(getCollection().iterator());
++ }
++
++ public boolean add(E object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean remove(Object object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/UnmodifiableSortedSet.java
+@@ -0,0 +1,139 @@
++// GenericsNote: Converted.
++/*
++ * Copyright 2003-2004 The Apache Software Foundation
++ *
++ * Licensed 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.collections15.set;
++
++import org.apache.commons.collections15.Unmodifiable;
++import org.apache.commons.collections15.iterators.UnmodifiableIterator;
++
++import java.io.IOException;
++import java.io.ObjectInputStream;
++import java.io.ObjectOutputStream;
++import java.io.Serializable;
++import java.util.Collection;
++import java.util.Iterator;
++import java.util.SortedSet;
++
++/**
++ * Decorates another <code>SortedSet</code> to ensure it can't be altered.
++ * <p/>
++ * This class is Serializable from Commons Collections 3.1.
++ *
++ * @author Matt Hall, John Watkinson, Stephen Colebourne
++ * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:39 $
++ * @since Commons Collections 3.0
++ */
++public final class UnmodifiableSortedSet <E> extends AbstractSortedSetDecorator<E> implements Unmodifiable, Serializable {
++
++ /**
++ * Serialization version
++ */
++ private static final long serialVersionUID = -725356885467962424L;
++
++ /**
++ * Factory method to create an unmodifiable set.
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ public static <E> SortedSet<E> decorate(SortedSet<E> set) {
++ if (set instanceof Unmodifiable) {
++ return set;
++ }
++ return new UnmodifiableSortedSet<E>(set);
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Write the collection out using a custom routine.
++ *
++ * @param out the output stream
++ * @throws IOException
++ */
++ private void writeObject(ObjectOutputStream out) throws IOException {
++ out.defaultWriteObject();
++ out.writeObject(collection);
++ }
++
++ /**
++ * Read the collection in using a custom routine.
++ *
++ * @param in the input stream
++ * @throws IOException
++ * @throws ClassNotFoundException
++ */
++ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
++ in.defaultReadObject();
++ collection = (Collection<E>) in.readObject();
++ }
++
++ //-----------------------------------------------------------------------
++ /**
++ * Constructor that wraps (not copies).
++ *
++ * @param set the set to decorate, must not be null
++ * @throws IllegalArgumentException if set is null
++ */
++ private UnmodifiableSortedSet(SortedSet<E> set) {
++ super(set);
++ }
++
++ //-----------------------------------------------------------------------
++ public Iterator<E> iterator() {
++ return UnmodifiableIterator.decorate(getCollection().iterator());
++ }
++
++ public boolean add(E object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean addAll(Collection<? extends E> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public void clear() {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean remove(Object object) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean removeAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ public boolean retainAll(Collection<?> coll) {
++ throw new UnsupportedOperationException();
++ }
++
++ //-----------------------------------------------------------------------
++ public SortedSet<E> subSet(E fromElement, E toElement) {
++ SortedSet<E> sub = getSortedSet().subSet(fromElement, toElement);
++ return new UnmodifiableSortedSet<E>(sub);
++ }
++
++ public SortedSet<E> headSet(E toElement) {
++ SortedSet sub = getSortedSet().headSet(toElement);
++ return new UnmodifiableSortedSet<E>(sub);
++ }
++
++ public SortedSet<E> tailSet(E fromElement) {
++ SortedSet<E> sub = getSortedSet().tailSet(fromElement);
++ return new UnmodifiableSortedSet<E>(sub);
++ }
++
++}
+--- /dev/null
++++ libjung-java/collections15/org/apache/commons/collections15/set/package.html
+@@ -0,0 +1,42 @@
++<!-- $Id: package.html,v 1.1 2005/10/11 17:05:39 pents90 Exp $ -->
++ <!--
++ Copyright 2003-2004 The Apache Software Foundation
++
++ Licensed 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.
++ -->
++<BODY>
++<p>
++This package contains implementations of the
++{@link java.util.Set Set} and
++{@link java.util.SortedSet SortedSet} interfaces.
++<p>
++The implementations are in the form of direct implementations and decorators.
++A decorator wraps another implementation of the interface to add some
++specific additional functionality.
++<p>
++The following implementations are provided in the package:
++<ul>
++<li>CompositeSet - a set that combines multiple sets into one
++</ul>
++The following decorators are provided in the package:
++<ul>
++<li>Synchronized - synchronizes method access for multi-threaded environments
++<li>Unmodifiable - ensures the collection cannot be altered
++<li>Predicated - ensures that only elements that are valid according to a predicate can be added
++<li>Typed - ensures that only elements that are of a specific type can be added
++<li>Transformed - transforms each element added
++<li>ListOrdered - ensures that insertion order is retained
++<li>MapBackedSet - a set formed by decorating a Map
++</ul>
++</pre>
++</BODY>
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..692f4e8
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+collections15
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..dac7856
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,51 @@
+#!/usr/bin/make -f
+
+DH_VERBOSE := 1
+
+# some helpful variables - uncomment them if needed
+# shamelessly stolen from http://jmtd.net/log/awk/
+#DEBVERS := $(shell dpkg-parsechangelog | awk '/^Version:/ {print $$2}')
+#VERSION := $(shell echo '$(DEBVERS)' | sed -e 's/^[0-9]*://' -e 's/-.*//')
+#DEBFLAVOR := $(shell dpkg-parsechangelog | awk '/^Distribution:/ {print $$2}')
+#DEBPKGNAME := $(shell dpkg-parsechangelog | awk '/^Source:/ {print $$2}')
+#DEBIAN_BRANCH := $(shell awk 'BEGIN{FS="[= ]+"} /debian-branch/ {print $$2}' debian/gbp.conf)
+#GIT_TAG := $(subst ~,_,$(VERSION))
+
+# alternatively to manually set those variables you can
+# include /usr/share/cdbs/1/rules/buildvars.mk
+# and use what is set there. Any hint whether dh might set variables in
+# a similar manner are welcome.
+
+export JAVA_HOME=/usr/lib/jvm/default-java
+export CLASSPATH=/usr/share/java/commons-collections4.jar:/usr/share/java/colt.jar:./collections15.jar:./jung-api-2.0.1.jar
+
+%:
+ dh $@ --with javahelper
+
+override_dh_auto_build:
+ for jar in *.jar; do mkdir $${jar%%.jar}; pushd $${jar%%.jar}; \
+ unzip ../$${jar}; popd; done
+ #find . -type f | xargs sed -i -e \
+ #'s/org.apache.commons.collections15/org.apache.commons.collections4/' \
+ #-e 's/org.apache.commons.collections4.Buffer/java.util.Queue/' \
+ #-e 's/org.apache.commons.collections4.buffer.UnboundedFifoBuffer/java.util.LinkedList/' \
+ #-e 's/UnboundedFifoBuffer/LinkedList/' \
+ #-e 's/Buffer/Queue/' \
+ #-e 's/LazyMap.decorate/LazyMap.lazyMap/' \
+ #-e 's/MapTransformer.getInstance/MapTransformer.mapTransformer/' \
+ #-e 's/ChainedTransformer.getInstance/ChainedTransformer.chainedTransformer/' \
+ #-e 's/CloneTransformer.getInstance/CloneTransformer.cloneTransformer/' ;
+ # this _almost_ worked :-(
+ jh_build collections15.jar collections15
+ jh_build jung-api-2.0.1.jar jung-api-2.0.1-sources
+ jh_build jung-algorithms-2.0.1.jar jung-algorithms-2.0.1-sources
+ jh_build jung-graph-impl-2.0.1.jar jung-graph-impl-2.0.1-sources
+
+override_dh_auto_install:
+ jh_installlibs jung-api-2.0.1.jar
+ jh_installlibs collections15.jar
+ jh_installlibs jung-algorithms-2.0.1.jar
+ jh_installlibs jung-graph-impl-2.0.1.jar
+
+#get-orig-source:
+# . debian/get-orig-source
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/upstream/metadata b/debian/upstream/metadata
new file mode 100644
index 0000000..d8b5812
--- /dev/null
+++ b/debian/upstream/metadata
@@ -0,0 +1,12 @@
+Reference:
+ Author:
+ Title:
+ Journal:
+ Year:
+ Volume:
+ Number:
+ Pages:
+ DOI:
+ PMID:
+ URL:
+ eprint:
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..053abcf
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,37 @@
+version=3
+
+# Uncomment to examine a Webpage
+# <Webpage URL> <string match>
+#http://www.example.com/downloads.php #PACKAGE#-(.*)\.tar\.gz
+
+# Uncomment to examine a Webserver directory
+#http://www.example.com/pub/#PACKAGE#-(.*)\.tar\.gz
+
+# Uncommment to examine a FTP server
+#ftp://ftp.example.com/pub/#PACKAGE#-(.*)\.tar\.gz debian uupdate
+
+# Uncomment to find new files on sourceforge
+# http://sf.net/#PACKAGE#/#PACKAGE#-(\d[\d\.]+)\.(?:tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz)))
+
+# Uncomment to find new files on GooglePages
+# http://code.google.com/p/#PACKAGE#/downloads/list?can=1 \
+# .*/#PACKAGE#-([-.\d]+)\.(?:tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))|zip)
+
+# Uncomment to find new files on Github
+# - when using releases:
+# https://github.com/#GITHUBUSER#/#PACKAGE#/releases .*/archive/#PREFIX#(\d[\d.-]+)\.(?:tar(?:\.gz|\.bz2)?|tgz)
+# - when using tags
+# https://github.com/#GITHUBUSER#/#PACKAGE#/tags .*/#PREFIX#(\d.*)\.(?:tgz|tbz2|txz|tar\.(?:gz|bz2|xz))
+# Remark: frequently you can do s/#PREFIX#/v?/ since 'v' or nothing is quite common but there are other prefixes possible
+
+# PyPi repository of Python modules
+# see https://lists.debian.org/debian-python/2015/02/msg00027.html
+# http://pypi.debian.net/#module#/#module#-(.+)\.(?:tar(?:\.gz|\.bz2)?|tgz)
+
+# if tweaking of source is needed
+# \
+# debian debian/get-orig-source
+
+# if you need to repack and choose +dfsg prefix
+# opts=dversionmangle=s/[~\+]dfsg[0-9]*// \
+#
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/libjung-java.git
More information about the debian-med-commit
mailing list