hzzz 7 years ago
parent
commit
8282108423
  1. 6
      build.third_step1.gradle
  2. 167
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ArrayStack.java
  3. 221
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Bag.java
  4. 273
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/BagUtils.java
  5. 144
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/BidiMap.java
  6. 50
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/BoundedCollection.java
  7. 45
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/BoundedMap.java
  8. 44
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Closure.java
  9. 386
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ClosureUtils.java
  10. 1894
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/CollectionUtils.java
  11. 239
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ComparatorUtils.java
  12. 97
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/EnumerationUtils.java
  13. 45
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Equator.java
  14. 44
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Factory.java
  15. 154
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/FactoryUtils.java
  16. 505
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/FluentIterable.java
  17. 72
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/FunctorException.java
  18. 77
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Get.java
  19. 47
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/IterableGet.java
  20. 43
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/IterableMap.java
  21. 31
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/IterableSortedMap.java
  22. 1088
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/IterableUtils.java
  23. 1528
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/IteratorUtils.java
  24. 47
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/KeyValue.java
  25. 709
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ListUtils.java
  26. 67
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ListValuedMap.java
  27. 109
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MapIterator.java
  28. 1811
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MapUtils.java
  29. 158
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MultiMap.java
  30. 259
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MultiMapUtils.java
  31. 272
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MultiSet.java
  32. 123
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MultiSetUtils.java
  33. 320
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MultiValuedMap.java
  34. 51
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/OrderedBidiMap.java
  35. 47
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/OrderedIterator.java
  36. 73
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/OrderedMap.java
  37. 46
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/OrderedMapIterator.java
  38. 49
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Predicate.java
  39. 562
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/PredicateUtils.java
  40. 55
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Put.java
  41. 111
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/QueueUtils.java
  42. 38
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ResettableIterator.java
  43. 32
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ResettableListIterator.java
  44. 655
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/SetUtils.java
  45. 65
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/SetValuedMap.java
  46. 53
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/SortedBag.java
  47. 58
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/SortedBidiMap.java
  48. 250
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/SplitMapUtils.java
  49. 51
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Transformer.java
  50. 499
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/TransformerUtils.java
  51. 47
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Trie.java
  52. 50
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/TrieUtils.java
  53. 38
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Unmodifiable.java
  54. 98
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/AbstractBagDecorator.java
  55. 625
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/AbstractMapBag.java
  56. 82
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/AbstractSortedBagDecorator.java
  57. 243
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/CollectionBag.java
  58. 168
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/CollectionSortedBag.java
  59. 78
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/HashBag.java
  60. 126
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/PredicatedBag.java
  61. 108
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/PredicatedSortedBag.java
  62. 151
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/SynchronizedBag.java
  63. 108
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/SynchronizedSortedBag.java
  64. 150
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/TransformedBag.java
  65. 132
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/TransformedSortedBag.java
  66. 140
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/TreeBag.java
  67. 159
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/UnmodifiableBag.java
  68. 156
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/UnmodifiableSortedBag.java
  69. 39
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/package-info.java
  70. 89
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/AbstractBidiMapDecorator.java
  71. 806
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.java
  72. 92
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/AbstractOrderedBidiMapDecorator.java
  73. 93
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/AbstractSortedBidiMapDecorator.java
  74. 107
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/DualHashBidiMap.java
  75. 101
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/DualLinkedHashBidiMap.java
  76. 416
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/DualTreeBidiMap.java
  77. 2229
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/TreeBidiMap.java
  78. 136
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/UnmodifiableBidiMap.java
  79. 147
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/UnmodifiableOrderedBidiMap.java
  80. 158
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/UnmodifiableSortedBidiMap.java
  81. 41
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/package-info.java
  82. 178
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/AbstractCollectionDecorator.java
  83. 483
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/CompositeCollection.java
  84. 263
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/IndexedCollection.java
  85. 455
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/PredicatedCollection.java
  86. 232
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/SynchronizedCollection.java
  87. 156
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/TransformedCollection.java
  88. 168
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/UnmodifiableBoundedCollection.java
  89. 112
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/UnmodifiableCollection.java
  90. 36
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/package-info.java
  91. 192
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/BooleanComparator.java
  92. 130
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/ComparableComparator.java
  93. 349
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/ComparatorChain.java
  94. 299
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/FixedOrderComparator.java
  95. 182
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/NullComparator.java
  96. 125
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/ReverseComparator.java
  97. 133
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/TransformingComparator.java
  98. 28
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/package-info.java
  99. 56
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/functors/AbstractQuantifierPredicate.java
  100. 115
      fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/functors/AllPredicate.java
  101. Some files were not shown because too many files have changed in this diff Show More

6
build.third_step1.gradle

@ -31,8 +31,10 @@ sourceSets{
"${srcDir}/fine-poi/src",
"${srcDir}/fine-quartz/src",
"${srcDir}/fine-commons-io/src",
"${srcDir}/fine-commons-fileupload/src"
]
"${srcDir}/fine-commons-fileupload/src",
"${srcDir}/fine-commons-lang3/src",
"${srcDir}/fine-commons-collections4/src"
]
}
}

167
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ArrayStack.java

@ -0,0 +1,167 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
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.
* <p>
* Unlike <code>Stack</code>, <code>ArrayStack</code> accepts null entries.
* <p>
* <b>Note:</b> From version 4.0 onwards, this class does not implement the
* removed {@code Buffer} interface anymore.
*
* @see java.util.Stack
* @since 1.0
* @version $Id: ArrayStack.java 1477779 2013-04-30 18:55:24Z tn $
* @deprecated use {@link java.util.ArrayDeque} instead (available from Java 1.6)
*/
@Deprecated
public class ArrayStack<E> extends ArrayList<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(final 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 {
final 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(final int n) throws EmptyStackException {
final 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 {
final 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(final 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(final Object object) {
int i = size() - 1; // Current index
int n = 1; // Current distance
while (i >= 0) {
final Object current = get(i);
if ((object == null && current == null) ||
(object != null && object.equals(current))) {
return n;
}
i--;
n++;
}
return -1;
}
}

221
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Bag.java

@ -0,0 +1,221 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
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.
*
* @param <E> the type held in the bag
* @since 2.0
* @version $Id: Bag.java 1477779 2013-04-30 18:55:24Z tn $
*/
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(Object object);
/**
* <i>(Violation)</i>
* Adds one copy 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 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.
*
* @param object the object to remove
* @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(Object 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>&gt;= 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>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 &gt; 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>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();
}

273
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/BagUtils.java

@ -0,0 +1,273 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import com.fr.third.org.apache.commons.collections4.bag.CollectionBag;
import com.fr.third.org.apache.commons.collections4.bag.HashBag;
import com.fr.third.org.apache.commons.collections4.bag.PredicatedBag;
import com.fr.third.org.apache.commons.collections4.bag.PredicatedSortedBag;
import com.fr.third.org.apache.commons.collections4.bag.SynchronizedBag;
import com.fr.third.org.apache.commons.collections4.bag.SynchronizedSortedBag;
import com.fr.third.org.apache.commons.collections4.bag.TransformedBag;
import com.fr.third.org.apache.commons.collections4.bag.TransformedSortedBag;
import com.fr.third.org.apache.commons.collections4.bag.TreeBag;
import com.fr.third.org.apache.commons.collections4.bag.UnmodifiableBag;
import com.fr.third.org.apache.commons.collections4.bag.UnmodifiableSortedBag;
import com.fr.third.org.apache.commons.collections4.bag.CollectionBag;
import com.fr.third.org.apache.commons.collections4.bag.HashBag;
import com.fr.third.org.apache.commons.collections4.bag.PredicatedBag;
import com.fr.third.org.apache.commons.collections4.bag.PredicatedSortedBag;
import com.fr.third.org.apache.commons.collections4.bag.SynchronizedBag;
import com.fr.third.org.apache.commons.collections4.bag.SynchronizedSortedBag;
import com.fr.third.org.apache.commons.collections4.bag.TransformedBag;
import com.fr.third.org.apache.commons.collections4.bag.TransformedSortedBag;
import com.fr.third.org.apache.commons.collections4.bag.TreeBag;
import com.fr.third.org.apache.commons.collections4.bag.UnmodifiableBag;
import com.fr.third.org.apache.commons.collections4.bag.UnmodifiableSortedBag;
/**
* Provides utility methods and decorators for {@link Bag} and {@link SortedBag} instances.
*
* @since 2.1
* @version $Id: BagUtils.java 1686855 2015-06-22 13:00:27Z tn $
*/
public class BagUtils {
/**
* An empty unmodifiable bag.
*/
@SuppressWarnings("rawtypes") // OK, empty bag is compatible with any type
public static final Bag EMPTY_BAG = UnmodifiableBag.unmodifiableBag(new HashBag<Object>());
/**
* An empty unmodifiable sorted bag.
*/
@SuppressWarnings("rawtypes") // OK, empty bag is compatible with any type
public static final Bag EMPTY_SORTED_BAG =
UnmodifiableSortedBag.unmodifiableSortedBag(new TreeBag<Object>());
/**
* Instantiation of BagUtils is not intended or required.
*/
private 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:
*
* <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>
*
* Failure to follow this advice may result in non-deterministic behavior.
*
* @param <E> the element type
* @param bag the bag to synchronize, must not be null
* @return a synchronized bag backed by that bag
* @throws NullPointerException if the Bag is null
*/
public static <E> Bag<E> synchronizedBag(final Bag<E> bag) {
return SynchronizedBag.synchronizedBag(bag);
}
/**
* Returns an unmodifiable view of the given bag. Any modification attempts
* to the returned bag will raise an {@link UnsupportedOperationException}.
*
* @param <E> the element type
* @param bag the bag whose unmodifiable view is to be returned, must not be null
* @return an unmodifiable view of that bag
* @throws NullPointerException if the Bag is null
*/
public static <E> Bag<E> unmodifiableBag(final Bag<? extends E> bag) {
return UnmodifiableBag.unmodifiableBag(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 <E> the element type
* @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 NullPointerException if the Bag or Predicate is null
*/
public static <E> Bag<E> predicatedBag(final Bag<E> bag, final Predicate<? super E> predicate) {
return PredicatedBag.predicatedBag(bag, predicate);
}
/**
* 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.
* <p>
* Existing entries in the specified bag will not be transformed.
* If you want that behaviour, see {@link TransformedBag#transformedBag(Bag, Transformer)}.
*
* @param <E> the element type
* @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 NullPointerException if the Bag or Transformer is null
*/
public static <E> Bag<E> transformingBag(final Bag<E> bag, final Transformer<? super E, ? extends E> transformer) {
return TransformedBag.transformingBag(bag, transformer);
}
/**
* Returns a bag that complies to the Collection contract, backed by the given bag.
*
* @param <E> the element type
* @param bag the bag to decorate, must not be null
* @return a Bag that complies to the Collection contract
* @throws NullPointerException if bag is null
* @since 4.0
*/
public static <E> Bag<E> collectionBag(final Bag<E> bag) {
return CollectionBag.collectionBag(bag);
}
//-----------------------------------------------------------------------
/**
* 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:
*
* <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>
*
* Failure to follow this advice may result in non-deterministic behavior.
*
* @param <E> the element type
* @param bag the bag to synchronize, must not be null
* @return a synchronized bag backed by that bag
* @throws NullPointerException if the SortedBag is null
*/
public static <E> SortedBag<E> synchronizedSortedBag(final SortedBag<E> bag) {
return SynchronizedSortedBag.synchronizedSortedBag(bag);
}
/**
* Returns an unmodifiable view of the given sorted bag. Any modification
* attempts to the returned bag will raise an
* {@link UnsupportedOperationException}.
*
* @param <E> the element type
* @param bag the bag whose unmodifiable view is to be returned, must not be null
* @return an unmodifiable view of that bag
* @throws NullPointerException if the SortedBag is null
*/
public static <E> SortedBag<E> unmodifiableSortedBag(final SortedBag<E> bag) {
return UnmodifiableSortedBag.unmodifiableSortedBag(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 <E> the element type
* @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 NullPointerException if the SortedBag or Predicate is null
*/
public static <E> SortedBag<E> predicatedSortedBag(final SortedBag<E> bag,
final Predicate<? super E> predicate) {
return PredicatedSortedBag.predicatedSortedBag(bag, predicate);
}
/**
* 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.
* <p>
* Existing entries in the specified bag will not be transformed.
* If you want that behaviour, see
* {@link TransformedSortedBag#transformedSortedBag(SortedBag, Transformer)}.
*
* @param <E> the element type
* @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 NullPointerException if the Bag or Transformer is null
*/
public static <E> SortedBag<E> transformingSortedBag(final SortedBag<E> bag,
final Transformer<? super E, ? extends E> transformer) {
return TransformedSortedBag.transformingSortedBag(bag, transformer);
}
/**
* Get an empty <code>Bag</code>.
*
* @param <E> the element type
* @return an empty Bag
*/
@SuppressWarnings("unchecked") // OK, empty bag is compatible with any type
public static <E> Bag<E> emptyBag() {
return (Bag<E>) EMPTY_BAG;
}
/**
* Get an empty <code>SortedBag</code>.
*
* @param <E> the element type
* @return an empty sorted Bag
*/
@SuppressWarnings("unchecked") // OK, empty bag is compatible with any type
public static <E> SortedBag<E> emptySortedBag() {
return (SortedBag<E>) EMPTY_SORTED_BAG;
}
}

144
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/BidiMap.java

@ -0,0 +1,144 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
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.
*
* @param <K> the type of the keys in the map
* @param <V> the type of the values in the map
*
* @since 3.0
* @version $Id: BidiMap.java 1612021 2014-07-20 04:51:05Z ggregory $
*/
public interface BidiMap<K, V> extends IterableMap<K, V> {
/**
* 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
*
* 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 {@link Set} view of the values 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
* {@code remove} operation), the results of the iteration are undefined.
* The set supports element removal, which removes the corresponding
* mapping from the map, via the {@code Iterator.remove},
* {@code Collection.remove}, {@code removeAll},
* {@code retainAll} and {@code clear} operations. It does not
* support the {@code add} or {@code addAll} operations.
*
* @return a set view of the values contained in this map
*/
Set<V> values();
}

50
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/BoundedCollection.java

@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
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.
*
* @see CollectionUtils#isFull
* @see CollectionUtils#maxSize
*
* @since 3.0
* @version $Id: BoundedCollection.java 1477779 2013-04-30 18:55:24Z tn $
*/
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();
}

45
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/BoundedMap.java

@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
/**
* 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.
*
* @since 3.0
* @version $Id: BoundedMap.java 1477779 2013-04-30 18:55:24Z tn $
*/
public interface BoundedMap<K, V> extends IterableMap<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();
}

44
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Closure.java

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
/**
* 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 invocation and for/while loops.
*
* @param <T> the type that the closure acts on
* @since 1.0
* @version $Id: Closure.java 1543261 2013-11-19 00:47:34Z ggregory $
*/
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
*/
void execute(T input);
}

386
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ClosureUtils.java

@ -0,0 +1,386 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Collection;
import java.util.Map;
import com.fr.third.org.apache.commons.collections4.functors.ChainedClosure;
import com.fr.third.org.apache.commons.collections4.functors.EqualPredicate;
import com.fr.third.org.apache.commons.collections4.functors.ExceptionClosure;
import com.fr.third.org.apache.commons.collections4.functors.ForClosure;
import com.fr.third.org.apache.commons.collections4.functors.IfClosure;
import com.fr.third.org.apache.commons.collections4.functors.InvokerTransformer;
import com.fr.third.org.apache.commons.collections4.functors.NOPClosure;
import com.fr.third.org.apache.commons.collections4.functors.SwitchClosure;
import com.fr.third.org.apache.commons.collections4.functors.TransformerClosure;
import com.fr.third.org.apache.commons.collections4.functors.WhileClosure;
import com.fr.third.org.apache.commons.collections4.functors.ChainedClosure;
import com.fr.third.org.apache.commons.collections4.functors.EqualPredicate;
import com.fr.third.org.apache.commons.collections4.functors.ExceptionClosure;
import com.fr.third.org.apache.commons.collections4.functors.ForClosure;
import com.fr.third.org.apache.commons.collections4.functors.IfClosure;
import com.fr.third.org.apache.commons.collections4.functors.InvokerTransformer;
import com.fr.third.org.apache.commons.collections4.functors.NOPClosure;
import com.fr.third.org.apache.commons.collections4.functors.SwitchClosure;
import com.fr.third.org.apache.commons.collections4.functors.TransformerClosure;
import com.fr.third.org.apache.commons.collections4.functors.WhileClosure;
/**
* <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>Chained - chains two or more closures together
* <li>If - calls one closure or another based on a predicate
* <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>
* <p>
* Since v4.1 only closures which are considered to be unsafe are
* Serializable. Closures considered to be unsafe for serialization are:
* <ul>
* <li>Invoker
* <li>For
* <li>While
* </ul>
*
* @since 3.0
* @version $Id: ClosureUtils.java 1714362 2015-11-14 20:38:02Z tn $
*/
public class ClosureUtils {
/**
* This class is not normally instantiated.
*/
private ClosureUtils() {}
/**
* Gets a Closure that always throws an exception.
* This could be useful during testing as a placeholder.
*
* @see ExceptionClosure
*
* @param <E> the type that the closure acts on
* @return the closure
*/
public static <E> Closure<E> exceptionClosure() {
return ExceptionClosure.<E>exceptionClosure();
}
/**
* Gets a Closure that will do nothing.
* This could be useful during testing as a placeholder.
*
* @see NOPClosure
*
* @param <E> the type that the closure acts on
* @return the closure
*/
public static <E> Closure<E> nopClosure() {
return NOPClosure.<E>nopClosure();
}
/**
* 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.
*
* @see TransformerClosure
*
* @param <E> the type that the closure acts on
* @param transformer the transformer to run each time in the closure, null means nop
* @return the closure
*/
public static <E> Closure<E> asClosure(final Transformer<? super E, ?> transformer) {
return TransformerClosure.transformerClosure(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>.
*
* @see ForClosure
*
* @param <E> the type that the closure acts on
* @param count the number of times to loop
* @param closure the closure to call repeatedly
* @return the <code>for</code> closure
*/
public static <E> Closure<E> forClosure(final int count, final Closure<? super E> closure) {
return ForClosure.forClosure(count, closure);
}
/**
* Creates a Closure that will call the closure repeatedly until the
* predicate returns false.
*
* @see WhileClosure
*
* @param <E> the type that the closure acts on
* @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 NullPointerException if either argument is null
*/
public static <E> Closure<E> whileClosure(final Predicate<? super E> predicate, final Closure<? super E> closure) {
return WhileClosure.<E>whileClosure(predicate, closure, false);
}
/**
* Creates a Closure that will call the closure once and then repeatedly
* until the predicate returns false.
*
* @see WhileClosure
*
* @param <E> the type that the closure acts on
* @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 NullPointerException if either argument is null
*/
public static <E> Closure<E> doWhileClosure(final Closure<? super E> closure,
final Predicate<? super E> predicate) {
return WhileClosure.<E>whileClosure(predicate, closure, true);
}
/**
* Creates a Closure that will invoke a specific method on the closure's
* input object by reflection.
*
* @see InvokerTransformer
* @see TransformerClosure
*
* @param <E> the type that the closure acts on
* @param methodName the name of the method
* @return the <code>invoker</code> closure
* @throws NullPointerException if the method name is null
*/
public static <E> Closure<E> invokerClosure(final String methodName) {
// reuse transformer as it has caching - this is lazy really, should have inner class here
return asClosure(InvokerTransformer.<E, Object>invokerTransformer(methodName));
}
/**
* Creates a Closure that will invoke a specific method on the closure's
* input object by reflection.
*
* @see InvokerTransformer
* @see TransformerClosure
*
* @param <E> the type that the closure acts on
* @param methodName the name of the method
* @param paramTypes the parameter types
* @param args the arguments
* @return the <code>invoker</code> closure
* @throws NullPointerException if the method name is null
* @throws IllegalArgumentException if the paramTypes and args don't match
*/
public static <E> Closure<E> invokerClosure(final String methodName, final Class<?>[] paramTypes,
final Object[] args) {
// reuse transformer as it has caching - this is lazy really, should have inner class here
return asClosure(InvokerTransformer.<E, Object>invokerTransformer(methodName, paramTypes, args));
}
/**
* Create a new Closure that calls each closure in turn, passing the
* result into the next closure.
*
* @see ChainedClosure
*
* @param <E> the type that the closure acts on
* @param closures an array of closures to chain
* @return the <code>chained</code> closure
* @throws NullPointerException if the closures array is null
* @throws NullPointerException if any closure in the array is null
*/
public static <E> Closure<E> chainedClosure(final Closure<? super E>... closures) {
return ChainedClosure.chainedClosure(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.
*
* @see ChainedClosure
*
* @param <E> the type that the closure acts on
* @param closures a collection of closures to chain
* @return the <code>chained</code> closure
* @throws NullPointerException if the closures collection is null
* @throws NullPointerException if any closure in the collection is null
* @throws IllegalArgumentException if the closures collection is empty
*/
public static <E> Closure<E> chainedClosure(final Collection<? extends Closure<? super E>> closures) {
return ChainedClosure.chainedClosure(closures);
}
/**
* Create a new Closure that calls another closure based on the
* result of the specified predicate.
*
* @see IfClosure
*
* @param <E> the type that the closure acts on
* @param predicate the validating predicate
* @param trueClosure the closure called if the predicate is true
* @return the <code>if</code> closure
* @throws NullPointerException if the predicate or closure is null
* @since 3.2
*/
public static <E> Closure<E> ifClosure(final Predicate<? super E> predicate,
final Closure<? super E> trueClosure) {
return IfClosure.<E>ifClosure(predicate, trueClosure);
}
/**
* Create a new Closure that calls one of two closures depending
* on the specified predicate.
*
* @see IfClosure
*
* @param <E> the type that the closure acts on
* @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 NullPointerException if the predicate or either closure is null
*/
public static <E> Closure<E> ifClosure(final Predicate<? super E> predicate,
final Closure<? super E> trueClosure,
final Closure<? super E> falseClosure) {
return IfClosure.<E>ifClosure(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.
*
* @see SwitchClosure
*
* @param <E> the type that the closure acts on
* @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 NullPointerException if the either array is null
* @throws NullPointerException if any element in the arrays is null
* @throws IllegalArgumentException if the arrays have different sizes
*/
public static <E> Closure<E> switchClosure(final Predicate<? super E>[] predicates,
final Closure<? super E>[] closures) {
return SwitchClosure.<E>switchClosure(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.
*
* @see SwitchClosure
*
* @param <E> the type that the closure acts on
* @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 NullPointerException if the either array is null
* @throws NullPointerException if any element in the arrays is null
* @throws IllegalArgumentException if the arrays are different sizes
*/
public static <E> Closure<E> switchClosure(final Predicate<? super E>[] predicates,
final Closure<? super E>[] closures,
final Closure<? super E> defaultClosure) {
return SwitchClosure.<E>switchClosure(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.
*
* @see SwitchClosure
*
* @param <E> the type that the closure acts on
* @param predicatesAndClosures a map of predicates to closures
* @return the <code>switch</code> closure
* @throws NullPointerException if the map is null
* @throws NullPointerException if any closure in the map is null
* @throws IllegalArgumentException if the map is empty
* @throws ClassCastException if the map elements are of the wrong type
*/
public static <E> Closure<E> switchClosure(final Map<Predicate<E>, Closure<E>> predicatesAndClosures) {
return SwitchClosure.switchClosure(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.
*
* @see SwitchClosure
*
* @param <E> the type that the closure acts on
* @param objectsAndClosures a map of objects to closures
* @return the closure
* @throws NullPointerException if the map is null
* @throws NullPointerException if any closure in the map is null
* @throws IllegalArgumentException if the map is empty
*/
@SuppressWarnings("unchecked")
public static <E> Closure<E> switchMapClosure(final Map<? extends E, Closure<E>> objectsAndClosures) {
if (objectsAndClosures == null) {
throw new NullPointerException("The object and closure map must not be null");
}
final Closure<? super E> def = objectsAndClosures.remove(null);
final int size = objectsAndClosures.size();
final Closure<? super E>[] trs = new Closure[size];
final Predicate<E>[] preds = new Predicate[size];
int i = 0;
for (final Map.Entry<? extends E, Closure<E>> entry : objectsAndClosures.entrySet()) {
preds[i] = EqualPredicate.<E>equalPredicate(entry.getKey());
trs[i] = entry.getValue();
i++;
}
return ClosureUtils.<E>switchClosure(preds, trs, def);
}
}

1894
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/CollectionUtils.java

File diff suppressed because it is too large Load Diff

239
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ComparatorUtils.java

@ -0,0 +1,239 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Collection;
import java.util.Comparator;
import com.fr.third.org.apache.commons.collections4.comparators.BooleanComparator;
import com.fr.third.org.apache.commons.collections4.comparators.ComparableComparator;
import com.fr.third.org.apache.commons.collections4.comparators.ComparatorChain;
import com.fr.third.org.apache.commons.collections4.comparators.NullComparator;
import com.fr.third.org.apache.commons.collections4.comparators.ReverseComparator;
import com.fr.third.org.apache.commons.collections4.comparators.TransformingComparator;
/**
* 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.
*
* @since 2.1
* @version $Id: ComparatorUtils.java 1591832 2014-05-02 08:58:40Z tn $
*/
public class ComparatorUtils {
/**
* ComparatorUtils should not normally be instantiated.
*/
private ComparatorUtils() {}
/**
* Comparator for natural sort order.
*
* @see ComparableComparator#comparableComparator()
*/
@SuppressWarnings({ "rawtypes", "unchecked" }) // explicit type needed for Java 1.5 compilation
public static final Comparator NATURAL_COMPARATOR = ComparableComparator.<Comparable>comparableComparator();
/**
* Gets a comparator that uses the natural order of the objects.
*
* @param <E> the object type to compare
* @return a comparator which uses natural order
*/
@SuppressWarnings("unchecked")
public static <E extends Comparable<? super E>> Comparator<E> naturalComparator() {
return NATURAL_COMPARATOR;
}
/**
* 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 <E> the object type to compare
* @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 <E> Comparator<E> chainedComparator(final Comparator<E>... comparators) {
final ComparatorChain<E> chain = new ComparatorChain<E>();
for (final Comparator<E> comparator : comparators) {
if (comparator == null) {
throw new NullPointerException("Comparator cannot be null");
}
chain.addComparator(comparator);
}
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 <E> the object type to compare
* @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
*/
@SuppressWarnings("unchecked")
public static <E> Comparator<E> chainedComparator(final Collection<Comparator<E>> comparators) {
return chainedComparator(
(Comparator<E>[]) comparators.toArray(new Comparator[comparators.size()])
);
}
/**
* Gets a comparator that reverses the order of the given comparator.
*
* @param <E> the object type to compare
* @param comparator the comparator to reverse
* @return a comparator that reverses the order of the input comparator
* @see ReverseComparator
*/
public static <E> Comparator<E> reversedComparator(final Comparator<E> comparator) {
return new ReverseComparator<E>(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(final boolean trueFirst) {
return BooleanComparator.booleanComparator(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 <E> the object type to compare
* @param comparator the comparator that wants to allow nulls
* @return a version of that comparator that allows nulls
* @see NullComparator
*/
@SuppressWarnings("unchecked")
public static <E> Comparator<E> nullLowComparator(Comparator<E> comparator) {
if (comparator == null) {
comparator = NATURAL_COMPARATOR;
}
return new NullComparator<E>(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 <E> the object type to compare
* @param comparator the comparator that wants to allow nulls
* @return a version of that comparator that allows nulls
* @see NullComparator
*/
@SuppressWarnings("unchecked")
public static <E> Comparator<E> nullHighComparator(Comparator<E> comparator) {
if (comparator == null) {
comparator = NATURAL_COMPARATOR;
}
return new NullComparator<E>(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 <I> the input object type of the transformed comparator
* @param <O> the object type of the decorated 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
*/
@SuppressWarnings("unchecked")
public static <I, O> Comparator<I> transformedComparator(Comparator<O> comparator,
final Transformer<? super I, ? extends O> transformer) {
if (comparator == null) {
comparator = NATURAL_COMPARATOR;
}
return new TransformingComparator<I, O>(transformer, comparator);
}
/**
* Returns the smaller of the given objects according to the given
* comparator, returning the second object if the comparator
* returns equal.
*
* @param <E> the object type to compare
* @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
*/
@SuppressWarnings("unchecked")
public static <E> E min(final E o1, final E o2, Comparator<E> comparator) {
if (comparator == null) {
comparator = NATURAL_COMPARATOR;
}
final 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 <E> the object type to compare
* @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
*/
@SuppressWarnings("unchecked")
public static <E> E max(final E o1, final E o2, Comparator<E> comparator) {
if (comparator == null) {
comparator = NATURAL_COMPARATOR;
}
final int c = comparator.compare(o1, o2);
return c > 0 ? o1 : o2;
}
}

97
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/EnumerationUtils.java

@ -0,0 +1,97 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.StringTokenizer;
import com.fr.third.org.apache.commons.collections4.iterators.EnumerationIterator;
/**
* Provides utility methods for {@link Enumeration} instances.
*
* @since 3.0
* @version $Id: EnumerationUtils.java 1683009 2015-06-01 21:53:01Z tn $
*/
public class EnumerationUtils {
/**
* EnumerationUtils is not normally instantiated.
*/
private EnumerationUtils() {}
/**
* Returns the <code>index</code>-th value in the {@link Enumeration}, throwing
* <code>IndexOutOfBoundsException</code> if there is no such element.
* <p>
* The 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.
*
* @param e the enumeration to get a value from
* @param index the index to get
* @param <T> the type of object in the {@link Enumeration}
* @return the object at the specified index
* @throws IndexOutOfBoundsException if the index is invalid
* @throws IllegalArgumentException if the object type is invalid
* @since 4.1
*/
public static <T> T get(final Enumeration<T> e, final int index) {
int i = index;
CollectionUtils.checkIndexBounds(i);
while (e.hasMoreElements()) {
i--;
if (i == -1) {
return e.nextElement();
} else {
e.nextElement();
}
}
throw new IndexOutOfBoundsException("Entry does not exist: " + i);
}
/**
* Creates a list based on an enumeration.
*
* <p>As the enumeration is traversed, an ArrayList of its values is
* created. The new list is returned.</p>
*
* @param <E> the element type
* @param enumeration the enumeration to traverse, which should not be <code>null</code>.
* @return a list containing all elements of the given enumeration
* @throws NullPointerException if the enumeration parameter is <code>null</code>.
*/
public static <E> List<E> toList(final Enumeration<? extends E> enumeration) {
return IteratorUtils.toList(new EnumerationIterator<E>(enumeration));
}
/**
* Override toList(Enumeration) for StringTokenizer as it implements Enumeration&lt;Object&gt;
* for the sake of backward compatibility.
*
* @param stringTokenizer the tokenizer to convert to a {@link List}&lt;{@link String}&gt;
* @return a list containing all tokens of the given StringTokenizer
*/
public static List<String> toList(final StringTokenizer stringTokenizer) {
final List<String> result = new ArrayList<String>(stringTokenizer.countTokens());
while (stringTokenizer.hasMoreTokens()) {
result.add(stringTokenizer.nextToken());
}
return result;
}
}

45
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Equator.java

@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable
* law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import com.fr.third.org.apache.commons.collections4.map.HashedMap;
/**
* An equation function, which determines equality between objects of type T.
* <p>
* It is the functional sibling of {@link java.util.Comparator}; {@link Equator} is to
* {@link Object} as {@link java.util.Comparator} is to {@link java.lang.Comparable}.
*
* @param <T> the types of object this {@link Equator} can evaluate.
* @since 4.0
* @version $Id: Equator.java 1540567 2013-11-10 22:19:29Z tn $
*/
public interface Equator<T> {
/**
* Evaluates the two arguments for their equality.
*
* @param o1 the first object to be equated.
* @param o2 the second object to be equated.
* @return whether the two objects are equal.
*/
boolean equate(T o1, T o2);
/**
* Calculates the hash for the object, based on the method of equality used in the equate
* method. This is used for classes that delegate their {@link Object#equals(Object) equals(Object)} method to an
* Equator (and so must also delegate their {@link Object#hashCode() hashCode()} method), or for implementations
* of {@link HashedMap} that use an Equator for the key objects.
*
* @param o the object to calculate the hash for.
* @return the hash of the object.
*/
int hash(T o);
}

44
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Factory.java

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
/**
* 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.
*
* @param <T> the type that the factory creates
*
* @since 2.1
* @version $Id: Factory.java 1543256 2013-11-19 00:45:38Z ggregory $
*/
public interface Factory<T> {
/**
* Create a new object.
*
* @return a new object
* @throws FunctorException (runtime) if the factory cannot create an object
*/
T create();
}

154
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/FactoryUtils.java

@ -0,0 +1,154 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import com.fr.third.org.apache.commons.collections4.functors.ConstantFactory;
import com.fr.third.org.apache.commons.collections4.functors.ExceptionFactory;
import com.fr.third.org.apache.commons.collections4.functors.InstantiateFactory;
import com.fr.third.org.apache.commons.collections4.functors.PrototypeFactory;
import com.fr.third.org.apache.commons.collections4.functors.ConstantFactory;
import com.fr.third.org.apache.commons.collections4.functors.ExceptionFactory;
import com.fr.third.org.apache.commons.collections4.functors.InstantiateFactory;
import com.fr.third.org.apache.commons.collections4.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>Instantiate - creates objects using reflection
* <li>Constant - always returns the same object
* <li>Null - always returns null
* <li>Exception - always throws an exception
* </ul>
* <p>
* Since v4.1 only factories which are considered to be unsafe are
* Serializable. Factories considered to be unsafe for serialization are:
* <ul>
* <li>Prototype
* <li>Instantiate
* </ul>
*
* @since 3.0
* @version $Id: FactoryUtils.java 1714362 2015-11-14 20:38:02Z tn $
*/
public class FactoryUtils {
/**
* This class is not normally instantiated.
*/
private FactoryUtils() {}
/**
* Gets a Factory that always throws an exception.
* This could be useful during testing as a placeholder.
*
* @see ExceptionFactory
*
* @param <T> the type that the factory creates
* @return the factory
*/
public static <T> Factory<T> exceptionFactory() {
return ExceptionFactory.<T>exceptionFactory();
}
/**
* Gets a Factory that will return null each time the factory is used.
* This could be useful during testing as a placeholder.
*
* @see ConstantFactory
* @param <T> the "type" of null object the factory should return.
* @return the factory
*/
public static <T> Factory<T> nullFactory() {
return ConstantFactory.<T>constantFactory(null);
}
/**
* 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.
*
* @see ConstantFactory
*
* @param <T> the type that the factory creates
* @param constantToReturn the constant object to return each time in the factory
* @return the <code>constant</code> factory.
*/
public static <T> Factory<T> constantFactory(final T constantToReturn) {
return ConstantFactory.constantFactory(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>
*
* @see PrototypeFactory
*
* @param <T> the type that the factory creates
* @param prototype the object to clone each time in the factory
* @return the <code>prototype</code> factory, or a {@link ConstantFactory#NULL_INSTANCE} if
* the {@code prototype} is {@code null}
* @throws IllegalArgumentException if the prototype cannot be cloned
*/
public static <T> Factory<T> prototypeFactory(final T prototype) {
return PrototypeFactory.<T>prototypeFactory(prototype);
}
/**
* Creates a Factory that can create objects of a specific type using
* a no-args constructor.
*
* @see InstantiateFactory
*
* @param <T> the type that the factory creates
* @param classToInstantiate the Class to instantiate each time in the factory
* @return the <code>reflection</code> factory
* @throws NullPointerException if the classToInstantiate is null
*/
public static <T> Factory<T> instantiateFactory(final Class<T> classToInstantiate) {
return InstantiateFactory.instantiateFactory(classToInstantiate, null, null);
}
/**
* Creates a Factory that can create objects of a specific type using
* the arguments specified to this method.
*
* @see InstantiateFactory
*
* @param <T> the type that the factory creates
* @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 NullPointerException if the classToInstantiate is null
* @throws IllegalArgumentException if the paramTypes and args don't match
* @throws IllegalArgumentException if the constructor doesn't exist
*/
public static <T> Factory<T> instantiateFactory(final Class<T> classToInstantiate, final Class<?>[] paramTypes,
final Object[] args) {
return InstantiateFactory.instantiateFactory(classToInstantiate, paramTypes, args);
}
}

505
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/FluentIterable.java

@ -0,0 +1,505 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import com.fr.third.org.apache.commons.collections4.iterators.SingletonIterator;
/**
* A FluentIterable provides a powerful yet simple API for manipulating
* Iterable instances in a fluent manner.
* <p>
* A FluentIterable can be created either from an Iterable or from a set
* of elements. The following types of methods are provided:
* <ul>
* <li>fluent methods which return a new {@code FluentIterable} instance,
* providing a view of the original iterable (e.g. filter(Predicate));
* <li>conversion methods which copy the FluentIterable's contents into a
* new collection or array (e.g. toList());
* <li>utility methods which answer questions about the FluentIterable's
* contents (e.g. size(), anyMatch(Predicate)).
* <li>
* </ul>
* <p>
* The following example outputs the first 3 even numbers in the range [1, 10]
* into a list:
* <pre>
* List&lt;String&gt; result =
* FluentIterable
* .of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
* .filter(new Predicate<Integer>() {
* public boolean evaluate(Integer number) {
* return number % 2 == 0;
* }
* )
* .transform(TransformerUtils.stringValueTransformer())
* .limit(3)
* .toList();
* </pre>
* The resulting list will contain the following elements:
* <pre>[2, 4, 6]</pre>
*
* @param <E> the element type
* @since 4.1
* @version $Id: FluentIterable.java 1684264 2015-06-08 20:06:29Z tn $
*/
public class FluentIterable<E> implements Iterable<E> {
/** A reference to the wrapped iterable. */
private final Iterable<E> iterable;
// Static factory methods
// ----------------------------------------------------------------------
/**
* Creates a new empty FluentIterable.
*
* @param <T> the element type
* @return a new empty FluentIterable
*/
@SuppressWarnings("unchecked")
public static <T> FluentIterable<T> empty() {
return IterableUtils.EMPTY_ITERABLE;
}
/**
* Creates a new FluentIterable of the single provided element.
* <p>
* The returned iterable's iterator does not support {@code remove()}.
*
* @param <T> the element type
* @param singleton the singleton element
* @return a new FluentIterable containing the singleton
*/
public static <T> FluentIterable<T> of(final T singleton) {
return of(IteratorUtils.asIterable(new SingletonIterator<T>(singleton, false)));
}
/**
* Creates a new FluentIterable from the provided elements.
* <p>
* The returned iterable's iterator does not support {@code remove()}.
*
* @param <T> the element type
* @param elements the elements to be contained in the FluentIterable
* @return a new FluentIterable containing the provided elements
*/
public static <T> FluentIterable<T> of(final T... elements) {
return of(Arrays.asList(elements));
}
/**
* Construct a new FluentIterable from the provided iterable. If the
* iterable is already an instance of FluentIterable, the instance
* will be returned instead.
* <p>
* The returned iterable's iterator supports {@code remove()} when the
* corresponding input iterator supports it.
*
* @param <T> the element type
* @param iterable the iterable to wrap into a FluentIterable, may not be null
* @return a new FluentIterable wrapping the provided iterable
* @throws NullPointerException if iterable is null
*/
public static <T> FluentIterable<T> of(final Iterable<T> iterable) {
IterableUtils.checkNotNull(iterable);
if (iterable instanceof FluentIterable<?>) {
return (FluentIterable<T>) iterable;
} else {
return new FluentIterable<T>(iterable);
}
}
// Constructor
// ----------------------------------------------------------------------
/**
* Package-private constructor, used by IterableUtils.
*/
FluentIterable() {
this.iterable = this;
}
/**
* Create a new FluentIterable by wrapping the provided iterable.
* @param iterable the iterable to wrap
*/
private FluentIterable(final Iterable<E> iterable) {
this.iterable = iterable;
}
// fluent construction methods
// ----------------------------------------------------------------------
/**
* Returns a new FluentIterable whose iterator will first traverse
* the elements of the current iterable, followed by the provided
* elements.
*
* @param elements the elements to append to the iterable
* @return a new iterable, combining this iterable with the elements
*/
public FluentIterable<E> append(final E... elements) {
return append(Arrays.asList(elements));
}
/**
* Returns a new FluentIterable whose iterator will first traverse
* the elements of the current iterable, followed by the elements
* of the provided iterable.
*
* @param other the other iterable to combine, may not be null
* @return a new iterable, combining this iterable with other
* @throws NullPointerException if other is null
*/
public FluentIterable<E> append(final Iterable<? extends E> other) {
return of(IterableUtils.chainedIterable(iterable, other));
}
/**
* Returns a new FluentIterable whose iterator will traverse the
* elements of the current and provided iterable in natural order.
* <p>
* Example: natural ordering
* <ul>
* <li>this contains elements [1, 3, 5, 7]
* <li>other contains elements [2, 4, 6, 8]
* </ul>
* <p>
* The returned iterable will traverse the elements in the following
* order: [1, 2, 3, 4, 5, 6, 7, 8]
*
* @param other the other iterable to collate, may not be null
* @return a new iterable, collating this iterable with the other in natural order
* @throws NullPointerException if other is null
* @see {@link org.apache.commons.collections4.iterators.CollatingIterator CollatingIterator}
*/
public FluentIterable<E> collate(final Iterable<? extends E> other) {
return of(IterableUtils.collatedIterable(iterable, other));
}
/**
* Returns a new FluentIterable whose iterator will traverse the
* elements of the current and provided iterable according to the
* ordering defined by an comparator.
* <p>
* Example: descending order
* <ul>
* <li>this contains elements [7, 5, 3, 1]
* <li>other contains elements [8, 6, 4, 2]
* </ul>
* <p>
* The returned iterable will traverse the elements in the following
* order: [8, 7, 6, 5, 4, 3, 2, 1]
*
* @param comparator the comparator to define an ordering, may be null,
* in which case natural ordering will be used
* @param other the other iterable to collate, may not be null
* @return a new iterable, collating this iterable with the other in natural order
* @throws NullPointerException if other is null
* @see {@link org.apache.commons.collections4.iterators.CollatingIterator CollatingIterator}
*/
public FluentIterable<E> collate(final Iterable<? extends E> other,
final Comparator<? super E> comparator) {
return of(IterableUtils.collatedIterable(comparator, iterable, other));
}
/**
* This method fully traverses an iterator of this iterable and returns
* a new iterable with the same contents, but without any reference
* to the originating iterables and/or iterators.
* <p>
* Calling this method is equivalent to:
* <pre>
* FluentIterable<E> someIterable = ...;
* FluentIterable.of(someIterable.toList());
* </pre>
*
* @return a new iterable with the same contents as this iterable
*/
public FluentIterable<E> eval() {
return of(toList());
}
/**
* Returns a new FluentIterable whose iterator will only return
* elements from this iterable matching the provided predicate.
*
* @param predicate the predicate used to filter elements
* @return a new iterable, providing a filtered view of this iterable
* @throws NullPointerException if predicate is null
*/
public FluentIterable<E> filter(final Predicate<? super E> predicate) {
return of(IterableUtils.filteredIterable(iterable, predicate));
}
/**
* Returns a new FluentIterable whose iterator will return at most
* the provided maximum number of elements from this iterable.
*
* @param maxSize the maximum number of elements
* @return a new iterable, providing a bounded view of this iterable
* @throws IllegalArgumentException if maxSize is negative
*/
public FluentIterable<E> limit(final long maxSize) {
return of(IterableUtils.boundedIterable(iterable, maxSize));
}
/**
* Returns a new FluentIterable whose iterator will loop infinitely
* over the elements from this iterable.
*
* @return a new iterable, providing a looping view of this iterable
*/
public FluentIterable<E> loop() {
return of(IterableUtils.loopingIterable(iterable));
}
/**
* Returns a new FluentIterable whose iterator will traverse the
* elements from this iterable in reverse order.
*
* @return a new iterable, providing a reversed view of this iterable
*/
public FluentIterable<E> reverse() {
return of(IterableUtils.reversedIterable(iterable));
}
/**
* Returns a new FluentIterable whose iterator will skip the first
* N elements from this iterable.
*
* @param elementsToSkip the number of elements to skip
* @return a new iterable, providing a view of this iterable by skipping
* the first N elements
* @throws IllegalArgumentException if elementsToSkip is negative
*/
public FluentIterable<E> skip(final long elementsToSkip) {
return of(IterableUtils.skippingIterable(iterable, elementsToSkip));
}
/**
* Returns a new FluentIterable whose iterator will return all elements
* of this iterable transformed by the provided transformer.
*
* @param <O> the output element type
* @param transformer the transformer applied to each element
* @return a new iterable, providing a transformed view of this iterable
* @throws NullPointerException if transformer is null
*/
public <O> FluentIterable<O> transform(final Transformer<? super E, ? extends O> transformer) {
return of(IterableUtils.transformedIterable(iterable, transformer));
}
/**
* Returns a new FluentIterable whose iterator will return a unique view
* of this iterable.
*
* @return a new iterable, providing a unique view of this iterable
*/
public FluentIterable<E> unique() {
return of(IterableUtils.uniqueIterable(iterable));
}
/**
* Returns a new FluentIterable whose iterator will return an unmodifiable
* view of this iterable.
*
* @return a new iterable, providing an unmodifiable view of this iterable
*/
public FluentIterable<E> unmodifiable() {
return of(IterableUtils.unmodifiableIterable(iterable));
}
/**
* Returns a new FluentIterable whose iterator will traverse
* the elements of this iterable and the other iterable in
* alternating order.
*
* @param other the other iterable to interleave, may not be null
* @return a new iterable, interleaving this iterable with others
* @throws NullPointerException if other is null
*/
public FluentIterable<E> zip(final Iterable<? extends E> other) {
return of(IterableUtils.zippingIterable(iterable, other));
}
/**
* Returns a new FluentIterable whose iterator will traverse
* the elements of this iterable and the other iterables in
* alternating order.
*
* @param others the iterables to interleave, may not be null
* @return a new iterable, interleaving this iterable with others
* @throws NullPointerException if either of the provided iterables is null
*/
public FluentIterable<E> zip(final Iterable<? extends E>... others) {
return of(IterableUtils.zippingIterable(iterable, others));
}
// convenience methods
// ----------------------------------------------------------------------
/** {@inheritDoc} */
@Override
public Iterator<E> iterator() {
return iterable.iterator();
}
/**
* Returns an Enumeration that will enumerate all elements contained
* in this iterable.
*
* @return an Enumeration over the elements of this iterable
*/
public Enumeration<E> asEnumeration() {
return IteratorUtils.asEnumeration(iterator());
}
/**
* Checks if all elements contained in this iterable are matching the
* provided predicate.
* <p>
* A <code>null</code> or empty iterable returns true.
*
* @param predicate the predicate to use, may not be null
* @return true if all elements contained in this iterable match the predicate,
* false otherwise
* @throws NullPointerException if predicate is null
*/
public boolean allMatch(final Predicate<? super E> predicate) {
return IterableUtils.matchesAll(iterable, predicate);
}
/**
* Checks if this iterable contains any element matching the provided predicate.
* <p>
* A <code>null</code> or empty iterable returns false.
*
* @param predicate the predicate to use, may not be null
* @return true if at least one element contained in this iterable matches the predicate,
* false otherwise
* @throws NullPointerException if predicate is null
*/
public boolean anyMatch(final Predicate<? super E> predicate) {
return IterableUtils.matchesAny(iterable, predicate);
}
/**
* Checks if this iterable is empty.
*
* @return true if this iterable does not contain any elements, false otherwise
*/
public boolean isEmpty() {
return IterableUtils.isEmpty(iterable);
}
/**
* Checks if the object is contained in this iterable.
*
* @param object the object to check
* @return true if the object is contained in this iterable, false otherwise
*/
public boolean contains(final Object object) {
return IterableUtils.contains(iterable, object);
}
/**
* Applies the closure to all elements contained in this iterable.
*
* @param closure the closure to apply to each element, may not be null
* @throws NullPointerException if closure is null
*/
public void forEach(final Closure<? super E> closure) {
IterableUtils.forEach(iterable, closure);
}
/**
* Returns the element at the provided position in this iterable.
* In order to return the element, an iterator needs to be traversed
* up to the requested position.
*
* @param position the position of the element to return
* @return the element
* @throws IndexOutOfBoundsException if the provided position is outside the
* valid range of this iterable: [0, size)
*/
public E get(final int position) {
return IterableUtils.get(iterable, position);
}
/**
* Returns the number of elements that are contained in this iterable.
* In order to determine the size, an iterator needs to be traversed.
*
* @return the size of this iterable
*/
public int size() {
return IterableUtils.size(iterable);
}
/**
* Traverses an iterator of this iterable and adds all elements
* to the provided collection.
*
* @param collection the collection to add the elements
* @throws NullPointerException if collection is null
*/
public void copyInto(final Collection<? super E> collection) {
if (collection == null) {
throw new NullPointerException("Collection must not be null");
}
CollectionUtils.addAll(collection, iterable);
}
/**
* Returns an array containing all elements of this iterable by traversing
* its iterator.
*
* @param arrayClass the class of array to create
* @return an array of the iterable contents
* @throws ArrayStoreException if arrayClass is invalid
*/
public E[] toArray(final Class<E> arrayClass) {
return IteratorUtils.toArray(iterator(), arrayClass);
}
/**
* Returns a mutable list containing all elements of this iterable
* by traversing its iterator.
* <p>
* The returned list is guaranteed to be mutable.
*
* @return a list of the iterable contents
*/
public List<E> toList() {
return IterableUtils.toList(iterable);
}
/** {@inheritDoc} */
@Override
public String toString() {
return IterableUtils.toString(iterable);
}
}

72
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/FunctorException.java

@ -0,0 +1,72 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
/**
* Runtime exception thrown from functors.
* If required, a root cause error can be wrapped within this one.
*
* @since 3.0
* @version $Id: FunctorException.java 1477779 2013-04-30 18:55:24Z tn $
*/
public class FunctorException extends RuntimeException {
/** Serialization version */
private static final long serialVersionUID = -4704772662059351193L;
/**
* Constructs a new <code>FunctorException</code> without specified
* detail message.
*/
public FunctorException() {
super();
}
/**
* Constructs a new <code>FunctorException</code> with specified
* detail message.
*
* @param msg the error message.
*/
public FunctorException(final String msg) {
super(msg);
}
/**
* 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(final Throwable rootCause) {
super(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(final String msg, final Throwable rootCause) {
super(msg, rootCause);
}
}

77
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Get.java

@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Collection;
import java.util.Set;
/**
* The "read" subset of the {@link java.util.Map} interface.
*
* @since 4.0
* @version $Id: Get.java 1543265 2013-11-19 00:48:44Z ggregory $
*
* @see Put
*/
public interface Get<K, V> {
/**
* @see java.util.Map#containsKey(Object)
*/
boolean containsKey(Object key);
/**
* @see java.util.Map#containsValue(Object)
*/
boolean containsValue(Object value);
/**
* @see java.util.Map#entrySet()
*/
Set<java.util.Map.Entry<K, V>> entrySet();
/**
* @see java.util.Map#get(Object)
*/
V get(Object key);
/**
* @see java.util.Map#remove(Object)
*/
V remove(Object key);
/**
* @see java.util.Map#isEmpty()
*/
boolean isEmpty();
/**
* @see java.util.Map#keySet()
*/
Set<K> keySet();
/**
* @see java.util.Map#size()
*/
int size();
/**
* @see java.util.Map#values()
*/
Collection<V> values();
}

47
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/IterableGet.java

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
/**
* The "read" subset of the {@link java.util.Map} interface.
*
* @since 4.0
* @version $Id: IterableGet.java 1477779 2013-04-30 18:55:24Z tn $
*
* @see Put
*/
public interface IterableGet<K, V> extends Get<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 use Map Entry objects.
* <pre>
* IterableMap<String,Integer> map = new HashedMap<String,Integer>();
* MapIterator<String,Integer> it = map.mapIterator();
* while (it.hasNext()) {
* String key = it.next();
* Integer value = it.getValue();
* it.setValue(value + 1);
* }
* </pre>
*
* @return a map iterator
*/
MapIterator<K, V> mapIterator();
}

43
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/IterableMap.java

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
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 use Map Entry objects.
* <pre>
* IterableMap<String,Integer> map = new HashedMap<String,Integer>();
* MapIterator<String,Integer> it = map.mapIterator();
* while (it.hasNext()) {
* String key = it.next();
* Integer value = it.getValue();
* it.setValue(value + 1);
* }
* </pre>
*
* @param <K> the type of the keys in the map
* @param <V> the type of the values in the map
*
* @since 3.0
* @version $Id: IterableMap.java 1469004 2013-04-17 17:37:03Z tn $
*/
public interface IterableMap<K, V> extends Map<K, V>, Put<K, V>, IterableGet<K, V> {
}

31
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/IterableSortedMap.java

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.SortedMap;
/**
* {@link SortedMap} + {@link OrderedMap}.
*
* @param <K> the type of the keys in the map
* @param <V> the type of the values in the map
*
* @since 4.0
* @version $Id: IterableSortedMap.java 1469004 2013-04-17 17:37:03Z tn $
*/
public interface IterableSortedMap<K, V> extends SortedMap<K, V>, OrderedMap<K, V> {
}

1088
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/IterableUtils.java

File diff suppressed because it is too large Load Diff

1528
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/IteratorUtils.java

File diff suppressed because it is too large Load Diff

47
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/KeyValue.java

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
/**
* 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.
*
* @param <K> the type of the key
* @param <V> the type of the value
* @since 3.0
* @version $Id: KeyValue.java 1477779 2013-04-30 18:55:24Z tn $
*/
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();
}

709
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ListUtils.java

@ -0,0 +1,709 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import com.fr.third.org.apache.commons.collections4.bag.HashBag;
import com.fr.third.org.apache.commons.collections4.functors.DefaultEquator;
import com.fr.third.org.apache.commons.collections4.list.FixedSizeList;
import com.fr.third.org.apache.commons.collections4.list.LazyList;
import com.fr.third.org.apache.commons.collections4.list.PredicatedList;
import com.fr.third.org.apache.commons.collections4.list.TransformedList;
import com.fr.third.org.apache.commons.collections4.list.UnmodifiableList;
import com.fr.third.org.apache.commons.collections4.sequence.CommandVisitor;
import com.fr.third.org.apache.commons.collections4.sequence.EditScript;
import com.fr.third.org.apache.commons.collections4.sequence.SequencesComparator;
import com.fr.third.org.apache.commons.collections4.bag.HashBag;
import com.fr.third.org.apache.commons.collections4.functors.DefaultEquator;
import com.fr.third.org.apache.commons.collections4.list.FixedSizeList;
import com.fr.third.org.apache.commons.collections4.list.LazyList;
import com.fr.third.org.apache.commons.collections4.list.PredicatedList;
import com.fr.third.org.apache.commons.collections4.list.TransformedList;
import com.fr.third.org.apache.commons.collections4.list.UnmodifiableList;
import com.fr.third.org.apache.commons.collections4.sequence.CommandVisitor;
import com.fr.third.org.apache.commons.collections4.sequence.EditScript;
import com.fr.third.org.apache.commons.collections4.sequence.SequencesComparator;
/**
* Provides utility methods and decorators for {@link List} instances.
*
* @since 1.0
* @version $Id: ListUtils.java 1686855 2015-06-22 13:00:27Z tn $
*/
public class ListUtils {
/**
* <code>ListUtils</code> should not normally be instantiated.
*/
private ListUtils() {}
//-----------------------------------------------------------------------
/**
* Returns an immutable empty list if the argument is <code>null</code>,
* or the argument itself otherwise.
*
* @param <T> the element type
* @param list the list, possibly <code>null</code>
* @return an empty list if the argument is <code>null</code>
*/
public static <T> List<T> emptyIfNull(final List<T> list) {
return list == null ? Collections.<T>emptyList() : list;
}
/**
* Returns either the passed in list, or if the list is {@code null},
* the value of {@code defaultList}.
*
* @param <T> the element type
* @param list the list, possibly {@code null}
* @param defaultList the returned values if list is {@code null}
* @return an empty list if the argument is <code>null</code>
* @since 4.0
*/
public static <T> List<T> defaultIfNull(final List<T> list, final List<T> defaultList) {
return list == null ? defaultList : list;
}
/**
* Returns a new list containing all elements that are contained in
* both given lists.
*
* @param <E> the element type
* @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 List<E> result = new ArrayList<E>();
List<? extends E> smaller = list1;
List<? extends E> larger = list2;
if (list1.size() > list2.size()) {
smaller = list2;
larger = list1;
}
final HashSet<E> hashSet = new HashSet<E>(smaller);
for (final E e : larger) {
if (hashSet.contains(e)) {
result.add(e);
hashSet.remove(e);
}
}
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 <E> the element type
* @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<E> list1, final List<? extends E> list2) {
final ArrayList<E> result = new ArrayList<E>();
final HashBag<E> bag = new HashBag<E>(list2);
for (final E e : list1) {
if (!bag.remove(e, 1)) {
result.add(e);
}
}
return result;
}
/**
* Returns the sum of the given lists. This is their intersection
* subtracted from their union.
*
* @param <E> the element type
* @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 <E> the element type
* @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;
}
/**
* Selects all elements from input collection which match the given
* predicate into an output list.
* <p>
* A <code>null</code> predicate matches no elements.
*
* @param <E> the element type
* @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 list is null
*
* @since 4.0
* @see CollectionUtils#select(Iterable, Predicate)
*/
public static <E> List<E> select(final Collection<? extends E> inputCollection,
final Predicate<? super E> predicate) {
return CollectionUtils.select(inputCollection, predicate, new ArrayList<E>(inputCollection.size()));
}
/**
* 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 <E> the element type
* @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
*
* @since 4.0
* @see CollectionUtils#selectRejected(Iterable, Predicate)
*/
public static <E> List<E> selectRejected(final Collection<? extends E> inputCollection,
final Predicate<? super E> predicate) {
return CollectionUtils.selectRejected(inputCollection, predicate, new ArrayList<E>(inputCollection.size()));
}
/**
* 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
* {@code true} 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 {@code e1} and
* {@code e2} 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 {@code List} interface.
* </blockquote>
*
* <b>Note:</b> The behaviour of this method is undefined if the lists are
* modified during the equals comparison.
*
* @see java.util.List
* @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
*/
public static boolean isEqualList(final Collection<?> list1, final Collection<?> list2) {
if (list1 == list2) {
return true;
}
if (list1 == null || list2 == null || list1.size() != list2.size()) {
return false;
}
final Iterator<?> it1 = list1.iterator();
final Iterator<?> it2 = list2.iterator();
Object obj1 = null;
Object 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.
*
* @see java.util.List#hashCode()
* @param list the list to generate the hashCode for, may be null
* @return the hash code
*/
public static int hashCodeForList(final Collection<?> list) {
if (list == null) {
return 0;
}
int hashCode = 1;
final Iterator<?> it = list.iterator();
while (it.hasNext()) {
final Object obj = it.next();
hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
}
return hashCode;
}
//-----------------------------------------------------------------------
/**
* Returns a List containing all the elements in <code>collection</code>
* that are also in <code>retain</code>. The cardinality of an element <code>e</code>
* in the returned list is the same as the cardinality of <code>e</code>
* in <code>collection</code> unless <code>retain</code> does not contain <code>e</code>, in which
* case the cardinality is zero. This method is useful if you do not wish to modify
* the collection <code>c</code> and thus cannot call <code>collection.retainAll(retain);</code>.
* <p>
* This implementation iterates over <code>collection</code>, checking each element in
* turn to see if it's contained in <code>retain</code>. If it's contained, it's added
* to the returned list. As a consequence, it is advised to use a collection type for
* <code>retain</code> that provides a fast (e.g. O(1)) implementation of
* {@link Collection#contains(Object)}.
*
* @param <E> the element type
* @param collection the collection whose contents are the target of the #retailAll operation
* @param retain the collection containing the elements to be retained in the returned collection
* @return a <code>List</code> containing all the elements of <code>c</code>
* that occur at least once in <code>retain</code>.
* @throws NullPointerException if either parameter is null
* @since 3.2
*/
public static <E> List<E> retainAll(final Collection<E> collection, final Collection<?> retain) {
final List<E> list = new ArrayList<E>(Math.min(collection.size(), retain.size()));
for (final E obj : collection) {
if (retain.contains(obj)) {
list.add(obj);
}
}
return list;
}
/**
* Removes the elements in <code>remove</code> from <code>collection</code>. That is, this
* method returns a list containing all the elements in <code>collection</code>
* that are not in <code>remove</code>. The cardinality of an element <code>e</code>
* in the returned collection is the same as the cardinality of <code>e</code>
* in <code>collection</code> unless <code>remove</code> contains <code>e</code>, in which
* case the cardinality is zero. This method is useful if you do not wish to modify
* <code>collection</code> and thus cannot call <code>collection.removeAll(remove);</code>.
* <p>
* This implementation iterates over <code>collection</code>, checking each element in
* turn to see if it's contained in <code>remove</code>. If it's not contained, it's added
* to the returned list. As a consequence, it is advised to use a collection type for
* <code>remove</code> that provides a fast (e.g. O(1)) implementation of
* {@link Collection#contains(Object)}.
*
* @param <E> the element type
* @param collection the collection from which items are removed (in the returned collection)
* @param remove the items to be removed from the returned <code>collection</code>
* @return a <code>List</code> containing all the elements of <code>c</code> except
* any elements that also occur in <code>remove</code>.
* @throws NullPointerException if either parameter is null
* @since 3.2
*/
public static <E> List<E> removeAll(final Collection<E> collection, final Collection<?> remove) {
final List<E> list = new ArrayList<E>();
for (final E obj : collection) {
if (!remove.contains(obj)) {
list.add(obj);
}
}
return list;
}
//-----------------------------------------------------------------------
/**
* Returns a synchronized list backed by the given list.
* <p>
* You must manually synchronize on the returned list's iterator to
* avoid non-deterministic behavior:
*
* <pre>
* List list = ListUtils.synchronizedList(myList);
* synchronized (list) {
* Iterator i = list.iterator();
* while (i.hasNext()) {
* process (i.next());
* }
* }
* </pre>
*
* This method is just a wrapper for {@link Collections#synchronizedList(List)}.
*
* @param <E> the element type
* @param list the list to synchronize, must not be null
* @return a synchronized list backed by the given list
* @throws NullPointerException if the list is null
*/
public static <E> List<E> synchronizedList(final List<E> list) {
return Collections.synchronizedList(list);
}
/**
* Returns an unmodifiable list backed by the given list.
* <p>
* This method uses the implementation in the decorators subpackage.
*
* @param <E> the element type
* @param list the list to make unmodifiable, must not be null
* @return an unmodifiable list backed by the given list
* @throws NullPointerException if the list is null
*/
public static <E> List<E> unmodifiableList(final List<? extends E> list) {
return UnmodifiableList.unmodifiableList(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 <E> the element type
* @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 NullPointerException if the List or Predicate is null
*/
public static <E> List<E> predicatedList(final List<E> list, final Predicate<E> predicate) {
return PredicatedList.predicatedList(list, predicate);
}
/**
* Returns a transformed list backed by the given list.
* <p>
* This method returns a new list (decorating the specified list) that
* will transform any new entries added to it.
* Existing entries in the specified list will not be transformed.
* <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.
* <p>
* Existing entries in the specified list will not be transformed.
* If you want that behaviour, see {@link TransformedList#transformedList}.
*
* @param <E> the element type
* @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 NullPointerException if the List or Transformer is null
*/
public static <E> List<E> transformedList(final List<E> list,
final Transformer<? super E, ? extends E> transformer) {
return TransformedList.transformingList(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:
*
* <pre>
* Factory&lt;Date&gt; factory = new Factory&lt;Date&gt;() {
* public Date create() {
* return new Date();
* }
* }
* List&lt;Date&gt; lazy = ListUtils.lazyList(new ArrayList&lt;Date&gt;(), factory);
* Date date = lazy.get(3);
* </pre>
*
* After the above code is executed, <code>date</code> will refer to
* 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 <E> the element type
* @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 NullPointerException if the List or Factory is null
*/
public static <E> List<E> lazyList(final List<E> list, final Factory<? extends E> factory) {
return LazyList.lazyList(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 <E> the element type
* @param list the list whose size to fix, must not be null
* @return a fixed-size list backed by that list
* @throws NullPointerException if the List is null
*/
public static <E> List<E> fixedSizeList(final List<E> list) {
return FixedSizeList.fixedSizeList(list);
}
//-----------------------------------------------------------------------
/**
* Finds the first index in the given List which matches the given predicate.
* <p>
* If the input List or predicate is null, or no element of the List
* matches the predicate, -1 is returned.
*
* @param <E> the element type
* @param list the List to search, may be null
* @param predicate the predicate to use, may be null
* @return the first index of an Object in the List which matches the predicate or -1 if none could be found
*/
public static <E> int indexOf(final List<E> list, final Predicate<E> predicate) {
if (list != null && predicate != null) {
for (int i = 0; i < list.size(); i++) {
final E item = list.get(i);
if (predicate.evaluate(item)) {
return i;
}
}
}
return -1;
}
//-----------------------------------------------------------------------
/**
* Returns the longest common subsequence (LCS) of two sequences (lists).
*
* @param <E> the element type
* @param a the first list
* @param b the second list
* @return the longest common subsequence
* @throws NullPointerException if either list is {@code null}
* @since 4.0
*/
public static <E> List<E> longestCommonSubsequence(final List<E> a, final List<E> b) {
return longestCommonSubsequence( a, b, DefaultEquator.defaultEquator() );
}
/**
* Returns the longest common subsequence (LCS) of two sequences (lists).
*
* @param <E> the element type
* @param a the first list
* @param b the second list
* @param equator the equator used to test object equality
* @return the longest common subsequence
* @throws NullPointerException if either list or the equator is {@code null}
* @since 4.0
*/
public static <E> List<E> longestCommonSubsequence(final List<E> a, final List<E> b,
final Equator<? super E> equator) {
if (a == null || b == null) {
throw new NullPointerException("List must not be null");
}
if (equator == null) {
throw new NullPointerException("Equator must not be null");
}
final SequencesComparator<E> comparator = new SequencesComparator<E>(a, b, equator);
final EditScript<E> script = comparator.getScript();
final LcsVisitor<E> visitor = new LcsVisitor<E>();
script.visit(visitor);
return visitor.getSubSequence();
}
/**
* Returns the longest common subsequence (LCS) of two {@link CharSequence} objects.
* <p>
* This is a convenience method for using {@link #longestCommonSubsequence(List, List)}
* with {@link CharSequence} instances.
*
* @param a the first sequence
* @param b the second sequence
* @return the longest common subsequence as {@link String}
* @throws NullPointerException if either sequence is {@code null}
* @since 4.0
*/
public static String longestCommonSubsequence(final CharSequence a, final CharSequence b) {
if (a == null || b == null) {
throw new NullPointerException("CharSequence must not be null");
}
final List<Character> lcs = longestCommonSubsequence(new CharSequenceAsList( a ), new CharSequenceAsList( b ));
final StringBuilder sb = new StringBuilder();
for ( Character ch : lcs ) {
sb.append(ch);
}
return sb.toString();
}
/**
* A helper class used to construct the longest common subsequence.
*/
private static final class LcsVisitor<E> implements CommandVisitor<E> {
private ArrayList<E> sequence;
public LcsVisitor() {
sequence = new ArrayList<E>();
}
public void visitInsertCommand(final E object) {}
public void visitDeleteCommand(final E object) {}
public void visitKeepCommand(final E object) {
sequence.add(object);
}
public List<E> getSubSequence() {
return sequence;
}
}
/**
* A simple wrapper to use a CharSequence as List.
*/
private static final class CharSequenceAsList extends AbstractList<Character> {
private final CharSequence sequence;
public CharSequenceAsList(final CharSequence sequence) {
this.sequence = sequence;
}
@Override
public Character get( int index ) {
return Character.valueOf(sequence.charAt( index ));
}
@Override
public int size() {
return sequence.length();
}
}
//-----------------------------------------------------------------------
/**
* Returns consecutive {@link List#subList(int, int) sublists} of a
* list, each of the same size (the final list may be smaller). For example,
* partitioning a list containing {@code [a, b, c, d, e]} with a partition
* size of 3 yields {@code [[a, b, c], [d, e]]} -- an outer list containing
* two inner lists of three and two elements, all in the original order.
* <p>
* The outer list is unmodifiable, but reflects the latest state of the
* source list. The inner lists are sublist views of the original list,
* produced on demand using {@link List#subList(int, int)}, and are subject
* to all the usual caveats about modification as explained in that API.
* <p>
* Adapted from http://code.google.com/p/guava-libraries/
*
* @param <T> the element type
* @param list the list to return consecutive sublists of
* @param size the desired size of each sublist (the last may be smaller)
* @return a list of consecutive sublists
* @throws NullPointerException if list is null
* @throws IllegalArgumentException if size is not strictly positive
* @since 4.0
*/
public static <T> List<List<T>> partition(final List<T> list, final int size) {
if (list == null) {
throw new NullPointerException("List must not be null");
}
if (size <= 0) {
throw new IllegalArgumentException("Size must be greater than 0");
}
return new Partition<T>(list, size);
}
/**
* Provides a partition view on a {@link List}.
* @since 4.0
*/
private static class Partition<T> extends AbstractList<List<T>> {
private final List<T> list;
private final int size;
private Partition(final List<T> list, final int size) {
this.list = list;
this.size = size;
}
@Override
public List<T> get(final int index) {
final int listSize = size();
if (listSize < 0) {
throw new IllegalArgumentException("negative size: " + listSize);
}
if (index < 0) {
throw new IndexOutOfBoundsException("Index " + index + " must not be negative");
}
if (index >= listSize) {
throw new IndexOutOfBoundsException("Index " + index + " must be less than size " +
listSize);
}
final int start = index * size;
final int end = Math.min(start + size, list.size());
return list.subList(start, end);
}
@Override
public int size() {
return (list.size() + size - 1) / size;
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
}
}

67
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ListValuedMap.java

@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.List;
/**
* Defines a map that holds a list of values against each key.
* <p>
* A {@code ListValuedMap} is a Map with slightly different semantics:
* <ul>
* <li>Putting a value into the map will add the value to a {@link List} at that key.</li>
* <li>Getting a value will return a {@link List}, holding all the values put to that key.</li>
* </ul>
*
* @since 4.1
* @version $Id: ListValuedMap.java 1685299 2015-06-13 18:27:11Z tn $
*/
public interface ListValuedMap<K, V> extends MultiValuedMap<K, V> {
/**
* Gets the list of values associated with the specified key.
* <p>
* This method will return an <b>empty</b> list if
* {@link #containsKey(Object)} returns {@code false}. Changes to the
* returned list will update the underlying {@code ListValuedMap} and
* vice-versa.
*
* @param key the key to retrieve
* @return the {@code List} of values, implementations should return an
* empty {@code List} for no mapping
* @throws NullPointerException if the key is null and null keys are invalid
*/
@Override
List<V> get(K key);
/**
* Removes all values associated with the specified key.
* <p>
* The returned list <i>may</i> be modifiable, but updates will not be
* propagated to this list-valued map. In case no mapping was stored for the
* specified key, an empty, unmodifiable list will be returned.
*
* @param key the key to remove values from
* @return the {@code List} of values removed, implementations
* typically return an empty, unmodifiable {@code List} for no mapping found
* @throws UnsupportedOperationException if the map is unmodifiable
* @throws NullPointerException if the key is null and null keys are invalid
*/
@Override
List<V> remove(Object key);
}

109
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MapIterator.java

@ -0,0 +1,109 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
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<String,Integer> it = map.mapIterator();
* while (it.hasNext()) {
* String key = it.next();
* Integer value = it.getValue();
* it.setValue(value + 1);
* }
* </pre>
*
* @param <K> the type of the keys in the map
* @param <V> the type of the values in the map
* @since 3.0
* @version $Id: MapIterator.java 1469004 2013-04-17 17:37:03Z tn $
*/
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);
}

1811
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MapUtils.java

File diff suppressed because it is too large Load Diff

158
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MultiMap.java

@ -0,0 +1,158 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Collection;
/**
* 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>
* MultiMap mhm = new MultiValueMap();
* mhm.put(key, "A");
* mhm.put(key, "B");
* mhm.put(key, "C");
* Collection coll = (Collection) mhm.get(key);</pre>
* <p>
* <code>coll</code> will be a collection containing "A", "B", "C".
* <p>
* NOTE: Additional methods were added to this interface in Commons Collections 3.1.
* These were added solely for documentation purposes and do not change the interface
* as they were defined in the superinterface <code>Map</code> anyway.
*
* @since 2.0
* @version $Id: MultiMap.java 1683018 2015-06-01 22:41:31Z tn $
* @deprecated since 4.1, use {@link MultiValuedMap} instead
*/
@Deprecated
public interface MultiMap<K, V> extends IterableMap<K, Object> {
/**
* 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 subsequent <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 {@code true} if the mapping was removed, {@code false} otherwise
* @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
* @since 4.0 (signature in previous releases: V remove(K, V))
*/
boolean removeMapping(K key, V item);
//-----------------------------------------------------------------------
/**
* Gets the number of keys in this map.
* <p>
* Implementations typically return only the count of keys in the map
* This cannot be mandated due to backwards compatibility of this interface.
*
* @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 typically return <code>null</code> if no values have
* been mapped to the key, however the implementation may choose to
* return an empty collection.
* <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
*/
Object get(Object key); // Cannot use get(K key) as that does not properly implement Map#get
/**
* Checks whether the map contains the value specified.
* <p>
* Implementations typically check all collections against all keys for the value.
* This cannot be mandated due to backwards compatibility of this interface.
*
* @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);
/**
* 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
*/
Object put(K key, Object 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
*/
Object remove(Object key); // Cannot use remove(K key) as that does not properly implement Map#remove
/**
* Gets a collection containing all the values in the map.
* <p>
* Implementations typically return a collection containing the combination
* of values from all keys.
* This cannot be mandated due to backwards compatibility of this interface.
*
* @return a collection view of the values contained in this map
*/
Collection<Object> values();
}

259
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MultiMapUtils.java

@ -0,0 +1,259 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.bag.HashBag;
import com.fr.third.org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
import com.fr.third.org.apache.commons.collections4.multimap.HashSetValuedHashMap;
import com.fr.third.org.apache.commons.collections4.multimap.TransformedMultiValuedMap;
import com.fr.third.org.apache.commons.collections4.multimap.UnmodifiableMultiValuedMap;
import com.fr.third.org.apache.commons.collections4.bag.HashBag;
import com.fr.third.org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
import com.fr.third.org.apache.commons.collections4.multimap.HashSetValuedHashMap;
import com.fr.third.org.apache.commons.collections4.multimap.TransformedMultiValuedMap;
import com.fr.third.org.apache.commons.collections4.multimap.UnmodifiableMultiValuedMap;
/**
* Provides utility methods and decorators for {@link MultiValuedMap} instances.
* <p>
* It contains various type safe and null safe methods. Additionally, it provides
* the following decorators:
* <ul>
* <li>{@link #unmodifiableMultiValuedMap(MultiValuedMap)}</li>
* <li>{@link #transformedMultiValuedMap(MultiValuedMap, Transformer, Transformer)}</li>
* </ul>
*
* @since 4.1
* @version $Id: MultiMapUtils.java 1715302 2015-11-19 23:08:01Z tn $
*/
public class MultiMapUtils {
/**
* <code>MultiMapUtils</code> should not normally be instantiated.
*/
private MultiMapUtils() {}
/**
* An empty {@link UnmodifiableMultiValuedMap}.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static final MultiValuedMap EMPTY_MULTI_VALUED_MAP =
UnmodifiableMultiValuedMap.unmodifiableMultiValuedMap(new ArrayListValuedHashMap(0, 0));
/**
* Returns immutable EMPTY_MULTI_VALUED_MAP with generic type safety.
*
* @param <K> the type of key in the map
* @param <V> the type of value in the map
* @return immutable and empty <code>MultiValuedMap</code>
*/
@SuppressWarnings("unchecked")
public static <K, V> MultiValuedMap<K, V> emptyMultiValuedMap() {
return EMPTY_MULTI_VALUED_MAP;
}
// Null safe methods
/**
* Returns an immutable empty <code>MultiValuedMap</code> if the argument is
* <code>null</code>, or the argument itself otherwise.
*
* @param <K> the type of key in the map
* @param <V> the type of value in the map
* @param map the map, may be null
* @return an empty {@link MultiValuedMap} if the argument is null
*/
@SuppressWarnings("unchecked")
public static <K, V> MultiValuedMap<K, V> emptyIfNull(final MultiValuedMap<K, V> map) {
return map == null ? EMPTY_MULTI_VALUED_MAP : map;
}
/**
* Null-safe check if the specified <code>MultiValuedMap</code> is empty.
* <p>
* If the provided map is null, returns true.
*
* @param map the map to check, may be null
* @return true if the map is empty or null
*/
public static boolean isEmpty(final MultiValuedMap<?, ?> map) {
return map == null || map.isEmpty();
}
// Null safe getters
// -------------------------------------------------------------------------
/**
* Gets a Collection from <code>MultiValuedMap</code> in a null-safe manner.
*
* @param <K> the key type
* @param <V> the value type
* @param map the {@link MultiValuedMap} to use
* @param key the key to look up
* @return the Collection in the {@link MultiValuedMap}, or null if input map is null
*/
public static <K, V> Collection<V> getCollection(final MultiValuedMap<K, V> map, final K key) {
if (map != null) {
return map.get(key);
}
return null;
}
// TODO: review the getValuesAsXXX methods - depending on the actual MultiValuedMap type, changes
// to the returned collection might update the backing map. This should be clarified and/or prevented.
/**
* Gets a List from <code>MultiValuedMap</code> in a null-safe manner.
*
* @param <K> the key type
* @param <V> the value type
* @param map the {@link MultiValuedMap} to use
* @param key the key to look up
* @return the Collection in the {@link MultiValuedMap} as List, or null if input map is null
*/
public static <K, V> List<V> getValuesAsList(final MultiValuedMap<K, V> map, final K key) {
if (map != null) {
Collection<V> col = map.get(key);
if (col instanceof List) {
return (List<V>) col;
}
return new ArrayList<V>(col);
}
return null;
}
/**
* Gets a Set from <code>MultiValuedMap</code> in a null-safe manner.
*
* @param <K> the key type
* @param <V> the value type
* @param map the {@link MultiValuedMap} to use
* @param key the key to look up
* @return the Collection in the {@link MultiValuedMap} as Set, or null if input map is null
*/
public static <K, V> Set<V> getValuesAsSet(final MultiValuedMap<K, V> map, final K key) {
if (map != null) {
Collection<V> col = map.get(key);
if (col instanceof Set) {
return (Set<V>) col;
}
return new HashSet<V>(col);
}
return null;
}
/**
* Gets a Bag from <code>MultiValuedMap</code> in a null-safe manner.
*
* @param <K> the key type
* @param <V> the value type
* @param map the {@link MultiValuedMap} to use
* @param key the key to look up
* @return the Collection in the {@link MultiValuedMap} as Bag, or null if input map is null
*/
public static <K, V> Bag<V> getValuesAsBag(final MultiValuedMap<K, V> map, final K key) {
if (map != null) {
Collection<V> col = map.get(key);
if (col instanceof Bag) {
return (Bag<V>) col;
}
return new HashBag<V>(col);
}
return null;
}
// Factory Methods
// -----------------------------------------------------------------------
/**
* Creates a {@link ListValuedMap} with an {@link java.util.ArrayList ArrayList} as
* collection class to store the values mapped to a key.
*
* @param <K> the key type
* @param <V> the value type
* @return a new <code>ListValuedMap</code>
*/
public static <K, V> ListValuedMap<K, V> newListValuedHashMap() {
return new ArrayListValuedHashMap<K, V>();
}
/**
* Creates a {@link SetValuedMap} with an {@link java.util.HashSet HashSet} as
* collection class to store the values mapped to a key.
*
* @param <K> the key type
* @param <V> the value type
* @return a new {@link SetValuedMap}
*/
public static <K, V> SetValuedMap<K, V> newSetValuedHashMap() {
return new HashSetValuedHashMap<K, V>();
}
// MultiValuedMap Decorators
// -----------------------------------------------------------------------
/**
* Returns an <code>UnmodifiableMultiValuedMap</code> backed by the given
* map.
*
* @param <K> the key type
* @param <V> the value type
* @param map the {@link MultiValuedMap} to decorate, must not be null
* @return an unmodifiable {@link MultiValuedMap} backed by the provided map
* @throws NullPointerException if map is null
*/
public static <K, V> MultiValuedMap<K, V> unmodifiableMultiValuedMap(
final MultiValuedMap<? extends K, ? extends V> map) {
return UnmodifiableMultiValuedMap.<K, V>unmodifiableMultiValuedMap(map);
}
/**
* Returns a <code>TransformedMultiValuedMap</code> backed by the given map.
* <p>
* This method returns a new <code>MultiValuedMap</code> (decorating the
* specified map) that will transform any new entries added to it. Existing
* entries in the specified map will not be transformed. If you want that
* behaviour, see {@link TransformedMultiValuedMap#transformedMap}.
* <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 back door for adding untransformed objects.
* <p>
* If there are any elements already in the map being decorated, they are
* NOT transformed.
*
* @param <K> the key type
* @param <V> the value type
* @param map the {@link MultiValuedMap} to transform, must not be null, typically empty
* @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 <code>MultiValuedMap</code> backed by the given map
* @throws NullPointerException if map is null
*/
public static <K, V> MultiValuedMap<K, V> transformedMultiValuedMap(final MultiValuedMap<K, V> map,
final Transformer<? super K, ? extends K> keyTransformer,
final Transformer<? super V, ? extends V> valueTransformer) {
return TransformedMultiValuedMap.transformingMap(map, keyTransformer, valueTransformer);
}
}

272
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MultiSet.java

@ -0,0 +1,272 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
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 MultiSet 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>.
*
* @param <E> the type held in the multiset
* @since 4.1
* @version $Id: MultiSet.java 1714424 2015-11-15 10:06:16Z tn $
*/
public interface MultiSet<E> extends Collection<E> {
/**
* Returns the number of occurrences of the given object currently
* in the MultiSet. If the object does not exist in the multiset,
* return 0.
*
* @param object the object to search for
* @return the number of occurrences of the object, zero if not found
*/
int getCount(Object object);
/**
* Sets the number of occurrences of the specified object in the MultiSet
* to the given count.
* <p>
* If the provided count is zero, the object will be removed from the
* {@link #uniqueSet()}.
*
* @param object the object to update
* @param count the number of occurrences of the object
* @return the number of occurrences of the object before this operation, zero
* if the object was not contained in the multiset
* @throws IllegalArgumentException if count is negative
*/
int setCount(E object, int count);
/**
* Adds one copy of the specified object to the MultiSet.
* <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.
*
* @param object the object to add
* @return <code>true</code> always, as the size of the MultiSet is increased
* in any case
*/
@Override
boolean add(E object);
/**
* Adds a number of occurrences of the specified object to the MultiSet.
* <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>occurrences</code>.
*
* @param object the object to add
* @param occurrences the number of occurrences to add, may be zero,
* in which case no change is made to the multiset
* @return the number of occurrences of the object in the multiset before
* this operation; possibly zero
* @throws IllegalArgumentException if occurrences is negative
*/
int add(E object, int occurrences);
/**
* Removes one occurrence of the given object from the MultiSet.
* <p>
* If the number of occurrences after this operations is reduced
* to zero, the object will be removed from the {@link #uniqueSet()}.
*
* @param object the object to remove
* @return <code>true</code> if this call changed the collection
*/
@Override
boolean remove(Object object);
/**
* Removes a number of occurrences of the specified object from the MultiSet.
* <p>
* If the number of occurrences to remove is greater than the actual number of
* occurrences in the multiset, the object will be removed from the multiset.
*
* @param object the object to remove
* @param occurrences the number of occurrences to remove, may be zero,
* in which case no change is made to the multiset
* @return the number of occurrences of the object in the multiset
* before the operation; possibly zero
* @throws IllegalArgumentException if occurrences is negative
*/
int remove(Object object, int occurrences);
/**
* Returns a {@link Set} of unique elements in the MultiSet.
* <p>
* Uniqueness constraints are the same as those in {@link java.util.Set}.
* <p>
* The returned set is backed by this multiset, so any change to either
* is immediately reflected in the other. Only removal operations are
* supported, in which case all occurrences of the element are removed
* from the backing multiset.
*
* @return the Set of unique MultiSet elements
*/
Set<E> uniqueSet();
/**
* Returns a {@link Set} of all entries contained in the MultiSet.
* <p>
* The returned set is backed by this multiset, so any change to either
* is immediately reflected in the other.
*
* @return the Set of MultiSet entries
*/
Set<Entry<E>> entrySet();
/**
* 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 MultiSet
*/
@Override
Iterator<E> iterator();
/**
* Returns the total number of items in the MultiSet.
*
* @return the total size of the multiset
*/
@Override
int size();
/**
* Returns <code>true</code> if the MultiSet contains at least one
* occurrence for each element contained in the given collection.
*
* @param coll the collection to check against
* @return <code>true</code> if the MultiSet contains all the collection
*/
@Override
boolean containsAll(Collection<?> coll);
/**
* Remove all occurrences of all elements from this MultiSet represented
* in the given collection.
*
* @param coll the collection of elements to remove
* @return <code>true</code> if this call changed the multiset
*/
@Override
boolean removeAll(Collection<?> coll);
/**
* Remove any elements of this MultiSet that are not contained in the
* given collection.
*
* @param coll the collection of elements to retain
* @return <code>true</code> if this call changed the multiset
*/
@Override
boolean retainAll(Collection<?> coll);
/**
* Compares this MultiSet to another object.
* <p>
* This MultiSet equals another object if it is also a MultiSet
* that contains the same number of occurrences of the same elements.
*
* @param obj the object to compare to
* @return true if equal
*/
@Override
boolean equals(Object obj);
/**
* Gets a hash code for the MultiSet 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>.
*
* @return the hash code of the MultiSet
*/
@Override
int hashCode();
/**
* An unmodifiable entry for an element and its occurrence as contained in a MultiSet.
* <p>
* The {@link MultiSet#entrySet()} method returns a view of the multiset whose elements
* implements this interface.
*
* @param <E> the element type
*/
interface Entry<E> {
/**
* Returns the element corresponding to this entry.
*
* @return the element corresponding to this entry
*/
E getElement();
/**
* Returns the number of occurrences for the element of this entry.
*
* @return the number of occurrences of the element
*/
int getCount();
/**
* Compares the specified object with this entry for equality.
* Returns true if the given object is also a multiset entry
* and the two entries represent the same element with the same
* number of occurrences.
* <p>
* More formally, two entries <tt>e1</tt> and <tt>e2</tt> represent
* the same mapping if
* <pre>
* (e1.getElement()==null ? e2.getElement()==null
* : e1.getElement().equals(e2.getElement())) &amp;&amp;
* (e1.getCount()==e2.getCount())
* </pre>
*
* @param o object to be compared for equality with this multiset entry
* @return true if the specified object is equal to this multiset entry
*/
@Override
boolean equals(Object o);
/**
* Returns the hash code value for this multiset entry.
* <p>
* The hash code of a multiset entry <tt>e</tt> is defined to be:
* <pre>
* (e==null ? 0 : e.hashCode()) ^ noOccurances)
* </pre>
*
* @return the hash code value for this multiset entry
*/
@Override
int hashCode();
}
}

123
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MultiSetUtils.java

@ -0,0 +1,123 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import com.fr.third.org.apache.commons.collections4.multiset.HashMultiSet;
import com.fr.third.org.apache.commons.collections4.multiset.PredicatedMultiSet;
import com.fr.third.org.apache.commons.collections4.multiset.SynchronizedMultiSet;
import com.fr.third.org.apache.commons.collections4.multiset.UnmodifiableMultiSet;
import com.fr.third.org.apache.commons.collections4.multiset.HashMultiSet;
import com.fr.third.org.apache.commons.collections4.multiset.PredicatedMultiSet;
import com.fr.third.org.apache.commons.collections4.multiset.SynchronizedMultiSet;
import com.fr.third.org.apache.commons.collections4.multiset.UnmodifiableMultiSet;
/**
* Provides utility methods and decorators for {@link MultiSet} instances.
*
* @since 4.1
* @version $Id: MultiSetUtils.java 1714424 2015-11-15 10:06:16Z tn $
*/
public class MultiSetUtils {
/**
* An empty unmodifiable multiset.
*/
@SuppressWarnings("rawtypes") // OK, empty multiset is compatible with any type
public static final MultiSet EMPTY_MULTISET =
UnmodifiableMultiSet.unmodifiableMultiSet(new HashMultiSet<Object>());
/**
* Instantiation of MultiSetUtils is not intended or required.
*/
private MultiSetUtils() {}
//-----------------------------------------------------------------------
/**
* Returns a synchronized (thread-safe) multiset backed by the given multiset.
* In order to guarantee serial access, it is critical that all access to the
* backing multiset is accomplished through the returned multiset.
* <p>
* It is imperative that the user manually synchronize on the returned multiset
* when iterating over it:
*
* <pre>
* MultiSet multiset = MultiSetUtils.synchronizedMultiSet(new HashMultiSet());
* ...
* synchronized(multiset) {
* Iterator i = multiset.iterator(); // Must be in synchronized block
* while (i.hasNext())
* foo(i.next());
* }
* }
* </pre>
*
* Failure to follow this advice may result in non-deterministic behavior.
*
* @param <E> the element type
* @param multiset the multiset to synchronize, must not be null
* @return a synchronized multiset backed by that multiset
* @throws NullPointerException if the MultiSet is null
*/
public static <E> MultiSet<E> synchronizedMultiSet(final MultiSet<E> multiset) {
return SynchronizedMultiSet.synchronizedMultiSet(multiset);
}
/**
* Returns an unmodifiable view of the given multiset. Any modification attempts
* to the returned multiset will raise an {@link UnsupportedOperationException}.
*
* @param <E> the element type
* @param multiset the multiset whose unmodifiable view is to be returned, must not be null
* @return an unmodifiable view of that multiset
* @throws NullPointerException if the MultiSet is null
*/
public static <E> MultiSet<E> unmodifiableMultiSet(final MultiSet<? extends E> multiset) {
return UnmodifiableMultiSet.unmodifiableMultiSet(multiset);
}
/**
* Returns a predicated (validating) multiset backed by the given multiset.
* <p>
* Only objects that pass the test in the given predicate can be added to
* the multiset. Trying to add an invalid object results in an
* IllegalArgumentException. It is important not to use the original multiset
* after invoking this method, as it is a backdoor for adding invalid
* objects.
*
* @param <E> the element type
* @param multiset the multiset to predicate, must not be null
* @param predicate the predicate for the multiset, must not be null
* @return a predicated multiset backed by the given multiset
* @throws NullPointerException if the MultiSet or Predicate is null
*/
public static <E> MultiSet<E> predicatedMultiSet(final MultiSet<E> multiset,
final Predicate<? super E> predicate) {
return PredicatedMultiSet.predicatedMultiSet(multiset, predicate);
}
/**
* Get an empty <code>MultiSet</code>.
*
* @param <E> the element type
* @return an empty MultiSet
*/
@SuppressWarnings("unchecked") // OK, empty multiset is compatible with any type
public static <E> MultiSet<E> emptyMultiSet() {
return EMPTY_MULTISET;
}
}

320
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/MultiValuedMap.java

@ -0,0 +1,320 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Defines a map that holds a collection of values against each key.
* <p>
* A {@code MultiValuedMap} is a Map with slightly different semantics:
* <ul>
* <li>Putting a value into the map will add the value to a {@link Collection} at that key.</li>
* <li>Getting a value will return a {@link Collection}, holding all the values put to that key.</li>
* </ul>
* <p>
* For example:
* <pre>
* MultiValuedMap&lt;K, String&gt; map = new MultiValuedHashMap&lt;K, String&gt;();
* map.put(key, &quot;A&quot;);
* map.put(key, &quot;B&quot;);
* map.put(key, &quot;C&quot;);
* Collection&lt;String&gt; coll = map.get(key);
* </pre>
* <p>
* <code>coll</code> will be a collection containing "A", "B", "C".
* <p>
*
* @since 4.1
* @version $Id: MultiValuedMap.java 1716537 2015-11-25 20:27:24Z tn $
*/
public interface MultiValuedMap<K, V> {
// Query operations
/**
* Gets the total size of the map.
* <p>
* Implementations would return the total size of the map which is the count
* of the values from all keys.
*
* @return the total size of the map
*/
int size();
/**
* Returns {@code true} if this map contains no key-value mappings.
*
* @return {@code true} if this map contains no key-value mappings
*/
boolean isEmpty();
/**
* Returns {@code true} if this map contains a mapping for the specified
* key. More formally, returns {@code true} if and only if this map contains
* a mapping for a key {@code k} such that {@code (key==null ? k==null : key.equals(k))}.
* (There can be at most one such mapping.)
*
* @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 NullPointerException if the specified key is null and this map
* does not permit null keys (optional)
*/
boolean containsKey(Object key);
/**
* Checks whether the map contains at least one mapping for the specified value.
*
* @param value the value to search for
* @return true if the map contains the value
* @throws NullPointerException if the value is null and null values are not supported
* by the used collection types (optional)
*/
boolean containsValue(Object value);
/**
* Checks whether the map contains a mapping for the specified key and value.
*
* @param key the key to search for
* @param value the value to search for
* @return true if the map contains the value
*/
boolean containsMapping(Object key, Object value);
/**
* Returns a view collection of the values associated with the specified key.
* <p>
* This method will return an <b>empty</b> collection if {@link #containsKey(Object)}
* returns {@code false}. Changes to the returned collection will update the underlying
* {@code MultiValuedMap} and vice-versa.
*
* @param key the key to retrieve
* @return the {@code Collection} of values, implementations should
* return an empty collection for no mapping
* @throws NullPointerException if the key is null and null keys are invalid (optional)
*/
Collection<V> get(K key);
// Modification operations
/**
* Adds a key-value mapping to this multi-valued map.
* <p>
* Unlike a normal {@code Map} the previous value is not replaced.
* Instead the new value is added to the collection stored against the key.
* Depending on the collection type used, duplicate key-value mappings may
* be allowed.
* <p>
* The method will return {@code true} if the size of the multi-valued map
* has been increased because of this operation.
*
* @param key the key to store against
* @param value the value to add to the collection at the key
* @return true if the map changed as a result of this put operation, or false
* if the map already contained the key-value mapping and the collection
* type does not allow duplicate values, e.g. when using a Set
* @throws UnsupportedOperationException if the put operation is not supported by
* this multi-valued map, e.g. if it is unmodifiable
* @throws NullPointerException if the key or value is null and null is invalid (optional)
* @throws IllegalArgumentException if some aspect of the specified key or value prevents
* it from being stored in this multi-valued map
*/
boolean put(K key, V value);
/**
* Adds a mapping to the specified key for all values contained in the given Iterable.
*
* @param key the key to store against
* @param values the values to add to the collection at the key, may not be null
* @return true if the map changed as a result of this operation
* @throws NullPointerException if the specified iterable is null, or if this map
* does not permit null keys or values, and the specified key or values contain
* null (optional)
*/
boolean putAll(K key, Iterable<? extends V> values);
/**
* Copies all mappings from the specified map to this multi-valued map
* (optional operation).
* <p>
* 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 {@code k} to value {@code v} in the specified map.
* <p>
* The behavior of this operation is undefined if the specified map is modified
* while the operation is in progress.
*
* @param map mappings to be stored in this map, may not be null
* @return true if the map changed as a result of this operation
* @throws UnsupportedOperationException if the {@code putAll} operation is
* not supported by this map
* @throws NullPointerException if the specified map is null, or if this map
* does not permit null keys or values, and the specified map
* contains null keys or values (optional)
* @throws IllegalArgumentException if some property of a key or value in
* the specified map prevents it from being stored in this map
*/
boolean putAll(Map<? extends K, ? extends V> map);
/**
* Copies all mappings from the specified map to this multi-valued map
* (optional operation).
* <p>
* 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 {@code k} to value {@code v} in the specified map.
* <p>
* The behavior of this operation is undefined if the specified map is modified
* while the operation is in progress.
*
* @param map mappings to be stored in this map, may not be null
* @return true if the map changed as a result of this operation
* @throws UnsupportedOperationException if the {@code putAll} operation is
* not supported by this map
* @throws NullPointerException if the specified map is null, or if this map
* does not permit null keys or values, and the specified map
* contains null keys or values (optional)
* @throws IllegalArgumentException if some property of a key or value in
* the specified map prevents it from being stored in this map
*/
boolean putAll(MultiValuedMap<? extends K, ? extends V> map);
/**
* Removes all values associated with the specified key.
* <p>
* The returned collection <i>may</i> be modifiable, but updates will not be propagated
* to this multi-valued map. In case no mapping was stored for the specified
* key, an empty, unmodifiable collection will be returned.
*
* @param key the key to remove values from
* @return the values that were removed
* @throws UnsupportedOperationException if the map is unmodifiable
* @throws NullPointerException if the key is null and null keys are invalid (optional)
*/
Collection<V> remove(Object key);
/**
* Removes a key-value mapping from the 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
* an empty collection from a subsequent <code>get(Object)</code>.
*
* @param key the key to remove from
* @param item the item to remove
* @return true if the mapping was removed, false otherwise
* @throws UnsupportedOperationException if the map is unmodifiable
* @throws NullPointerException if the key or value is null and null is invalid (optional)
*/
boolean removeMapping(Object key, Object item);
/**
* Removes all of the mappings from this map (optional operation).
* <p>
* The map will be empty after this call returns.
*
* @throws UnsupportedOperationException if the map is unmodifiable
*/
void clear();
// Views
/**
* Returns a {@link Collection} view of the mappings contained in this multi-valued map.
* <p>
* The collection is backed by the map, so changes to the map are reflected
* in the collection, and vice-versa.
*
* @return a set view of the mappings contained in this map
*/
Collection<Entry<K, V>> entries();
/**
* Returns a {@link MultiSet} view of the keys contained in this multi-valued map.
* <p>
* The {@link MultiSet#getCount(Object)} method of the returned multiset will give
* the same result a calling {@code get(Object).size()} for the same key.
* <p>
* This multiset is backed by the map, so any changes in the map are reflected in
* the multiset.
*
* @return a multiset view of the keys contained in this map
*/
MultiSet<K> keys();
/**
* Returns a {@link Set} view of the keys contained in this multi-valued map.
* <p>
* The set is backed by the map, so changes to the map are reflected
* in the set, and vice-versa.
* <p>
* If the map is modified while an iteration over the set is in
* progress (except through the iterator's own {@code remove} operation),
* the result of the iteration is undefined. The set supports element
* removal, which removes the corresponding mapping from the map, via the
* {@code Iterator.remove}, {@code Set.remove}, {@code removeAll},
* {@code retainAll}, and {@code clear} operations. It does not support
* the {@code add} or {@code addAll} operations.
*
* @return a set view of the keys contained in this map
*/
Set<K> keySet();
/**
* Gets a {@link Collection} view of all values contained in this multi-valued map.
* <p>
* Implementations typically return a collection containing the combination
* of values from all keys.
*
* @return a collection view of the values contained in this multi-valued map
*/
Collection<V> values();
/**
* Returns a view of this multi-valued map as a {@code Map} from each distinct
* key to the non-empty collection of that key's associated values.
* <p>
* Note that {@code this.asMap().get(k)} is equivalent to {@code this.get(k)}
* only when {@code k} is a key contained in the multi-valued map; otherwise it
* returns {@code null} as opposed to an empty collection.
* <p>
* Changes to the returned map or the collections that serve as its values
* will update the underlying multi-valued map, and vice versa. The map does
* not support {@code put} or {@code putAll}, nor do its entries support
* {@link Map.Entry#setValue setValue}.
*
* @return a map view of the mappings in this multi-valued map
*/
Map<K, Collection<V>> asMap();
// Iterators
/**
* Obtains a <code>MapIterator</code> over this multi-valued map.
* <p>
* A map iterator is an efficient way of iterating over maps. There is no
* need to access the entries collection or use {@code Map.Entry} objects.
*
* @return a map iterator
*/
MapIterator<K, V> mapIterator();
}

51
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/OrderedBidiMap.java

@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
/**
* 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.
*
* @param <K> the type of the keys in the map
* @param <V> the type of the values in the map
*
* @since 3.0
* @version $Id: OrderedBidiMap.java 1543260 2013-11-19 00:47:22Z ggregory $
*/
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
*/
OrderedBidiMap<V, K> inverseBidiMap();
}

47
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/OrderedIterator.java

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Iterator;
/**
* Defines an iterator that operates over an ordered container. Subset of {@link java.util.ListIterator}.
* <p>
* This iterator allows both forward and reverse iteration through the container.
*
* @param <E> the type to iterate over
* @since 3.0
* @version $Id: OrderedIterator.java 1469004 2013-04-17 17:37:03Z tn $
*/
public interface OrderedIterator<E> extends Iterator<E> {
/**
* Checks to see if there is a previous element that can be iterated to.
*
* @return <code>true</code> if the iterator has a previous element
*/
boolean hasPrevious();
/**
* Gets the previous element from the container.
*
* @return the previous element in the iteration
* @throws java.util.NoSuchElementException if the iteration is finished
*/
E previous();
}

73
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/OrderedMap.java

@ -0,0 +1,73 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
/**
* Defines a map that maintains order and allows both forward and backward
* iteration through that order.
*
* @param <K> the type of the keys in the map
* @param <V> the type of the values in the map
*
* @since 3.0
* @version $Id: OrderedMap.java 1543259 2013-11-19 00:47:07Z ggregory $
*/
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.
*
* @return a map iterator
*/
OrderedMapIterator<K, V> mapIterator();
/**
* 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
*/
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
*/
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
*/
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
*/
K previousKey(K key);
}

46
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/OrderedMapIterator.java

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
/**
* Defines an iterator that operates over an ordered <code>Map</code>.
* <p>
* This iterator allows both forward and reverse iteration through the map.
*
* @param <K> the type of the keys in the map
* @param <V> the type of the values in the map
* @since 3.0
* @version $Id: OrderedMapIterator.java 1469004 2013-04-17 17:37:03Z tn $
*/
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();
}

49
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Predicate.java

@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
/**
* 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.
*
* @param <T> the type that the predicate queries
*
* @since 1.0
* @version $Id: Predicate.java 1543262 2013-11-19 00:47:45Z ggregory $
*/
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
*/
boolean evaluate(T object);
}

562
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/PredicateUtils.java

@ -0,0 +1,562 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Collection;
import com.fr.third.org.apache.commons.collections4.functors.AllPredicate;
import com.fr.third.org.apache.commons.collections4.functors.AndPredicate;
import com.fr.third.org.apache.commons.collections4.functors.AnyPredicate;
import com.fr.third.org.apache.commons.collections4.functors.EqualPredicate;
import com.fr.third.org.apache.commons.collections4.functors.ExceptionPredicate;
import com.fr.third.org.apache.commons.collections4.functors.FalsePredicate;
import com.fr.third.org.apache.commons.collections4.functors.IdentityPredicate;
import com.fr.third.org.apache.commons.collections4.functors.InstanceofPredicate;
import com.fr.third.org.apache.commons.collections4.functors.InvokerTransformer;
import com.fr.third.org.apache.commons.collections4.functors.NonePredicate;
import com.fr.third.org.apache.commons.collections4.functors.NotNullPredicate;
import com.fr.third.org.apache.commons.collections4.functors.NotPredicate;
import com.fr.third.org.apache.commons.collections4.functors.NullIsExceptionPredicate;
import com.fr.third.org.apache.commons.collections4.functors.NullIsFalsePredicate;
import com.fr.third.org.apache.commons.collections4.functors.NullIsTruePredicate;
import com.fr.third.org.apache.commons.collections4.functors.NullPredicate;
import com.fr.third.org.apache.commons.collections4.functors.OnePredicate;
import com.fr.third.org.apache.commons.collections4.functors.OrPredicate;
import com.fr.third.org.apache.commons.collections4.functors.TransformedPredicate;
import com.fr.third.org.apache.commons.collections4.functors.TransformerPredicate;
import com.fr.third.org.apache.commons.collections4.functors.TruePredicate;
import com.fr.third.org.apache.commons.collections4.functors.UniquePredicate;
import com.fr.third.org.apache.commons.collections4.functors.AllPredicate;
import com.fr.third.org.apache.commons.collections4.functors.AndPredicate;
import com.fr.third.org.apache.commons.collections4.functors.AnyPredicate;
import com.fr.third.org.apache.commons.collections4.functors.EqualPredicate;
import com.fr.third.org.apache.commons.collections4.functors.ExceptionPredicate;
import com.fr.third.org.apache.commons.collections4.functors.FalsePredicate;
import com.fr.third.org.apache.commons.collections4.functors.IdentityPredicate;
import com.fr.third.org.apache.commons.collections4.functors.InstanceofPredicate;
import com.fr.third.org.apache.commons.collections4.functors.InvokerTransformer;
import com.fr.third.org.apache.commons.collections4.functors.NonePredicate;
import com.fr.third.org.apache.commons.collections4.functors.NotNullPredicate;
import com.fr.third.org.apache.commons.collections4.functors.NotPredicate;
import com.fr.third.org.apache.commons.collections4.functors.NullIsExceptionPredicate;
import com.fr.third.org.apache.commons.collections4.functors.NullIsFalsePredicate;
import com.fr.third.org.apache.commons.collections4.functors.NullIsTruePredicate;
import com.fr.third.org.apache.commons.collections4.functors.NullPredicate;
import com.fr.third.org.apache.commons.collections4.functors.OnePredicate;
import com.fr.third.org.apache.commons.collections4.functors.OrPredicate;
import com.fr.third.org.apache.commons.collections4.functors.TransformedPredicate;
import com.fr.third.org.apache.commons.collections4.functors.TransformerPredicate;
import com.fr.third.org.apache.commons.collections4.functors.TruePredicate;
import com.fr.third.org.apache.commons.collections4.functors.UniquePredicate;
/**
* <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.
*
* @since 3.0
* @version $Id: PredicateUtils.java 1686855 2015-06-22 13:00:27Z tn $
*/
public class PredicateUtils {
/**
* This class is not normally instantiated.
*/
private PredicateUtils() {}
// Simple predicates
//-----------------------------------------------------------------------------
/**
* Gets a Predicate that always throws an exception.
* This could be useful during testing as a placeholder.
*
* @param <T> the type that the predicate queries
* @return the predicate
* @see ExceptionPredicate
*/
public static <T> Predicate<T> exceptionPredicate() {
return ExceptionPredicate.exceptionPredicate();
}
/**
* Gets a Predicate that always returns true.
*
* @param <T> the type that the predicate queries
* @return the predicate
* @see TruePredicate
*/
public static <T> Predicate<T> truePredicate() {
return TruePredicate.truePredicate();
}
/**
* Gets a Predicate that always returns false.
*
* @param <T> the type that the predicate queries
* @return the predicate
* @see FalsePredicate
*/
public static <T> Predicate<T> falsePredicate() {
return FalsePredicate.falsePredicate();
}
/**
* Gets a Predicate that checks if the input object passed in is null.
*
* @param <T> the type that the predicate queries
* @return the predicate
* @see NullPredicate
*/
public static <T> Predicate<T> nullPredicate() {
return NullPredicate.nullPredicate();
}
/**
* Gets a Predicate that checks if the input object passed in is not null.
*
* @param <T> the type that the predicate queries
* @return the predicate
* @see NotNullPredicate
*/
public static <T> Predicate<T> notNullPredicate() {
return NotNullPredicate.notNullPredicate();
}
/**
* Creates a Predicate that checks if the input object is equal to the
* specified object using equals().
*
* @param <T> the type that the predicate queries
* @param value the value to compare against
* @return the predicate
* @see EqualPredicate
*/
public static <T> Predicate<T> equalPredicate(final T value) {
return EqualPredicate.equalPredicate(value);
}
/**
* Creates a Predicate that checks if the input object is equal to the
* specified object by identity.
*
* @param <T> the type that the predicate queries
* @param value the value to compare against
* @return the predicate
* @see IdentityPredicate
*/
public static <T> Predicate<T> identityPredicate(final T value) {
return IdentityPredicate.identityPredicate(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 NullPointerException if the class is null
* @see InstanceofPredicate
*/
public static Predicate<Object> instanceofPredicate(final Class<?> type) {
return InstanceofPredicate.instanceOfPredicate(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.
*
* @param <T> the type that the predicate queries
* @return the predicate
* @see UniquePredicate
*/
public static <T> Predicate<T> uniquePredicate() {
// must return new instance each time
return UniquePredicate.uniquePredicate();
}
/**
* 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 <T> the type that the predicate queries
* @param methodName the method name to call on the input object, may not be null
* @return the predicate
* @throws NullPointerException if the methodName is null.
* @see InvokerTransformer
* @see TransformerPredicate
*/
public static <T> Predicate<T> invokerPredicate(final String methodName) {
// reuse transformer as it has caching - this is lazy really, should have inner class here
return asPredicate(InvokerTransformer.<Object, Boolean>invokerTransformer(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 <T> the type that the predicate queries
* @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 NullPointerException if the method name is null
* @throws IllegalArgumentException if the paramTypes and args don't match
* @see InvokerTransformer
* @see TransformerPredicate
*/
public static <T> Predicate<T> invokerPredicate(final String methodName, final Class<?>[] paramTypes,
final Object[] args) {
// reuse transformer as it has caching - this is lazy really, should have inner class here
return asPredicate(InvokerTransformer.<Object, Boolean>invokerTransformer(methodName, paramTypes, args));
}
// Boolean combinations
//-----------------------------------------------------------------------------
/**
* Create a new Predicate that returns true only if both of the specified
* predicates are true.
*
* @param <T> the type that the predicate queries
* @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 NullPointerException if either predicate is null
* @see AndPredicate
*/
public static <T> Predicate<T> andPredicate(final Predicate<? super T> predicate1,
final Predicate<? super T> predicate2) {
return AndPredicate.andPredicate(predicate1, predicate2);
}
/**
* Create a new Predicate that returns true only if all of the specified
* predicates are true.
* If the array of predicates is empty, then this predicate returns true.
*
* @param <T> the type that the predicate queries
* @param predicates an array of predicates to check, may not be null
* @return the <code>all</code> predicate
* @throws NullPointerException if the predicates array is null
* @throws NullPointerException if any predicate in the array is null
* @see AllPredicate
*/
public static <T> Predicate<T> allPredicate(final Predicate<? super T>... predicates) {
return AllPredicate.allPredicate(predicates);
}
/**
* Create a new Predicate that returns true only if all of the specified
* predicates are true. The predicates are checked in iterator order.
* If the collection of predicates is empty, then this predicate returns true.
*
* @param <T> the type that the predicate queries
* @param predicates a collection of predicates to check, may not be null
* @return the <code>all</code> predicate
* @throws NullPointerException if the predicates collection is null
* @throws NullPointerException if any predicate in the collection is null
* @see AllPredicate
*/
public static <T> Predicate<T> allPredicate(final Collection<? extends Predicate<? super T>> predicates) {
return AllPredicate.allPredicate(predicates);
}
/**
* Create a new Predicate that returns true if either of the specified
* predicates are true.
*
* @param <T> the type that the predicate queries
* @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 NullPointerException if either predicate is null
* @see OrPredicate
*/
public static <T> Predicate<T> orPredicate(final Predicate<? super T> predicate1,
final Predicate<? super T> predicate2) {
return OrPredicate.orPredicate(predicate1, predicate2);
}
/**
* Create a new Predicate that returns true if any of the specified
* predicates are true.
* If the array of predicates is empty, then this predicate returns false.
*
* @param <T> the type that the predicate queries
* @param predicates an array of predicates to check, may not be null
* @return the <code>any</code> predicate
* @throws NullPointerException if the predicates array is null
* @throws NullPointerException if any predicate in the array is null
* @see AnyPredicate
*/
public static <T> Predicate<T> anyPredicate(final Predicate<? super T>... predicates) {
return AnyPredicate.anyPredicate(predicates);
}
/**
* Create a new Predicate that returns true if any of the specified
* predicates are true. The predicates are checked in iterator order.
* If the collection of predicates is empty, then this predicate returns false.
*
* @param <T> the type that the predicate queries
* @param predicates a collection of predicates to check, may not be null
* @return the <code>any</code> predicate
* @throws NullPointerException if the predicates collection is null
* @throws NullPointerException if any predicate in the collection is null
* @see AnyPredicate
*/
public static <T> Predicate<T> anyPredicate(final Collection<? extends Predicate<? super T>> predicates) {
return AnyPredicate.anyPredicate(predicates);
}
/**
* Create a new Predicate that returns true if one, but not both, of the
* specified predicates are true. XOR
*
* @param <T> the type that the predicate queries
* @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 NullPointerException if either predicate is null
* @see OnePredicate
*/
public static <T> Predicate<T> eitherPredicate(final Predicate<? super T> predicate1,
final Predicate<? super T> predicate2) {
@SuppressWarnings("unchecked")
final Predicate<T> onePredicate = PredicateUtils.onePredicate(predicate1, predicate2);
return onePredicate;
}
/**
* Create a new Predicate that returns true if only one of the specified
* predicates are true.
* If the array of predicates is empty, then this predicate returns false.
*
* @param <T> the type that the predicate queries
* @param predicates an array of predicates to check, may not be null
* @return the <code>one</code> predicate
* @throws NullPointerException if the predicates array is null
* @throws NullPointerException if any predicate in the array is null
* @see OnePredicate
*/
public static <T> Predicate<T> onePredicate(final Predicate<? super T>... predicates) {
return OnePredicate.onePredicate(predicates);
}
/**
* Create a new Predicate that returns true if only one of the specified
* predicates are true. The predicates are checked in iterator order.
* If the collection of predicates is empty, then this predicate returns false.
*
* @param <T> the type that the predicate queries
* @param predicates a collection of predicates to check, may not be null
* @return the <code>one</code> predicate
* @throws NullPointerException if the predicates collection is null
* @throws NullPointerException if any predicate in the collection is null
* @see OnePredicate
*/
public static <T> Predicate<T> onePredicate(final Collection<? extends Predicate<? super T>> predicates) {
return OnePredicate.onePredicate(predicates);
}
/**
* Create a new Predicate that returns true if neither of the specified
* predicates are true.
*
* @param <T> the type that the predicate queries
* @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 NullPointerException if either predicate is null
* @see NonePredicate
*/
public static <T> Predicate<T> neitherPredicate(final Predicate<? super T> predicate1,
final Predicate<? super T> predicate2) {
@SuppressWarnings("unchecked")
final Predicate<T> nonePredicate = PredicateUtils.nonePredicate(predicate1, predicate2);
return nonePredicate;
}
/**
* Create a new Predicate that returns true if none of the specified
* predicates are true.
* If the array of predicates is empty, then this predicate returns true.
*
* @param <T> the type that the predicate queries
* @param predicates an array of predicates to check, may not be null
* @return the <code>none</code> predicate
* @throws NullPointerException if the predicates array is null
* @throws NullPointerException if any predicate in the array is null
* @see NonePredicate
*/
public static <T> Predicate<T> nonePredicate(final Predicate<? super T>... predicates) {
return NonePredicate.nonePredicate(predicates);
}
/**
* Create a new Predicate that returns true if none of the specified
* predicates are true. The predicates are checked in iterator order.
* If the collection of predicates is empty, then this predicate returns true.
*
* @param <T> the type that the predicate queries
* @param predicates a collection of predicates to check, may not be null
* @return the <code>none</code> predicate
* @throws NullPointerException if the predicates collection is null
* @throws NullPointerException if any predicate in the collection is null
* @see NonePredicate
*/
public static <T> Predicate<T> nonePredicate(final Collection<? extends Predicate<? super T>> predicates) {
return NonePredicate.nonePredicate(predicates);
}
/**
* Create a new Predicate that returns true if the specified predicate
* returns false and vice versa.
*
* @param <T> the type that the predicate queries
* @param predicate the predicate to not
* @return the <code>not</code> predicate
* @throws NullPointerException if the predicate is null
* @see NotPredicate
*/
public static <T> Predicate<T> notPredicate(final Predicate<? super T> predicate) {
return NotPredicate.notPredicate(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 <T> the type that the predicate queries
* @param transformer the transformer to wrap, may not be null
* @return the transformer wrapping predicate
* @throws NullPointerException if the transformer is null
* @see TransformerPredicate
*/
public static <T> Predicate<T> asPredicate(final Transformer<? super T, Boolean> transformer) {
return TransformerPredicate.transformerPredicate(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 <T> the type that the predicate queries
* @param predicate the predicate to wrap, may not be null
* @return the predicate
* @throws NullPointerException if the predicate is null.
* @see NullIsExceptionPredicate
*/
public static <T> Predicate<T> nullIsExceptionPredicate(final Predicate<? super T> predicate){
return NullIsExceptionPredicate.nullIsExceptionPredicate(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 <T> the type that the predicate queries
* @param predicate the predicate to wrap, may not be null
* @return the predicate
* @throws NullPointerException if the predicate is null.
* @see NullIsFalsePredicate
*/
public static <T> Predicate<T> nullIsFalsePredicate(final Predicate<? super T> predicate){
return NullIsFalsePredicate.nullIsFalsePredicate(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 <T> the type that the predicate queries
* @param predicate the predicate to wrap, may not be null
* @return the predicate
* @throws NullPointerException if the predicate is null.
* @see NullIsTruePredicate
*/
public static <T> Predicate<T> nullIsTruePredicate(final Predicate<? super T> predicate){
return NullIsTruePredicate.nullIsTruePredicate(predicate);
}
// Transformed
//-----------------------------------------------------------------------
/**
* Creates a predicate that transforms the input object before passing it
* to the predicate.
*
* @param <T> the type that the predicate queries
* @param transformer the transformer to call first
* @param predicate the predicate to call with the result of the transform
* @return the predicate
* @throws NullPointerException if the transformer or the predicate is null
* @see TransformedPredicate
* @since 3.1
*/
public static <T> Predicate<T> transformedPredicate(
final Transformer<? super T, ? extends T> transformer, final Predicate<? super T> predicate) {
return TransformedPredicate.transformedPredicate(transformer, predicate);
}
}

55
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Put.java

@ -0,0 +1,55 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Map;
/**
* The "write" subset of the {@link Map} interface.
* <p>
* NOTE: in the original {@link Map} interface, {@link Map#put(Object, Object)} is known
* to have the same return type as {@link Map#get(Object)}, namely {@code V}. {@link Put}
* makes no assumptions in this regard (there is no association with, nor even knowledge
* of, a "reading" interface) and thus defines {@link #put(Object, Object)} as returning
* {@link Object}.
*
* @since 4.0
* @version $Id: Put.java 1543257 2013-11-19 00:45:55Z ggregory $
*
* @see Get
*/
public interface Put<K, V> {
/**
* @see Map#clear()
*/
void clear();
/**
* Note that the return type is Object, rather than V as in the Map interface.
* See the class Javadoc for further info.
*
* @see Map#put(Object, Object)
*/
Object put(K key, V value);
/**
* @see Map#putAll(Map)
*/
void putAll(Map<? extends K, ? extends V> t);
}

111
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/QueueUtils.java

@ -0,0 +1,111 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.LinkedList;
import java.util.Queue;
import com.fr.third.org.apache.commons.collections4.queue.PredicatedQueue;
import com.fr.third.org.apache.commons.collections4.queue.TransformedQueue;
import com.fr.third.org.apache.commons.collections4.queue.UnmodifiableQueue;
import com.fr.third.org.apache.commons.collections4.queue.PredicatedQueue;
import com.fr.third.org.apache.commons.collections4.queue.TransformedQueue;
import com.fr.third.org.apache.commons.collections4.queue.UnmodifiableQueue;
/**
* Provides utility methods and decorators for {@link Queue} instances.
*
* @since 4.0
* @version $Id: QueueUtils.java 1686855 2015-06-22 13:00:27Z tn $
*/
public class QueueUtils {
/**
* An empty unmodifiable queue.
*/
@SuppressWarnings("rawtypes") // OK, empty queue is compatible with any type
public static final Queue EMPTY_QUEUE = UnmodifiableQueue.unmodifiableQueue(new LinkedList<Object>());
/**
* <code>QueueUtils</code> should not normally be instantiated.
*/
private QueueUtils() {}
//-----------------------------------------------------------------------
/**
* Returns an unmodifiable queue backed by the given queue.
*
* @param <E> the type of the elements in the queue
* @param queue the queue to make unmodifiable, must not be null
* @return an unmodifiable queue backed by that queue
* @throws NullPointerException if the queue is null
*/
public static <E> Queue<E> unmodifiableQueue(final Queue<? extends E> queue) {
return UnmodifiableQueue.unmodifiableQueue(queue);
}
/**
* Returns a predicated (validating) queue backed by the given queue.
* <p>
* Only objects that pass the test in the given predicate can be added to the queue.
* Trying to add an invalid object results in an IllegalArgumentException.
* It is important not to use the original queue after invoking this method,
* as it is a backdoor for adding invalid objects.
*
* @param <E> the type of the elements in the queue
* @param queue the queue to predicate, must not be null
* @param predicate the predicate used to evaluate new elements, must not be null
* @return a predicated queue
* @throws NullPointerException if the queue or predicate is null
*/
public static <E> Queue<E> predicatedQueue(final Queue<E> queue, final Predicate<? super E> predicate) {
return PredicatedQueue.predicatedQueue(queue, predicate);
}
/**
* Returns a transformed queue backed by the given queue.
* <p>
* Each object is passed through the transformer as it is added to the
* Queue. It is important not to use the original queue after invoking this
* method, as it is a backdoor for adding untransformed objects.
* <p>
* Existing entries in the specified queue will not be transformed.
* If you want that behaviour, see {@link TransformedQueue#transformedQueue}.
*
* @param <E> the type of the elements in the queue
* @param queue the queue to predicate, must not be null
* @param transformer the transformer for the queue, must not be null
* @return a transformed queue backed by the given queue
* @throws NullPointerException if the queue or transformer is null
*/
public static <E> Queue<E> transformingQueue(final Queue<E> queue,
final Transformer<? super E, ? extends E> transformer) {
return TransformedQueue.transformingQueue(queue, transformer);
}
/**
* Get an empty <code>Queue</code>.
*
* @param <E> the type of the elements in the queue
* @return an empty {@link Queue}
*/
@SuppressWarnings("unchecked") // OK, empty queue is compatible with any type
public static <E> Queue<E> emptyQueue() {
return (Queue<E>) EMPTY_QUEUE;
}
}

38
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ResettableIterator.java

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
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.
*
* @param <E> the type to iterate over
* @since 3.0
* @version $Id: ResettableIterator.java 1543263 2013-11-19 00:47:55Z ggregory $
*/
public interface ResettableIterator<E> extends Iterator<E> {
/**
* Resets the iterator back to the position at which the iterator
* was created.
*/
void reset();
}

32
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/ResettableListIterator.java

@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
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.
*
* @param <E> the type to iterate over
* @since 3.0
* @version $Id: ResettableListIterator.java 1477779 2013-04-30 18:55:24Z tn $
*/
public interface ResettableListIterator<E> extends ListIterator<E>, ResettableIterator<E>, OrderedIterator<E> {
}

655
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/SetUtils.java

@ -0,0 +1,655 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import com.fr.third.org.apache.commons.collections4.set.ListOrderedSet;
import com.fr.third.org.apache.commons.collections4.set.PredicatedNavigableSet;
import com.fr.third.org.apache.commons.collections4.set.PredicatedSet;
import com.fr.third.org.apache.commons.collections4.set.PredicatedSortedSet;
import com.fr.third.org.apache.commons.collections4.set.TransformedNavigableSet;
import com.fr.third.org.apache.commons.collections4.set.TransformedSet;
import com.fr.third.org.apache.commons.collections4.set.TransformedSortedSet;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableNavigableSet;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSortedSet;
import com.fr.third.org.apache.commons.collections4.set.ListOrderedSet;
import com.fr.third.org.apache.commons.collections4.set.PredicatedNavigableSet;
import com.fr.third.org.apache.commons.collections4.set.PredicatedSet;
import com.fr.third.org.apache.commons.collections4.set.PredicatedSortedSet;
import com.fr.third.org.apache.commons.collections4.set.TransformedNavigableSet;
import com.fr.third.org.apache.commons.collections4.set.TransformedSet;
import com.fr.third.org.apache.commons.collections4.set.TransformedSortedSet;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableNavigableSet;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSortedSet;
/**
* Provides utility methods and decorators for
* {@link Set} and {@link SortedSet} instances.
*
* @since 2.1
* @version $Id: SetUtils.java 1686950 2015-06-22 21:51:07Z tn $
*/
public class SetUtils {
/**
* Get a typed empty unmodifiable Set.
* @param <E> the element type
* @return an empty Set
*/
public static <E> Set<E> emptySet() {
return Collections.<E>emptySet();
}
/**
* An empty unmodifiable sorted set.
* This is not provided in the JDK.
*/
@SuppressWarnings("rawtypes")
public static final SortedSet EMPTY_SORTED_SET =
UnmodifiableSortedSet.unmodifiableSortedSet(new TreeSet<Object>());
/**
* Get a typed empty unmodifiable sorted set.
* @param <E> the element type
* @return an empty sorted Set
*/
@SuppressWarnings("unchecked") // empty set is OK for any type
public static <E> SortedSet<E> emptySortedSet() {
return EMPTY_SORTED_SET;
}
/**
* <code>SetUtils</code> should not normally be instantiated.
*/
private SetUtils() {}
//-----------------------------------------------------------------------
/**
* Returns an immutable empty set if the argument is <code>null</code>,
* or the argument itself otherwise.
*
* @param <T> the element type
* @param set the set, possibly <code>null</code>
* @return an empty set if the argument is <code>null</code>
*/
public static <T> Set<T> emptyIfNull(final Set<T> set) {
return set == null ? Collections.<T>emptySet() : set;
}
/**
* 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 {@code equals} method works
* properly across different implementations of the {@code Set}
* interface.</p>
*
* <p>
* This implementation first checks if the two sets are the same object:
* if so it returns {@code true}. Then, it checks if the two sets are
* identical in size; if not, it returns false. If so, it returns
* {@code a.containsAll((Collection) b)}.</p>
* </blockquote>
*
* @see java.util.Set
* @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
*/
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 <T> the element type
* @see java.util.Set#hashCode()
* @param set the set to calculate the hash code for, may be null
* @return the hash code
*/
public static <T> int hashCodeForSet(final Collection<T> set) {
if (set == null) {
return 0;
}
int hashCode = 0;
for (final T obj : set) {
if (obj != null) {
hashCode += obj.hashCode();
}
}
return hashCode;
}
/**
* Returns a new hash set that matches elements based on <code>==</code> not
* <code>equals()</code>.
* <p>
* <strong>This set will violate the detail of various Set contracts.</note>
* As a general rule, don't compare this set to other sets. In particular, you can't
* use decorators like {@link ListOrderedSet} on it, which silently assume that these
* contracts are fulfilled.</strong>
* <p>
* <strong>Note that the returned set is not synchronized and is not thread-safe.</strong>
* If you wish to use this set from multiple threads concurrently, you must use
* appropriate synchronization. The simplest approach is to wrap this map
* using {@link java.util.Collections#synchronizedSet(Set)}. This class may throw
* exceptions when accessed by concurrent threads without synchronization.
*
* @param <E> the element type
* @return a new identity hash set
* @since 4.1
*/
public static <E> Set<E> newIdentityHashSet() {
return Collections.newSetFromMap(new IdentityHashMap<E, Boolean>());
}
// Set
//-----------------------------------------------------------------------
/**
* Returns a synchronized set backed by the given set.
* <p>
* You must manually synchronize on the returned set's iterator to
* avoid non-deterministic behavior:
*
* <pre>
* Set s = SetUtils.synchronizedSet(mySet);
* synchronized (s) {
* Iterator i = s.iterator();
* while (i.hasNext()) {
* process (i.next());
* }
* }
* </pre>
*
* This method is just a wrapper for {@link Collections#synchronizedSet(Set)}.
*
* @param <E> the element type
* @param set the set to synchronize, must not be null
* @return a synchronized set backed by the given set
* @throws NullPointerException if the set is null
*/
public static <E> Set<E> synchronizedSet(final Set<E> set) {
return Collections.synchronizedSet(set);
}
/**
* Returns an unmodifiable set backed by the given set.
* <p>
* This method uses the implementation in the decorators subpackage.
*
* @param <E> the element type
* @param set the set to make unmodifiable, must not be null
* @return an unmodifiable set backed by the given set
* @throws NullPointerException if the set is null
*/
public static <E> Set<E> unmodifiableSet(final Set<? extends E> set) {
return UnmodifiableSet.unmodifiableSet(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 <E> the element type
* @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 NullPointerException if the set or predicate is null
*/
public static <E> Set<E> predicatedSet(final Set<E> set, final Predicate<? super E> predicate) {
return PredicatedSet.predicatedSet(set, predicate);
}
/**
* 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.
* <p>
* Existing entries in the specified set will not be transformed.
* If you want that behaviour, see {@link TransformedSet#transformedSet}.
*
* @param <E> the element type
* @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 NullPointerException if the set or transformer is null
*/
public static <E> Set<E> transformedSet(final Set<E> set,
final Transformer<? super E, ? extends E> transformer) {
return TransformedSet.transformingSet(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 <E> the element type
* @param set the set to order, must not be null
* @return an ordered set backed by the given set
* @throws NullPointerException if the set is null
*/
public static <E> Set<E> orderedSet(final Set<E> set) {
return ListOrderedSet.listOrderedSet(set);
}
// SortedSet
//-----------------------------------------------------------------------
/**
* Returns a synchronized sorted set backed by the given sorted set.
* <p>
* You must manually synchronize on the returned set's iterator to
* avoid non-deterministic behavior:
*
* <pre>
* Set s = SetUtils.synchronizedSortedSet(mySet);
* synchronized (s) {
* Iterator i = s.iterator();
* while (i.hasNext()) {
* process (i.next());
* }
* }
* </pre>
*
* This method is just a wrapper for {@link Collections#synchronizedSortedSet(SortedSet)}.
*
* @param <E> the element type
* @param set the sorted set to synchronize, must not be null
* @return a synchronized set backed by the given set
* @throws NullPointerException if the set is null
*/
public static <E> SortedSet<E> synchronizedSortedSet(final SortedSet<E> set) {
return Collections.synchronizedSortedSet(set);
}
/**
* Returns an unmodifiable sorted set backed by the given sorted set.
* <p>
* This method uses the implementation in the decorators subpackage.
*
* @param <E> the element type
* @param set the sorted set to make unmodifiable, must not be null
* @return an unmodifiable set backed by the given set
* @throws NullPointerException if the set is null
*/
public static <E> SortedSet<E> unmodifiableSortedSet(final SortedSet<E> set) {
return UnmodifiableSortedSet.unmodifiableSortedSet(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 <E> the element type
* @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 NullPointerException if the set or predicate is null
*/
public static <E> SortedSet<E> predicatedSortedSet(final SortedSet<E> set,
final Predicate<? super E> predicate) {
return PredicatedSortedSet.predicatedSortedSet(set, predicate);
}
/**
* 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.
* <p>
* Existing entries in the specified set will not be transformed.
* If you want that behaviour, see {@link TransformedSortedSet#transformedSortedSet}.
*
* @param <E> the element type
* @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 NullPointerException if the set or transformer is null
*/
public static <E> SortedSet<E> transformedSortedSet(final SortedSet<E> set,
final Transformer<? super E, ? extends E> transformer) {
return TransformedSortedSet.transformingSortedSet(set, transformer);
}
// NavigableSet
//-----------------------------------------------------------------------
/**
* Returns an unmodifiable navigable set backed by the given navigable set.
* <p>
* This method uses the implementation in the decorators subpackage.
*
* @param <E> the element type
* @param set the navigable set to make unmodifiable, must not be null
* @return an unmodifiable set backed by the given set
* @throws NullPointerException if the set is null
* @since 4.1
*/
public static <E> SortedSet<E> unmodifiableNavigableSet(final NavigableSet<E> set) {
return UnmodifiableNavigableSet.unmodifiableNavigableSet(set);
}
/**
* Returns a predicated (validating) navigable set backed by the given navigable 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 <E> the element type
* @param set the navigable set to predicate, must not be null
* @param predicate the predicate for the navigable set, must not be null
* @return a predicated navigable set backed by the given navigable set
* @throws NullPointerException if the set or predicate is null
* @since 4.1
*/
public static <E> SortedSet<E> predicatedNavigableSet(final NavigableSet<E> set,
final Predicate<? super E> predicate) {
return PredicatedNavigableSet.predicatedNavigableSet(set, predicate);
}
/**
* Returns a transformed navigable set backed by the given navigable 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.
* <p>
* Existing entries in the specified set will not be transformed.
* If you want that behaviour, see {@link TransformedNavigableSet#transformedNavigableSet}.
*
* @param <E> the element type
* @param set the navigable 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 NullPointerException if the set or transformer is null
* @since 4.1
*/
public static <E> SortedSet<E> transformedNavigableSet(final NavigableSet<E> set,
final Transformer<? super E, ? extends E> transformer) {
return TransformedNavigableSet.transformingNavigableSet(set, transformer);
}
// Set operations
//-----------------------------------------------------------------------
/**
* Returns a unmodifiable <b>view</b> of the union of the given {@link Set}s.
* <p>
* The returned view contains all elements of {@code a} and {@code b}.
*
* @param <E> the generic type that is able to represent the types contained
* in both input sets.
* @param a the first set, must not be null
* @param b the second set, must not be null
* @return a view of the union of the two set
* @throws NullPointerException if either input set is null
* @since 4.1
*/
public static <E> SetView<E> union(final Set<? extends E> a, final Set<? extends E> b) {
if (a == null || b == null) {
throw new NullPointerException("Sets must not be null.");
}
final SetView<E> bMinusA = difference(b, a);
return new SetView<E>() {
@Override
public boolean contains(Object o) {
return a.contains(o) || b.contains(o);
}
@Override
public Iterator<E> createIterator() {
return IteratorUtils.chainedIterator(a.iterator(), bMinusA.iterator());
}
@Override
public boolean isEmpty() {
return a.isEmpty() && b.isEmpty();
}
@Override
public int size() {
return a.size() + bMinusA.size();
}
};
}
/**
* Returns a unmodifiable <b>view</b> containing the difference of the given
* {@link Set}s, denoted by {@code a \ b} (or {@code a - b}).
* <p>
* The returned view contains all elements of {@code a} that are not a member
* of {@code b}.
*
* @param <E> the generic type that is able to represent the types contained
* in both input sets.
* @param a the set to subtract from, must not be null
* @param b the set to subtract, must not be null
* @return a view of the relative complement of of the two sets
* @since 4.1
*/
public static <E> SetView<E> difference(final Set<? extends E> a, final Set<? extends E> b) {
if (a == null || b == null) {
throw new NullPointerException("Sets must not be null.");
}
final Predicate<E> notContainedInB = new Predicate<E>() {
@Override
public boolean evaluate(E object) {
return !b.contains(object);
}
};
return new SetView<E>() {
@Override
public boolean contains(Object o) {
return a.contains(o) && !b.contains(o);
}
@Override
public Iterator<E> createIterator() {
return IteratorUtils.filteredIterator(a.iterator(), notContainedInB);
}
};
}
/**
* Returns a unmodifiable <b>view</b> of the intersection of the given {@link Set}s.
* <p>
* The returned view contains all elements that are members of both input sets
* ({@code a} and {@code b}).
*
* @param <E> the generic type that is able to represent the types contained
* in both input sets.
* @param a the first set, must not be null
* @param b the second set, must not be null
* @return a view of the intersection of the two sets
* @since 4.1
*/
public static <E> SetView<E> intersection(final Set<? extends E> a, final Set<? extends E> b) {
if (a == null || b == null) {
throw new NullPointerException("Sets must not be null.");
}
final Predicate<E> containedInB = new Predicate<E>() {
@Override
public boolean evaluate(E object) {
return b.contains(object);
}
};
return new SetView<E>() {
@Override
public boolean contains(Object o) {
return a.contains(o) && b.contains(o);
}
@Override
public Iterator<E> createIterator() {
return IteratorUtils.filteredIterator(a.iterator(), containedInB);
}
};
}
/**
* Returns a unmodifiable <b>view</b> of the symmetric difference of the given
* {@link Set}s.
* <p>
* The returned view contains all elements of {@code a} and {@code b} that are
* not a member of the other set.
* <p>
* This is equivalent to {@code union(difference(a, b), difference(b, a))}.
*
* @param <E> the generic type that is able to represent the types contained
* in both input sets.
* @param a the first set, must not be null
* @param b the second set, must not be null
* @return a view of the symmetric difference of the two sets
* @since 4.1
*/
public static <E> SetView<E> disjunction(final Set<? extends E> a, final Set<? extends E> b) {
if (a == null || b == null) {
throw new NullPointerException("Sets must not be null.");
}
final SetView<E> aMinusB = difference(a, b);
final SetView<E> bMinusA = difference(b, a);
return new SetView<E>() {
@Override
public boolean contains(Object o) {
return a.contains(o) ^ b.contains(o);
}
@Override
public Iterator<E> createIterator() {
return IteratorUtils.chainedIterator(aMinusB.iterator(), bMinusA.iterator());
}
@Override
public boolean isEmpty() {
return aMinusB.isEmpty() && bMinusA.isEmpty();
}
@Override
public int size() {
return aMinusB.size() + bMinusA.size();
}
};
}
/**
* An unmodifiable <b>view</b> of a set that may be backed by other sets.
* <p>
* If the decorated sets change, this view will change as well. The contents
* of this view can be transferred to another instance via the {@link #copyInto(Set)}
* and {@link #toSet()} methods.
*
* @param <E> the element type
* @since 4.1
*/
public static abstract class SetView<E> extends AbstractSet<E> {
@Override
public Iterator<E> iterator() {
return IteratorUtils.unmodifiableIterator(createIterator());
}
/**
* Return an iterator for this view; the returned iterator is
* not required to be unmodifiable.
* @return a new iterator for this view
*/
protected abstract Iterator<E> createIterator();
@Override
public int size() {
return IteratorUtils.size(iterator());
}
/**
* Copies the contents of this view into the provided set.
*
* @param <S> the set type
* @param set the set for copying the contents
*/
public <S extends Set<E>> void copyInto(final S set) {
CollectionUtils.addAll(set, this);
}
/**
* Returns a new set containing the contents of this view.
*
* @return a new set containing all elements of this view
*/
public Set<E> toSet() {
final Set<E> set = new HashSet<E>(size());
copyInto(set);
return set;
}
}
}

65
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/SetValuedMap.java

@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Set;
/**
* Defines a map that holds a set of values against each key.
* <p>
* A {@code SetValuedMap} is a Map with slightly different semantics:
* <ul>
* <li>Putting a value into the map will add the value to a {@link Set} at that key.</li>
* <li>Getting a value will return a {@link Set}, holding all the values put to that key.</li>
* </ul>
*
* @since 4.1
* @version $Id: SetValuedMap.java 1685299 2015-06-13 18:27:11Z tn $
*/
public interface SetValuedMap<K, V> extends MultiValuedMap<K, V> {
/**
* Gets the set of values associated with the specified key.
* <p>
* Implementations typically return an empty {@code Set} if no values
* have been mapped to the key.
* <p>
*
* @param key the key to retrieve
* @return the {@code Set} of values, implementations should return an
* empty {@code Set} for no mapping
* @throws NullPointerException if the key is null and null keys are invalid
*/
@Override
Set<V> get(K key);
/**
* Removes all values associated with the specified key.
* <p>
* The returned set <i>may</i> be modifiable, but updates will not be
* propagated to this set-valued map. In case no mapping was stored for the
* specified key, an empty, unmodifiable set will be returned.
*
* @param key the key to remove values from
* @return the {@code Set} of values removed, implementations should
* return null for no mapping found, but may return an empty collection
* @throws UnsupportedOperationException if the map is unmodifiable
* @throws NullPointerException if the key is null and null keys are invalid
*/
@Override
Set<V> remove(Object key);
}

53
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/SortedBag.java

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Comparator;
/**
* Defines a type of <code>Bag</code> that maintains a sorted order among
* its unique representative members.
*
* @param <E> the type to iterate over
* @since 2.0
* @version $Id: SortedBag.java 1543264 2013-11-19 00:48:12Z ggregory $
*/
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
*/
Comparator<? super E> comparator();
/**
* Returns the first (lowest) member.
*
* @return the first element in the sorted bag
*/
E first();
/**
* Returns the last (highest) member.
*
* @return the last element in the sorted bag
*/
E last();
}

58
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/SortedBidiMap.java

@ -0,0 +1,58 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Comparator;
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.
*
* @param <K> the type of the keys in the map
* @param <V> the type of the values in the map
* @since 3.0
* @version $Id: SortedBidiMap.java 1543255 2013-11-19 00:45:24Z ggregory $
*/
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
*/
SortedBidiMap<V, K> inverseBidiMap();
/**
* Get the comparator used for the values in the value-to-key map aspect.
* @return Comparator<? super V>
*/
Comparator<? super V> valueComparator();
}

250
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/SplitMapUtils.java

@ -0,0 +1,250 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.map.EntrySetToMapIteratorAdapter;
import com.fr.third.org.apache.commons.collections4.map.UnmodifiableEntrySet;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
import com.fr.third.org.apache.commons.collections4.collection.UnmodifiableCollection;
import com.fr.third.org.apache.commons.collections4.iterators.UnmodifiableMapIterator;
import com.fr.third.org.apache.commons.collections4.map.EntrySetToMapIteratorAdapter;
import com.fr.third.org.apache.commons.collections4.map.UnmodifiableEntrySet;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
/**
* Utilities for working with "split maps:" objects that implement {@link Put}
* and/or {@link Get} but not {@link Map}.
*
* @since 4.0
* @version $Id: SplitMapUtils.java 1686855 2015-06-22 13:00:27Z tn $
*
* @see Get
* @see Put
*/
public class SplitMapUtils {
/**
* <code>SplitMapUtils</code> should not normally be instantiated.
*/
private SplitMapUtils() {}
//-----------------------------------------------------------------------
private static class WrappedGet<K, V> implements IterableMap<K, V>, Unmodifiable {
private final Get<K, V> get;
private WrappedGet(final Get<K, V> get) {
this.get = get;
}
public void clear() {
throw new UnsupportedOperationException();
}
public boolean containsKey(final Object key) {
return get.containsKey(key);
}
public boolean containsValue(final Object value) {
return get.containsValue(value);
}
public Set<Map.Entry<K, V>> entrySet() {
return UnmodifiableEntrySet.unmodifiableEntrySet(get.entrySet());
}
@Override
public boolean equals(final Object arg0) {
if (arg0 == this) {
return true;
}
return arg0 instanceof WrappedGet && ((WrappedGet<?, ?>) arg0).get.equals(this.get);
}
public V get(final Object key) {
return get.get(key);
}
@Override
public int hashCode() {
return ("WrappedGet".hashCode() << 4) | get.hashCode();
}
public boolean isEmpty() {
return get.isEmpty();
}
public Set<K> keySet() {
return UnmodifiableSet.unmodifiableSet(get.keySet());
}
public V put(final K key, final V value) {
throw new UnsupportedOperationException();
}
public void putAll(final Map<? extends K, ? extends V> t) {
throw new UnsupportedOperationException();
}
public V remove(final Object key) {
return get.remove(key);
}
public int size() {
return get.size();
}
public Collection<V> values() {
return UnmodifiableCollection.unmodifiableCollection(get.values());
}
public MapIterator<K, V> mapIterator() {
MapIterator<K, V> it;
if (get instanceof IterableGet) {
it = ((IterableGet<K, V>) get).mapIterator();
} else {
it = new EntrySetToMapIteratorAdapter<K, V>(get.entrySet());
}
return UnmodifiableMapIterator.unmodifiableMapIterator(it);
}
}
private static class WrappedPut<K, V> implements Map<K, V>, Put<K, V> {
private final Put<K, V> put;
private WrappedPut(final Put<K, V> put) {
this.put = put;
}
public void clear() {
put.clear();
}
public boolean containsKey(final Object key) {
throw new UnsupportedOperationException();
}
public boolean containsValue(final Object value) {
throw new UnsupportedOperationException();
}
public Set<Map.Entry<K, V>> entrySet() {
throw new UnsupportedOperationException();
}
@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
return obj instanceof WrappedPut && ((WrappedPut<?, ?>) obj).put.equals(this.put);
}
public V get(final Object key) {
throw new UnsupportedOperationException();
}
@Override
public int hashCode() {
return ("WrappedPut".hashCode() << 4) | put.hashCode();
}
public boolean isEmpty() {
throw new UnsupportedOperationException();
}
public Set<K> keySet() {
throw new UnsupportedOperationException();
}
@SuppressWarnings("unchecked")
public V put(final K key, final V value) {
return (V) put.put(key, value);
}
public void putAll(final Map<? extends K, ? extends V> t) {
put.putAll(t);
}
public V remove(final Object key) {
throw new UnsupportedOperationException();
}
public int size() {
throw new UnsupportedOperationException();
}
public Collection<V> values() {
throw new UnsupportedOperationException();
}
}
//-----------------------------------------------------------------------
/**
* Get the specified {@link Get} as an instance of {@link IterableMap}.
* If <code>get</code> implements {@link IterableMap} directly, no conversion will take place.
* If <code>get</code> implements {@link Map} but not {@link IterableMap} it will be decorated.
* Otherwise an {@link Unmodifiable} {@link IterableMap} will be returned.
* @param <K> the key type
* @param <V> the value type
* @param get to wrap, must not be null
* @return {@link IterableMap}
* @throws NullPointerException if the argument is null
*/
@SuppressWarnings("unchecked")
public static <K, V> IterableMap<K, V> readableMap(final Get<K, V> get) {
if (get == null) {
throw new NullPointerException("Get must not be null");
}
if (get instanceof Map) {
return get instanceof IterableMap ?
((IterableMap<K, V>) get) :
MapUtils.iterableMap((Map<K, V>) get);
}
return new WrappedGet<K, V>(get);
}
/**
* Get the specified {@link Put} as an instanceof {@link Map}.
* If <code>put</code> implements {@link Map} directly, no conversion will take place.
* Otherwise a <em>write-only</em> {@link Map} will be returned. On such a {@link Map}
* it is recommended that the result of #put(K, V) be discarded as it likely will not
* match <code>V</code> at runtime.
*
* @param <K> the key type
* @param <V> the element type
* @param put to wrap, must not be null
* @return {@link Map}
* @throws NullPointerException if the argument is null
*/
@SuppressWarnings("unchecked")
public static <K, V> Map<K, V> writableMap(final Put<K, V> put) {
if (put == null) {
throw new NullPointerException("Put must not be null");
}
if (put instanceof Map) {
return (Map<K, V>) put;
}
return new WrappedPut<K, V>(put);
}
}

51
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Transformer.java

@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
/**
* 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 invocation, returning a constant,
* cloning and returning the string value.
*
* @param <I> the input type to the transformer
* @param <O> the output type from the transformer
*
* @since 1.0
* @version $Id: Transformer.java 1543278 2013-11-19 00:54:07Z ggregory $
*/
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
*/
O transform(I input);
}

499
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/TransformerUtils.java

@ -0,0 +1,499 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.Collection;
import java.util.Map;
import com.fr.third.org.apache.commons.collections4.functors.ChainedTransformer;
import com.fr.third.org.apache.commons.collections4.functors.CloneTransformer;
import com.fr.third.org.apache.commons.collections4.functors.ClosureTransformer;
import com.fr.third.org.apache.commons.collections4.functors.ConstantTransformer;
import com.fr.third.org.apache.commons.collections4.functors.EqualPredicate;
import com.fr.third.org.apache.commons.collections4.functors.ExceptionTransformer;
import com.fr.third.org.apache.commons.collections4.functors.FactoryTransformer;
import com.fr.third.org.apache.commons.collections4.functors.IfTransformer;
import com.fr.third.org.apache.commons.collections4.functors.InstantiateTransformer;
import com.fr.third.org.apache.commons.collections4.functors.InvokerTransformer;
import com.fr.third.org.apache.commons.collections4.functors.MapTransformer;
import com.fr.third.org.apache.commons.collections4.functors.NOPTransformer;
import com.fr.third.org.apache.commons.collections4.functors.PredicateTransformer;
import com.fr.third.org.apache.commons.collections4.functors.StringValueTransformer;
import com.fr.third.org.apache.commons.collections4.functors.SwitchTransformer;
import com.fr.third.org.apache.commons.collections4.functors.ChainedTransformer;
import com.fr.third.org.apache.commons.collections4.functors.CloneTransformer;
import com.fr.third.org.apache.commons.collections4.functors.ClosureTransformer;
import com.fr.third.org.apache.commons.collections4.functors.ConstantTransformer;
import com.fr.third.org.apache.commons.collections4.functors.EqualPredicate;
import com.fr.third.org.apache.commons.collections4.functors.ExceptionTransformer;
import com.fr.third.org.apache.commons.collections4.functors.FactoryTransformer;
import com.fr.third.org.apache.commons.collections4.functors.IfTransformer;
import com.fr.third.org.apache.commons.collections4.functors.InstantiateTransformer;
import com.fr.third.org.apache.commons.collections4.functors.InvokerTransformer;
import com.fr.third.org.apache.commons.collections4.functors.MapTransformer;
import com.fr.third.org.apache.commons.collections4.functors.NOPTransformer;
import com.fr.third.org.apache.commons.collections4.functors.PredicateTransformer;
import com.fr.third.org.apache.commons.collections4.functors.StringValueTransformer;
import com.fr.third.org.apache.commons.collections4.functors.SwitchTransformer;
/**
* <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>If - calls one transformer or another based on a predicate
* <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>
* <p>
* Since v4.1 only transformers which are considered to be unsafe are
* Serializable. Transformers considered to be unsafe for serialization are:
* <ul>
* <li>Invoker
* <li>Clone
* <li>Instantiate
* </ul>
*
* @since 3.0
* @version $Id: TransformerUtils.java 1714362 2015-11-14 20:38:02Z tn $
*/
public class TransformerUtils {
/**
* This class is not normally instantiated.
*/
private TransformerUtils() {}
/**
* Gets a transformer that always throws an exception.
* This could be useful during testing as a placeholder.
*
* @param <I> the input type
* @param <O> the output type
* @return the transformer
* @see ExceptionTransformer
*/
public static <I, O> Transformer<I, O> exceptionTransformer() {
return ExceptionTransformer.exceptionTransformer();
}
/**
* Gets a transformer that always returns null.
*
* @param <I> the input type
* @param <O> the output type
* @return the transformer
* @see ConstantTransformer
*/
public static <I, O> Transformer<I, O> nullTransformer() {
return ConstantTransformer.nullTransformer();
}
/**
* 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).
*
* @param <T> the input/output type
* @return the transformer
* @see NOPTransformer
*/
public static <T> Transformer<T, T> nopTransformer() {
return NOPTransformer.nopTransformer();
}
/**
* 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>
*
* @param <T> the input/output type
* @return the transformer
* @see CloneTransformer
*/
public static <T> Transformer<T, T> cloneTransformer() {
return CloneTransformer.cloneTransformer();
}
/**
* Creates a Transformer that will return the same object each time the
* transformer is used.
*
* @param <I> the input type
* @param <O> the output type
* @param constantToReturn the constant object to return each time in the transformer
* @return the transformer.
* @see ConstantTransformer
*/
public static <I, O> Transformer<I, O> constantTransformer(final O constantToReturn) {
return ConstantTransformer.constantTransformer(constantToReturn);
}
/**
* Creates a Transformer that calls a Closure each time the transformer is used.
* The transformer returns the input object.
*
* @param <T> the input/output type
* @param closure the closure to run each time in the transformer, not null
* @return the transformer
* @throws NullPointerException if the closure is null
* @see ClosureTransformer
*/
public static <T> Transformer<T, T> asTransformer(final Closure<? super T> closure) {
return ClosureTransformer.closureTransformer(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 <T> the input type
* @param predicate the predicate to run each time in the transformer, not null
* @return the transformer
* @throws NullPointerException if the predicate is null
* @see PredicateTransformer
*/
public static <T> Transformer<T, Boolean> asTransformer(final Predicate<? super T> predicate) {
return PredicateTransformer.predicateTransformer(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 <I> the input type
* @param <O> the output type
* @param factory the factory to run each time in the transformer, not null
* @return the transformer
* @throws NullPointerException if the factory is null
* @see FactoryTransformer
*/
public static <I, O> Transformer<I, O> asTransformer(final Factory<? extends O> factory) {
return FactoryTransformer.factoryTransformer(factory);
}
/**
* Create a new Transformer that calls each transformer in turn, passing the
* result into the next transformer.
*
* @param <T> the input/output type
* @param transformers an array of transformers to chain
* @return the transformer
* @throws NullPointerException if the transformers array or any of the transformers is null
* @see ChainedTransformer
*/
public static <T> Transformer<T, T> chainedTransformer(
final Transformer<? super T, ? extends T>... transformers) {
return ChainedTransformer.chainedTransformer(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 <T> the input/output type
* @param transformers a collection of transformers to chain
* @return the transformer
* @throws NullPointerException if the transformers collection or any of the transformers is null
* @see ChainedTransformer
*/
public static <T> Transformer<T, T> chainedTransformer(
final Collection<? extends Transformer<? super T, ? extends T>> transformers) {
return ChainedTransformer.chainedTransformer(transformers);
}
/**
* Create a new Transformer that calls the transformer if the predicate is true,
* otherwise the input object is returned unchanged.
*
* @param <T> the input / output type
* @param predicate the predicate to switch on
* @param trueTransformer the transformer called if the predicate is true
* @return the transformer
* @throws NullPointerException if either the predicate or transformer is null
* @see IfTransformer
* @since 4.1
*/
public static <T> Transformer<T, T> ifTransformer(final Predicate<? super T> predicate,
final Transformer<? super T, ? extends T> trueTransformer) {
return IfTransformer.ifTransformer(predicate, trueTransformer);
}
/**
* Create a new Transformer that calls one of two transformers depending
* on the specified predicate.
*
* @param <I> the input type
* @param <O> the output type
* @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 NullPointerException if either the predicate or transformer is null
* @see IfTransformer
* @since 4.1
*/
public static <I, O> Transformer<I, O> ifTransformer(final Predicate<? super I> predicate,
final Transformer<? super I, ? extends O> trueTransformer,
final Transformer<? super I, ? extends O> falseTransformer) {
return IfTransformer.ifTransformer(predicate, trueTransformer, falseTransformer);
}
/**
* Create a new Transformer that calls one of two transformers depending
* on the specified predicate.
*
* @param <I> the input type
* @param <O> the output type
* @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 NullPointerException if either the predicate or transformer is null
* @see SwitchTransformer
* @deprecated as of 4.1, use {@link #ifTransformer(Predicate, Transformer, Transformer))
*/
@SuppressWarnings("unchecked")
@Deprecated
public static <I, O> Transformer<I, O> switchTransformer(final Predicate<? super I> predicate,
final Transformer<? super I, ? extends O> trueTransformer,
final Transformer<? super I, ? extends O> falseTransformer) {
return SwitchTransformer.switchTransformer(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 <I> the input type
* @param <O> the output type
* @param predicates an array of predicates to check
* @param transformers an array of transformers to call
* @return the transformer
* @throws NullPointerException if the either array is null
* @throws NullPointerException if any element in the arrays is null
* @throws IllegalArgumentException if the arrays have different sizes
* @see SwitchTransformer
*/
public static <I, O> Transformer<I, O> switchTransformer(final Predicate<? super I>[] predicates,
final Transformer<? super I, ? extends O>[] transformers) {
return SwitchTransformer.switchTransformer(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 <I> the input type
* @param <O> the output type
* @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 NullPointerException if the either array is null
* @throws NullPointerException if any element in the arrays is null
* @throws IllegalArgumentException if the arrays have different sizes
* @see SwitchTransformer
*/
public static <I, O> Transformer<I, O> switchTransformer(final Predicate<? super I>[] predicates,
final Transformer<? super I, ? extends O>[] transformers,
final Transformer<? super I, ? extends O> defaultTransformer) {
return SwitchTransformer.switchTransformer(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 <I> the input type
* @param <O> the output type
* @param predicatesAndTransformers a map of predicates to transformers
* @return the transformer
* @throws NullPointerException if the map is null
* @throws NullPointerException if any transformer in the map is null
* @throws ClassCastException if the map elements are of the wrong type
* @see SwitchTransformer
*/
public static <I, O> Transformer<I, O> switchTransformer(
final Map<Predicate<I>, Transformer<I, O>> predicatesAndTransformers) {
return SwitchTransformer.switchTransformer(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 <I> the input type
* @param <O> the output type
* @param objectsAndTransformers a map of objects to transformers
* @return the transformer
* @throws NullPointerException if the map is null
* @throws NullPointerException if any transformer in the map is null
* @see SwitchTransformer
*/
@SuppressWarnings("unchecked")
public static <I, O> Transformer<I, O> switchMapTransformer(
final Map<I, Transformer<I, O>> objectsAndTransformers) {
if (objectsAndTransformers == null) {
throw new NullPointerException("The object and transformer map must not be null");
}
final Transformer<? super I, ? extends O> def = objectsAndTransformers.remove(null);
final int size = objectsAndTransformers.size();
final Transformer<? super I, ? extends O>[] trs = new Transformer[size];
final Predicate<I>[] preds = new Predicate[size];
int i = 0;
for (final Map.Entry<I, Transformer<I, O>> entry : objectsAndTransformers.entrySet()) {
preds[i] = EqualPredicate.<I>equalPredicate(entry.getKey());
trs[i++] = entry.getValue();
}
return TransformerUtils.switchTransformer(preds, trs, def);
}
/**
* Gets a Transformer that expects an input Class object that it will instantiate.
*
* @param <T> the output type
* @return the transformer
* @see InstantiateTransformer
*/
public static <T> Transformer<Class<? extends T>, T> instantiateTransformer() {
return InstantiateTransformer.instantiateTransformer();
}
/**
* 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 <T> the output type
* @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 InstantiateTransformer
*/
public static <T> Transformer<Class<? extends T>, T> instantiateTransformer(
final Class<?>[] paramTypes, final Object[] args) {
return InstantiateTransformer.instantiateTransformer(paramTypes, args);
}
/**
* Creates a Transformer that uses the passed in Map to transform the input
* object (as a simple lookup).
*
* @param <I> the input type
* @param <O> the output type
* @param map the map to use to transform the objects
* @return the transformer, or {@link ConstantTransformer#nullTransformer()} if the
* {@code map} is {@code null}
* @see MapTransformer
*/
public static <I, O> Transformer<I, O> mapTransformer(final Map<? super I, ? extends O> map) {
return MapTransformer.mapTransformer(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.
*
* @param <I> the input type
* @param <O> the output type
* @param methodName the method name to call on the input object, may not be null
* @return the transformer
* @throws NullPointerException if the methodName is null.
* @see InvokerTransformer
*/
public static <I, O> Transformer<I, O> invokerTransformer(final String methodName) {
return InvokerTransformer.invokerTransformer(methodName, null, null);
}
/**
* Gets a Transformer that invokes a method on the input object.
* The method parameters are specified. If the input object is {@code null},
* {@code null} is returned.
*
* @param <I> the input type
* @param <O> the output type
* @param methodName the name of the method
* @param paramTypes the parameter types
* @param args the arguments
* @return the transformer
* @throws NullPointerException if the method name is null
* @throws IllegalArgumentException if the paramTypes and args don't match
* @see InvokerTransformer
*/
public static <I, O> Transformer<I, O> invokerTransformer(final String methodName, final Class<?>[] paramTypes,
final Object[] args) {
return InvokerTransformer.invokerTransformer(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'.
*
* @param <T> the input type
* @return the transformer
* @see StringValueTransformer
*/
public static <T> Transformer<T, String> stringValueTransformer() {
return StringValueTransformer.stringValueTransformer();
}
}

47
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Trie.java

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import java.util.SortedMap;
/**
* Defines the interface for a prefix tree, an ordered tree data structure. For
* more information, see <a href="http://en.wikipedia.org/wiki/Trie">Tries</a>.
*
* @since 4.0
* @version $Id: Trie.java 1543279 2013-11-19 00:54:31Z ggregory $
*/
public interface Trie<K, V> extends IterableSortedMap<K, V> {
/**
* Returns a view of this {@link Trie} of all elements that are prefixed
* by the given key.
* <p>
* In a {@link Trie} with fixed size keys, this is essentially a
* {@link #get(Object)} operation.
* <p>
* For example, if the {@link Trie} contains 'Anna', 'Anael',
* 'Analu', 'Andreas', 'Andrea', 'Andres', and 'Anatole', then
* a lookup of 'And' would return 'Andreas', 'Andrea', and 'Andres'.
*
* @param key the key used in the search
* @return a {@link SortedMap} view of this {@link Trie} with all elements whose
* key is prefixed by the search key
*/
SortedMap<K, V> prefixMap(K key);
}

50
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/TrieUtils.java

@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
import com.fr.third.org.apache.commons.collections4.trie.UnmodifiableTrie;
import com.fr.third.org.apache.commons.collections4.trie.UnmodifiableTrie;
/**
* A collection of {@link Trie} utilities.
*
* @since 4.0
* @version $Id: TrieUtils.java 1686855 2015-06-22 13:00:27Z tn $
*/
public class TrieUtils {
/**
* {@link TrieUtils} should not normally be instantiated.
*/
private TrieUtils() {}
/**
* Returns an unmodifiable instance of a {@link Trie}
*
* @param <K> the key type
* @param <V> the value type
* @param trie the trie to make unmodifiable, must not be null
* @return an unmodifiable trie backed by the given trie
* @throws NullPointerException if trie is null
*
* @see java.util.Collections#unmodifiableMap(java.util.Map)
*/
public static <K, V> Trie<K, V> unmodifiableTrie(final Trie<K, ? extends V> trie) {
return UnmodifiableTrie.unmodifiableTrie(trie);
}
}

38
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/Unmodifiable.java

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4;
/**
* Marker interface for collections, 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 {@code java.util Collections}
* then the interface won't be there.
*
* @since 3.0
* @version $Id: Unmodifiable.java 1477779 2013-04-30 18:55:24Z tn $
*/
public interface Unmodifiable {
// marker interface - no methods to implement
}

98
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/AbstractBagDecorator.java

@ -0,0 +1,98 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.Bag;
import com.fr.third.org.apache.commons.collections4.collection.AbstractCollectionDecorator;
/**
* Decorates another <code>Bag</code> to provide additional behaviour.
* <p>
* Methods are forwarded directly to the decorated bag.
*
* @since 3.0
* @version $Id: AbstractBagDecorator.java 1686855 2015-06-22 13:00:27Z tn $
*/
public abstract class AbstractBagDecorator<E>
extends AbstractCollectionDecorator<E> implements Bag<E> {
/** Serialization version */
private static final long serialVersionUID = -3768146017343785417L;
/**
* Constructor only used in deserialization, do not use otherwise.
* @since 3.1
*/
protected AbstractBagDecorator() {
super();
}
/**
* Constructor that wraps (not copies).
*
* @param bag the bag to decorate, must not be null
* @throws NullPointerException if bag is null
*/
protected AbstractBagDecorator(final Bag<E> bag) {
super(bag);
}
/**
* Gets the bag being decorated.
*
* @return the decorated bag
*/
@Override
protected Bag<E> decorated() {
return (Bag<E>) super.decorated();
}
@Override
public boolean equals(final Object object) {
return object == this || decorated().equals(object);
}
@Override
public int hashCode() {
return decorated().hashCode();
}
//-----------------------------------------------------------------------
@Override
public int getCount(final Object object) {
return decorated().getCount(object);
}
@Override
public boolean add(final E object, final int count) {
return decorated().add(object, count);
}
@Override
public boolean remove(final Object object, final int count) {
return decorated().remove(object, count);
}
@Override
public Set<E> uniqueSet() {
return decorated().uniqueSet();
}
}

625
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/AbstractMapBag.java

@ -0,0 +1,625 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
import com.fr.third.org.apache.commons.collections4.Bag;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
/**
* 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.
*
* @since 3.0 (previously DefaultMapBag v2.0)
* @version $Id: AbstractMapBag.java 1684859 2015-06-11 11:57:24Z tn $
*/
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;
/** Unique view of the elements */
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(final 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
*/
@Override
public int size() {
return size;
}
/**
* Returns true if the underlying map is empty.
*
* @return true if bag is empty
*/
@Override
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
*/
@Override
public int getCount(final Object object) {
final 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
*/
@Override
public boolean contains(final 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
*/
@Override
public boolean containsAll(final Collection<?> coll) {
if (coll instanceof Bag) {
return containsAll((Bag<?>) coll);
}
return containsAll(new HashBag<Object>(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(final Bag<?> other) {
final Iterator<?> it = other.uniqueSet().iterator();
while (it.hasNext()) {
final Object current = it.next();
if (getCount(current) < other.getCount(current)) {
return false;
}
}
return true;
}
//-----------------------------------------------------------------------
/**
* Gets an iterator over the bag elements. Elements present in the Bag more
* than once will be returned repeatedly.
*
* @return the iterator
*/
@Override
public Iterator<E> iterator() {
return new BagIterator<E>(this);
}
/**
* Inner class iterator for the Bag.
*/
static class BagIterator<E> implements Iterator<E> {
private final AbstractMapBag<E> parent;
private final 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(final AbstractMapBag<E> parent) {
this.parent = parent;
this.entryIterator = parent.map.entrySet().iterator();
this.current = null;
this.mods = parent.modCount;
this.canRemove = false;
}
/** {@inheritDoc} */
@Override
public boolean hasNext() {
return itemCount > 0 || entryIterator.hasNext();
}
/** {@inheritDoc} */
@Override
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();
}
/** {@inheritDoc} */
@Override
public void remove() {
if (parent.modCount != mods) {
throw new ConcurrentModificationException();
}
if (canRemove == false) {
throw new IllegalStateException();
}
final MutableInteger mut = current.getValue();
if (mut.value > 1) {
mut.value--;
} else {
entryIterator.remove();
}
parent.size--;
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>
*/
@Override
public boolean add(final 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>
*/
@Override
public boolean add(final E object, final int nCopies) {
modCount++;
if (nCopies > 0) {
final MutableInteger mut = map.get(object);
size += nCopies;
if (mut == null) {
map.put(object, new MutableInteger(nCopies));
return true;
}
mut.value += nCopies;
return false;
}
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
*/
@Override
public boolean addAll(final Collection<? extends E> coll) {
boolean changed = false;
final Iterator<? extends E> i = coll.iterator();
while (i.hasNext()) {
final boolean added = add(i.next());
changed = changed || added;
}
return changed;
}
//-----------------------------------------------------------------------
/**
* Clears the bag by clearing the underlying map.
*/
@Override
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
*/
@Override
public boolean remove(final Object object) {
final 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
*/
@Override
public boolean remove(final Object object, final int nCopies) {
final MutableInteger mut = map.get(object);
if (mut == null) {
return false;
}
if (nCopies <= 0) {
return false;
}
modCount++;
if (nCopies < mut.value) {
mut.value -= nCopies;
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
*/
@Override
public boolean removeAll(final Collection<?> coll) {
boolean result = false;
if (coll != null) {
final Iterator<?> i = coll.iterator();
while (i.hasNext()) {
final boolean changed = remove(i.next(), 1);
result = result || changed;
}
}
return result;
}
/**
* Remove any members of the bag that are not in the given bag, respecting
* cardinality.
*
* @param coll the collection to retain
* @return true if this call changed the collection
*/
@Override
public boolean retainAll(final Collection<?> coll) {
if (coll instanceof Bag) {
return retainAll((Bag<?>) coll);
}
return retainAll(new HashBag<Object>(coll));
}
/**
* Remove any members of the bag that are not in the given bag, respecting
* cardinality.
* @see #retainAll(Collection)
*
* @param other the bag to retain
* @return <code>true</code> if this call changed the collection
*/
boolean retainAll(final Bag<?> other) {
boolean result = false;
final Bag<E> excess = new HashBag<E>();
final Iterator<E> i = uniqueSet().iterator();
while (i.hasNext()) {
final E current = i.next();
final int myCount = getCount(current);
final 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(final int value) {
this.value = value;
}
@Override
public boolean equals(final Object obj) {
if (obj instanceof MutableInteger == false) {
return false;
}
return ((MutableInteger) obj).value == value;
}
@Override
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
*/
@Override
public Object[] toArray() {
final Object[] result = new Object[size()];
int i = 0;
final Iterator<E> it = map.keySet().iterator();
while (it.hasNext()) {
final 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.
* If the input array has more elements than are in the bag,
* trailing elements will be set to null.
*
* @param <T> the type of the array elements
* @param array the array to populate
* @return an array of all of this bag's elements
* @throws ArrayStoreException if the runtime type of the specified array is not
* a supertype of the runtime type of the elements in this list
* @throws NullPointerException if the specified array is null
*/
@Override
public <T> T[] toArray(T[] array) {
final int size = size();
if (array.length < size) {
@SuppressWarnings("unchecked") // safe as both are of type T
final T[] unchecked = (T[]) Array.newInstance(array.getClass().getComponentType(), size);
array = unchecked;
}
int i = 0;
final Iterator<E> it = map.keySet().iterator();
while (it.hasNext()) {
final E current = it.next();
for (int index = getCount(current); index > 0; index--) {
// unsafe, will throw ArrayStoreException if types are not compatible, see javadoc
@SuppressWarnings("unchecked")
final T unchecked = (T) current;
array[i++] = unchecked;
}
}
while (i < array.length) {
array[i++] = null;
}
return array;
}
/**
* Returns an unmodifiable view of the underlying map's key set.
*
* @return the set of unique elements in this bag
*/
@Override
public Set<E> uniqueSet() {
if (uniqueSet == null) {
uniqueSet = UnmodifiableSet.<E> unmodifiableSet(map.keySet());
}
return uniqueSet;
}
//-----------------------------------------------------------------------
/**
* Write the map out using a custom routine.
* @param out the output stream
* @throws IOException any of the usual I/O related exceptions
*/
protected void doWriteObject(final ObjectOutputStream out) throws IOException {
out.writeInt(map.size());
for (final Entry<E, MutableInteger> entry : map.entrySet()) {
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 any of the usual I/O related exceptions
* @throws ClassNotFoundException if the stream contains an object which class can not be loaded
* @throws ClassCastException if the stream does not contain the correct objects
*/
protected void doReadObject(final Map<E, MutableInteger> map, final ObjectInputStream in)
throws IOException, ClassNotFoundException {
this.map = map;
final int entrySize = in.readInt();
for (int i = 0; i < entrySize; i++) {
@SuppressWarnings("unchecked") // This will fail at runtime if the stream is incorrect
final E obj = (E) in.readObject();
final 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
*/
@Override
public boolean equals(final Object object) {
if (object == this) {
return true;
}
if (object instanceof Bag == false) {
return false;
}
final Bag<?> other = (Bag<?>) object;
if (other.size() != size()) {
return false;
}
for (final E element : map.keySet()) {
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
*/
@Override
public int hashCode() {
int total = 0;
for (final Entry<E, MutableInteger> entry : map.entrySet()) {
final E element = entry.getKey();
final MutableInteger count = entry.getValue();
total += (element == null ? 0 : element.hashCode()) ^ count.value;
}
return total;
}
/**
* Implement a toString() method suitable for debugging.
*
* @return a debugging toString
*/
@Override
public String toString() {
if (size() == 0) {
return "[]";
}
final StringBuilder buf = new StringBuilder();
buf.append('[');
final Iterator<E> it = uniqueSet().iterator();
while (it.hasNext()) {
final Object current = it.next();
final int count = getCount(current);
buf.append(count);
buf.append(':');
buf.append(current);
if (it.hasNext()) {
buf.append(',');
}
}
buf.append(']');
return buf.toString();
}
}

82
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/AbstractSortedBagDecorator.java

@ -0,0 +1,82 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.util.Comparator;
import com.fr.third.org.apache.commons.collections4.SortedBag;
/**
* Decorates another <code>SortedBag</code> to provide additional behaviour.
* <p>
* Methods are forwarded directly to the decorated bag.
*
* @since 3.0
* @version $Id: AbstractSortedBagDecorator.java 1686855 2015-06-22 13:00:27Z tn $
*/
public abstract class AbstractSortedBagDecorator<E>
extends AbstractBagDecorator<E> implements SortedBag<E> {
/** Serialization version */
private static final long serialVersionUID = -8223473624050467718L;
/**
* Constructor only used in deserialization, do not use otherwise.
* @since 3.1
*/
protected AbstractSortedBagDecorator() {
super();
}
/**
* Constructor that wraps (not copies).
*
* @param bag the bag to decorate, must not be null
* @throws NullPointerException if bag is null
*/
protected AbstractSortedBagDecorator(final SortedBag<E> bag) {
super(bag);
}
/**
* Gets the bag being decorated.
*
* @return the decorated bag
*/
@Override
protected SortedBag<E> decorated() {
return (SortedBag<E>) super.decorated();
}
//-----------------------------------------------------------------------
@Override
public E first() {
return decorated().first();
}
@Override
public E last() {
return decorated().last();
}
@Override
public Comparator<? super E> comparator() {
return decorated().comparator();
}
}

243
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/CollectionBag.java

@ -0,0 +1,243 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.Iterator;
import com.fr.third.org.apache.commons.collections4.Bag;
/**
* Decorates another {@link Bag} to comply with the Collection contract.
* <p>
* By decorating an existing {@link Bag} instance with a {@link CollectionBag},
* it can be safely passed on to methods that require Collection types that
* are fully compliant with the Collection contract.
* <p>
* The method javadoc highlights the differences compared to the original Bag interface.
*
* @see Bag
* @param <E> the type held in the bag
* @since 4.0
* @version $Id: CollectionBag.java 1686855 2015-06-22 13:00:27Z tn $
*/
public final class CollectionBag<E> extends AbstractBagDecorator<E> {
/** Serialization version */
private static final long serialVersionUID = -2560033712679053143L;
/**
* Factory method to create a bag that complies to the Collection contract.
*
* @param <E> the type of the elements in the bag
* @param bag the bag to decorate, must not be null
* @return a Bag that complies to the Collection contract
* @throws NullPointerException if bag is null
*/
public static <E> Bag<E> collectionBag(final Bag<E> bag) {
return new CollectionBag<E>(bag);
}
//-----------------------------------------------------------------------
/**
* Constructor that wraps (not copies).
*
* @param bag the bag to decorate, must not be null
* @throws NullPointerException if bag is null
*/
public CollectionBag(final Bag<E> bag) {
super(bag);
}
//-----------------------------------------------------------------------
/**
* Write the collection out using a custom routine.
*
* @param out the output stream
* @throws IOException
*/
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(decorated());
}
/**
* Read the collection in using a custom routine.
*
* @param in the input stream
* @throws IOException
* @throws ClassNotFoundException
* @throws ClassCastException if deserialised object has wrong type
*/
@SuppressWarnings("unchecked") // will throw CCE, see Javadoc
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
setCollection((Collection<E>) in.readObject());
}
//-----------------------------------------------------------------------
// Collection interface
//-----------------------------------------------------------------------
/**
* <i>(Change)</i>
* Returns <code>true</code> if the bag contains all elements in
* the given collection, <b>not</b> respecting cardinality. That is,
* if the given collection <code>coll</code> contains at least one of
* every object contained in this object.
*
* @param coll the collection to check against
* @return <code>true</code> if the Bag contains at least one of every object in the collection
*/
@Override
public boolean containsAll(final Collection<?> coll) {
final Iterator<?> e = coll.iterator();
while (e.hasNext()) {
if(!contains(e.next())) {
return false;
}
}
return true;
}
/**
* <i>(Change)</i>
* Adds one copy of the specified object to the Bag.
* <p>
* Since this method always increases the size of the bag, it
* will always return <code>true</code>.
*
* @param object the object to add
* @return <code>true</code>, always
*/
@Override
public boolean add(final E object) {
return add(object, 1);
}
@Override
public boolean addAll(final Collection<? extends E> coll) {
boolean changed = false;
final Iterator<? extends E> i = coll.iterator();
while (i.hasNext()) {
final boolean added = add(i.next(), 1);
changed = changed || added;
}
return changed;
}
/**
* <i>(Change)</i>
* Removes the first occurrence of the given object from the bag.
* <p>
* This will also remove the object from the {@link #uniqueSet()} if the
* bag contains no occurrence anymore of the object after this operation.
*
* @param object the object to remove
* @return <code>true</code> if this call changed the collection
*/
@Override
public boolean remove(final Object object) {
return remove(object, 1);
}
/**
* <i>(Change)</i>
* Remove all elements represented in the given collection,
* <b>not</b> respecting cardinality. That is, 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
*/
@Override
public boolean removeAll(final Collection<?> coll) {
if (coll != null) {
boolean result = false;
final Iterator<?> i = coll.iterator();
while (i.hasNext()) {
final Object obj = i.next();
final boolean changed = remove(obj, getCount(obj));
result = result || changed;
}
return result;
} else {
// let the decorated bag handle the case of null argument
return decorated().removeAll(null);
}
}
/**
* <i>(Change)</i>
* Remove any members of the bag that are not in the given collection,
* <i>not</i> respecting cardinality. That is, any object in the given
* collection <code>coll</code> will be retained in the bag with the same
* number of copies prior to this operation. All other objects will be
* completely removed from this bag.
* <p>
* This implementation iterates over the elements of this bag, checking
* each element in turn to see if it's contained in <code>coll</code>.
* If it's not contained, it's removed from this bag. As a consequence,
* it is advised to use a collection type for <code>coll</code> that provides
* a fast (e.g. O(1)) implementation of {@link Collection#contains(Object)}.
*
* @param coll the collection to retain
* @return <code>true</code> if this call changed the collection
*/
@Override
public boolean retainAll(final Collection<?> coll) {
if (coll != null) {
boolean modified = false;
final Iterator<E> e = iterator();
while (e.hasNext()) {
if (!coll.contains(e.next())) {
e.remove();
modified = true;
}
}
return modified;
} else {
// let the decorated bag handle the case of null argument
return decorated().retainAll(null);
}
}
//-----------------------------------------------------------------------
// Bag interface
//-----------------------------------------------------------------------
/**
* <i>(Change)</i>
* Adds <code>count</code> copies of the specified object to the Bag.
* <p>
* Since this method always increases the size of the bag, it
* will always return <code>true</code>.
*
* @param object the object to add
* @param count the number of copies to add
* @return <code>true</code>, always
*/
@Override
public boolean add(final E object, final int count) {
decorated().add(object, count);
return true;
}
}

168
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/CollectionSortedBag.java

@ -0,0 +1,168 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.Iterator;
import com.fr.third.org.apache.commons.collections4.SortedBag;
/**
* Decorates another {@link SortedBag} to comply with the Collection contract.
*
* @since 4.0
* @version $Id: CollectionSortedBag.java 1686855 2015-06-22 13:00:27Z tn $
*/
public final class CollectionSortedBag<E> extends AbstractSortedBagDecorator<E> {
/** Serialization version */
private static final long serialVersionUID = -2560033712679053143L;
/**
* Factory method to create a sorted bag that complies to the Collection contract.
*
* @param <E> the type of the elements in the bag
* @param bag the sorted bag to decorate, must not be null
* @return a SortedBag that complies to the Collection contract
* @throws NullPointerException if bag is null
*/
public static <E> SortedBag<E> collectionSortedBag(final SortedBag<E> bag) {
return new CollectionSortedBag<E>(bag);
}
//-----------------------------------------------------------------------
/**
* Constructor that wraps (not copies).
*
* @param bag the sorted bag to decorate, must not be null
* @throws NullPointerException if bag is null
*/
public CollectionSortedBag(final SortedBag<E> bag) {
super(bag);
}
//-----------------------------------------------------------------------
/**
* Write the collection out using a custom routine.
*
* @param out the output stream
* @throws IOException
*/
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(decorated());
}
/**
* Read the collection in using a custom routine.
*
* @param in the input stream
* @throws IOException
* @throws ClassNotFoundException
* @throws ClassCastException if deserialised object has wrong type
*/
@SuppressWarnings("unchecked") // will throw CCE, see Javadoc
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
setCollection((Collection<E>) in.readObject());
}
//-----------------------------------------------------------------------
// Collection interface
//-----------------------------------------------------------------------
@Override
public boolean containsAll(final Collection<?> coll) {
final Iterator<?> e = coll.iterator();
while (e.hasNext()) {
if(!contains(e.next())) {
return false;
}
}
return true;
}
@Override
public boolean add(final E object) {
return add(object, 1);
}
@Override
public boolean addAll(final Collection<? extends E> coll) {
boolean changed = false;
final Iterator<? extends E> i = coll.iterator();
while (i.hasNext()) {
final boolean added = add(i.next(), 1);
changed = changed || added;
}
return changed;
}
@Override
public boolean remove(final Object object) {
return remove(object, 1);
}
@Override
public boolean removeAll(final Collection<?> coll) {
if (coll != null) {
boolean result = false;
final Iterator<?> i = coll.iterator();
while (i.hasNext()) {
final Object obj = i.next();
final boolean changed = remove(obj, getCount(obj));
result = result || changed;
}
return result;
} else {
// let the decorated bag handle the case of null argument
return decorated().removeAll(null);
}
}
@Override
public boolean retainAll(final Collection<?> coll) {
if (coll != null) {
boolean modified = false;
final Iterator<E> e = iterator();
while (e.hasNext()) {
if (!coll.contains(e.next())) {
e.remove();
modified = true;
}
}
return modified;
} else {
// let the decorated bag handle the case of null argument
return decorated().retainAll(null);
}
}
//-----------------------------------------------------------------------
// Bag interface
//-----------------------------------------------------------------------
@Override
public boolean add(final E object, final int count) {
decorated().add(object, count);
return true;
}
}

78
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/HashBag.java

@ -0,0 +1,78 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.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}, using a {@link HashMap} to provide the
* data storage. This is the standard implementation of a bag.
* <p>
* A {@code Bag} 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
* {@link Collection} interface specification.
*
* @since 3.0 (previously in main package v2.0)
* @version $Id: HashBag.java 1685902 2015-06-16 20:13:13Z tn $
*/
public class HashBag<E> extends AbstractMapBag<E> implements Serializable {
/** Serial version lock */
private static final long serialVersionUID = -6561115435802554013L;
/**
* Constructs an empty {@link HashBag}.
*/
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(final Collection<? extends E> coll) {
this();
addAll(coll);
}
//-----------------------------------------------------------------------
/**
* Write the bag out using a custom routine.
*/
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
super.doWriteObject(out);
}
/**
* Read the bag in using a custom routine.
*/
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
super.doReadObject(new HashMap<E, MutableInteger>(), in);
}
}

126
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/PredicatedBag.java

@ -0,0 +1,126 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.Predicate;
import com.fr.third.org.apache.commons.collections4.Bag;
import com.fr.third.org.apache.commons.collections4.Predicate;
import com.fr.third.org.apache.commons.collections4.collection.PredicatedCollection;
/**
* Decorates another {@link Bag} 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 {@link IllegalArgumentException} is thrown.
* <p>
* One usage would be to ensure that no null entries are added to the bag.
* <pre>
* Bag bag = PredicatedBag.predicatedBag(new HashBag(), NotNullPredicate.INSTANCE);
* </pre>
* <p>
* This class is Serializable from Commons Collections 3.1.
*
* @since 3.0
* @version $Id: PredicatedBag.java 1686855 2015-06-22 13:00:27Z tn $
*/
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 <E> the type of the elements in the bag
* @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 NullPointerException if bag or predicate is null
* @throws IllegalArgumentException if the bag contains invalid elements
* @since 4.0
*/
public static <E> PredicatedBag<E> predicatedBag(final Bag<E> bag, final 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 NullPointerException if bag or predicate is null
* @throws IllegalArgumentException if the bag contains invalid elements
*/
protected PredicatedBag(final Bag<E> bag, final Predicate<? super E> predicate) {
super(bag, predicate);
}
/**
* Gets the decorated bag.
*
* @return the decorated bag
*/
@Override
protected Bag<E> decorated() {
return (Bag<E>) super.decorated();
}
@Override
public boolean equals(final Object object) {
return object == this || decorated().equals(object);
}
@Override
public int hashCode() {
return decorated().hashCode();
}
//-----------------------------------------------------------------------
@Override
public boolean add(final E object, final int count) {
validate(object);
return decorated().add(object, count);
}
@Override
public boolean remove(final Object object, final int count) {
return decorated().remove(object, count);
}
@Override
public Set<E> uniqueSet() {
return decorated().uniqueSet();
}
@Override
public int getCount(final Object object) {
return decorated().getCount(object);
}
}

108
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/PredicatedSortedBag.java

@ -0,0 +1,108 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.util.Comparator;
import com.fr.third.org.apache.commons.collections4.Predicate;
import com.fr.third.org.apache.commons.collections4.SortedBag;
/**
* Decorates another {@link SortedBag} 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 {@link IllegalArgumentException} is thrown.
* <p>
* One usage would be to ensure that no null entries are added to the bag.
* <pre>
* SortedBag bag = PredicatedSortedBag.predicatedSortedBag(new TreeBag(), NotNullPredicate.INSTANCE);
* </pre>
* <p>
* This class is Serializable from Commons Collections 3.1.
*
* @since 3.0
* @version $Id: PredicatedSortedBag.java 1686855 2015-06-22 13:00:27Z tn $
*/
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 <E> the type of the elements in the bag
* @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 NullPointerException if bag or predicate is null
* @throws IllegalArgumentException if the bag contains invalid elements
* @since 4.0
*/
public static <E> PredicatedSortedBag<E> predicatedSortedBag(final SortedBag<E> bag,
final Predicate<? super E> predicate) {
return new PredicatedSortedBag<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 NullPointerException if bag or predicate is null
* @throws IllegalArgumentException if the bag contains invalid elements
*/
protected PredicatedSortedBag(final SortedBag<E> bag, final Predicate<? super E> predicate) {
super(bag, predicate);
}
/**
* Gets the decorated sorted bag.
*
* @return the decorated bag
*/
@Override
protected SortedBag<E> decorated() {
return (SortedBag<E>) super.decorated();
}
//-----------------------------------------------------------------------
@Override
public E first() {
return decorated().first();
}
@Override
public E last() {
return decorated().last();
}
@Override
public Comparator<? super E> comparator() {
return decorated().comparator();
}
}

151
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/SynchronizedBag.java

@ -0,0 +1,151 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.Bag;
import com.fr.third.org.apache.commons.collections4.collection.SynchronizedCollection;
/**
* Decorates another {@link Bag} 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.
*
* @since 3.0
* @version $Id: SynchronizedBag.java 1686855 2015-06-22 13:00:27Z tn $
*/
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 <E> the type of the elements in the bag
* @param bag the bag to decorate, must not be null
* @return a new synchronized Bag
* @throws NullPointerException if bag is null
* @since 4.0
*/
public static <E> SynchronizedBag<E> synchronizedBag(final Bag<E> bag) {
return new SynchronizedBag<E>(bag);
}
//-----------------------------------------------------------------------
/**
* Constructor that wraps (not copies).
*
* @param bag the bag to decorate, must not be null
* @throws NullPointerException if bag is null
*/
protected SynchronizedBag(final 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 NullPointerException if bag or lock is null
*/
protected SynchronizedBag(final Bag<E> bag, final Object lock) {
super(bag, lock);
}
/**
* Gets the bag being decorated.
*
* @return the decorated bag
*/
protected Bag<E> getBag() {
return (Bag<E>) decorated();
}
@Override
public boolean equals(final Object object) {
if (object == this) {
return true;
}
synchronized (lock) {
return getBag().equals(object);
}
}
@Override
public int hashCode() {
synchronized (lock) {
return getBag().hashCode();
}
}
//-----------------------------------------------------------------------
@Override
public boolean add(final E object, final int count) {
synchronized (lock) {
return getBag().add(object, count);
}
}
@Override
public boolean remove(final Object object, final int count) {
synchronized (lock) {
return getBag().remove(object, count);
}
}
@Override
public Set<E> uniqueSet() {
synchronized (lock) {
final Set<E> set = getBag().uniqueSet();
return new SynchronizedBagSet(set, lock);
}
}
@Override
public int getCount(final Object object) {
synchronized (lock) {
return getBag().getCount(object);
}
}
//-----------------------------------------------------------------------
/**
* Synchronized Set for the Bag class.
*/
class SynchronizedBagSet extends SynchronizedCollection<E> implements Set<E> {
/** Serialization version */
private static final long serialVersionUID = 2990565892366827855L;
/**
* Constructor.
* @param set the set to decorate
* @param lock the lock to use, shared with the bag
*/
SynchronizedBagSet(final Set<E> set, final Object lock) {
super(set, lock);
}
}
}

108
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/SynchronizedSortedBag.java

@ -0,0 +1,108 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.util.Comparator;
import com.fr.third.org.apache.commons.collections4.Bag;
import com.fr.third.org.apache.commons.collections4.SortedBag;
/**
* Decorates another {@link SortedBag} 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.
*
* @since 3.0
* @version $Id: SynchronizedSortedBag.java 1686855 2015-06-22 13:00:27Z tn $
*/
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 <E> the type of the elements in the bag
* @param bag the bag to decorate, must not be null
* @return a new synchronized SortedBag
* @throws NullPointerException if bag is null
* @since 4.0
*/
public static <E> SynchronizedSortedBag<E> synchronizedSortedBag(final SortedBag<E> bag) {
return new SynchronizedSortedBag<E>(bag);
}
//-----------------------------------------------------------------------
/**
* Constructor that wraps (not copies).
*
* @param bag the bag to decorate, must not be null
* @throws NullPointerException if bag is null
*/
protected SynchronizedSortedBag(final 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 NullPointerException if bag or lock is null
*/
protected SynchronizedSortedBag(final Bag<E> bag, final Object lock) {
super(bag, lock);
}
/**
* Gets the bag being decorated.
*
* @return the decorated bag
*/
protected SortedBag<E> getSortedBag() {
return (SortedBag<E>) decorated();
}
//-----------------------------------------------------------------------
@Override
public synchronized E first() {
synchronized (lock) {
return getSortedBag().first();
}
}
@Override
public synchronized E last() {
synchronized (lock) {
return getSortedBag().last();
}
}
@Override
public synchronized Comparator<? super E> comparator() {
synchronized (lock) {
return getSortedBag().comparator();
}
}
}

150
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/TransformedBag.java

@ -0,0 +1,150 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.Transformer;
import com.fr.third.org.apache.commons.collections4.set.TransformedSet;
import com.fr.third.org.apache.commons.collections4.Bag;
import com.fr.third.org.apache.commons.collections4.Transformer;
import com.fr.third.org.apache.commons.collections4.collection.TransformedCollection;
import com.fr.third.org.apache.commons.collections4.set.TransformedSet;
/**
* Decorates another {@link Bag} 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.
*
* @since 3.0
* @version $Id: TransformedBag.java 1686855 2015-06-22 13:00:27Z tn $
*/
public class TransformedBag<E> extends TransformedCollection<E> implements Bag<E> {
/** 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. Contrast this with {@link #transformedBag(Bag, Transformer)}.
*
* @param <E> the type of the elements in the bag
* @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 NullPointerException if bag or transformer is null
* @since 4.0
*/
public static <E> Bag<E> transformingBag(final Bag<E> bag, final Transformer<? super E, ? extends E> transformer) {
return new TransformedBag<E>(bag, transformer);
}
/**
* Factory method to create a transforming bag that will transform
* existing contents of the specified bag.
* <p>
* If there are any elements already in the bag being decorated, they
* will be transformed by this method.
* Contrast this with {@link #transformingBag(Bag, Transformer)}.
*
* @param <E> the type of the elements in the bag
* @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 NullPointerException if bag or transformer is null
* @since 4.0
*/
public static <E> Bag<E> transformedBag(final Bag<E> bag, final Transformer<? super E, ? extends E> transformer) {
final TransformedBag<E> decorated = new TransformedBag<E>(bag, transformer);
if (bag.size() > 0) {
@SuppressWarnings("unchecked") // Bag is of type E
final E[] values = (E[]) bag.toArray(); // NOPMD - false positive for generics
bag.clear();
for (final E value : values) {
decorated.decorated().add(transformer.transform(value));
}
}
return decorated;
}
//-----------------------------------------------------------------------
/**
* 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 NullPointerException if bag or transformer is null
*/
protected TransformedBag(final Bag<E> bag, final Transformer<? super E, ? extends E> transformer) {
super(bag, transformer);
}
/**
* Gets the decorated bag.
*
* @return the decorated bag
*/
protected Bag<E> getBag() {
return (Bag<E>) decorated();
}
@Override
public boolean equals(final Object object) {
return object == this || decorated().equals(object);
}
@Override
public int hashCode() {
return decorated().hashCode();
}
//-----------------------------------------------------------------------
@Override
public int getCount(final Object object) {
return getBag().getCount(object);
}
@Override
public boolean remove(final Object object, final int nCopies) {
return getBag().remove(object, nCopies);
}
//-----------------------------------------------------------------------
@Override
public boolean add(final E object, final int nCopies) {
return getBag().add(transform(object), nCopies);
}
@Override
public Set<E> uniqueSet() {
final Set<E> set = getBag().uniqueSet();
return TransformedSet.<E>transformingSet(set, transformer);
}
}

132
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/TransformedSortedBag.java

@ -0,0 +1,132 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.util.Comparator;
import com.fr.third.org.apache.commons.collections4.Transformer;
import com.fr.third.org.apache.commons.collections4.SortedBag;
import com.fr.third.org.apache.commons.collections4.Transformer;
/**
* Decorates another {@link SortedBag} 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.
*
* @since 3.0
* @version $Id: TransformedSortedBag.java 1686855 2015-06-22 13:00:27Z tn $
*/
public class TransformedSortedBag<E> extends TransformedBag<E> implements SortedBag<E> {
/** 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. Contrast this with {@link #transformedSortedBag(SortedBag, Transformer)}.
*
* @param <E> the type of the elements in the bag
* @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 NullPointerException if bag or transformer is null
* @since 4.0
*/
public static <E> TransformedSortedBag<E> transformingSortedBag(final SortedBag<E> bag,
final Transformer<? super E, ? extends E> transformer) {
return new TransformedSortedBag<E>(bag, transformer);
}
/**
* Factory method to create a transforming sorted bag that will transform
* existing contents of the specified sorted bag.
* <p>
* If there are any elements already in the bag being decorated, they
* will be transformed by this method.
* Contrast this with {@link #transformingSortedBag(SortedBag, Transformer)}.
*
* @param <E> the type of the elements in the bag
* @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 NullPointerException if bag or transformer is null
* @since 4.0
*/
public static <E> TransformedSortedBag<E> transformedSortedBag(final SortedBag<E> bag,
final Transformer<? super E, ? extends E> transformer) {
final TransformedSortedBag<E> decorated = new TransformedSortedBag<E>(bag, transformer);
if (bag.size() > 0) {
@SuppressWarnings("unchecked") // bag is type E
final E[] values = (E[]) bag.toArray(); // NOPMD - false positive for generics
bag.clear();
for (final E value : values) {
decorated.decorated().add(transformer.transform(value));
}
}
return decorated;
}
//-----------------------------------------------------------------------
/**
* 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 NullPointerException if bag or transformer is null
*/
protected TransformedSortedBag(final SortedBag<E> bag, final Transformer<? super E, ? extends E> transformer) {
super(bag, transformer);
}
/**
* Gets the decorated bag.
*
* @return the decorated bag
*/
protected SortedBag<E> getSortedBag() {
return (SortedBag<E>) decorated();
}
//-----------------------------------------------------------------------
@Override
public E first() {
return getSortedBag().first();
}
@Override
public E last() {
return getSortedBag().last();
}
@Override
public Comparator<? super E> comparator() {
return getSortedBag().comparator();
}
}

140
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/TreeBag.java

@ -0,0 +1,140 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
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;
import com.fr.third.org.apache.commons.collections4.SortedBag;
/**
* Implements {@link SortedBag}, using a {@link TreeMap} 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 {@link org.apache.commons.collections4.Bag Bag} 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 {@link Collection} interface specification.
*
* @since 3.0 (previously in main package v2.0)
* @version $Id: TreeBag.java 1683951 2015-06-06 20:19:03Z tn $
*/
public class TreeBag<E> extends AbstractMapBag<E> implements SortedBag<E>, Serializable {
/** Serial version lock */
private static final long serialVersionUID = -7740146511091606676L;
/**
* Constructs an empty {@link TreeBag}.
*/
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(final Comparator<? super E> comparator) {
super(new TreeMap<E, MutableInteger>(comparator));
}
/**
* Constructs a {@link TreeBag} containing all the members of the
* specified collection.
*
* @param coll the collection to copy into the bag
*/
public TreeBag(final Collection<? extends E> coll) {
this();
addAll(coll);
}
//-----------------------------------------------------------------------
/**
* {@inheritDoc}
*
* @throws IllegalArgumentException if the object to be added does not implement
* {@link Comparable} and the {@link TreeBag} is using natural ordering
* @throws NullPointerException if the specified key is null and this bag uses
* natural ordering, or its comparator does not permit null keys
*/
@Override
public boolean add(final E object) {
if(comparator() == null && !(object instanceof Comparable)) {
if (object == null) {
throw new NullPointerException();
}
throw new IllegalArgumentException("Objects of type " + object.getClass() + " cannot be added to " +
"a naturally ordered TreeBag as it does not implement Comparable");
}
return super.add(object);
}
//-----------------------------------------------------------------------
@Override
public E first() {
return getMap().firstKey();
}
@Override
public E last() {
return getMap().lastKey();
}
@Override
public Comparator<? super E> comparator() {
return getMap().comparator();
}
@Override
protected SortedMap<E, AbstractMapBag.MutableInteger> getMap() {
return (SortedMap<E, AbstractMapBag.MutableInteger>) super.getMap();
}
//-----------------------------------------------------------------------
/**
* Write the bag out using a custom routine.
*/
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(comparator());
super.doWriteObject(out);
}
/**
* Read the bag in using a custom routine.
*/
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
@SuppressWarnings("unchecked") // This will fail at runtime if the stream is incorrect
final Comparator<? super E> comp = (Comparator<? super E>) in.readObject();
super.doReadObject(new TreeMap<E, MutableInteger>(comp), in);
}
}

159
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/UnmodifiableBag.java

@ -0,0 +1,159 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
import com.fr.third.org.apache.commons.collections4.Bag;
import com.fr.third.org.apache.commons.collections4.Unmodifiable;
import com.fr.third.org.apache.commons.collections4.iterators.UnmodifiableIterator;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
/**
* Decorates another {@link Bag} to ensure it can't be altered.
* <p>
* This class is Serializable from Commons Collections 3.1.
* <p>
* Attempts to modify it will result in an UnsupportedOperationException.
*
* @since 3.0
* @version $Id: UnmodifiableBag.java 1686855 2015-06-22 13:00:27Z tn $
*/
public final class UnmodifiableBag<E>
extends AbstractBagDecorator<E> implements Unmodifiable {
/** 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 <E> the type of the elements in the bag
* @param bag the bag to decorate, must not be null
* @return an unmodifiable Bag
* @throws NullPointerException if bag is null
* @since 4.0
*/
public static <E> Bag<E> unmodifiableBag(final Bag<? extends E> bag) {
if (bag instanceof Unmodifiable) {
@SuppressWarnings("unchecked") // safe to upcast
final Bag<E> tmpBag = (Bag<E>) bag;
return tmpBag;
}
return new UnmodifiableBag<E>(bag);
}
//-----------------------------------------------------------------------
/**
* Constructor that wraps (not copies).
*
* @param bag the bag to decorate, must not be null
* @throws NullPointerException if bag is null
*/
@SuppressWarnings("unchecked") // safe to upcast
private UnmodifiableBag(final Bag<? extends E> bag) {
super((Bag<E>) bag);
}
//-----------------------------------------------------------------------
/**
* Write the collection out using a custom routine.
*
* @param out the output stream
* @throws IOException
*/
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(decorated());
}
/**
* Read the collection in using a custom routine.
*
* @param in the input stream
* @throws IOException
* @throws ClassNotFoundException
* @throws ClassCastException if deserialised object has wrong type
*/
@SuppressWarnings("unchecked") // will throw CCE, see Javadoc
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
setCollection((Collection<E>) in.readObject());
}
//-----------------------------------------------------------------------
@Override
public Iterator<E> iterator() {
return UnmodifiableIterator.<E> unmodifiableIterator(decorated().iterator());
}
@Override
public boolean add(final E object) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(final Collection<? extends E> coll) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(final Object object) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(final Collection<?> coll) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(final Collection<?> coll) {
throw new UnsupportedOperationException();
}
//-----------------------------------------------------------------------
@Override
public boolean add(final E object, final int count) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(final Object object, final int count) {
throw new UnsupportedOperationException();
}
@Override
public Set<E> uniqueSet() {
final Set<E> set = decorated().uniqueSet();
return UnmodifiableSet.<E> unmodifiableSet(set);
}
}

156
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/UnmodifiableSortedBag.java

@ -0,0 +1,156 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bag;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
import com.fr.third.org.apache.commons.collections4.SortedBag;
import com.fr.third.org.apache.commons.collections4.Unmodifiable;
import com.fr.third.org.apache.commons.collections4.iterators.UnmodifiableIterator;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
/**
* Decorates another {@link SortedBag} to ensure it can't be altered.
* <p>
* This class is Serializable from Commons Collections 3.1.
* <p>
* Attempts to modify it will result in an UnsupportedOperationException.
*
* @since 3.0
* @version $Id: UnmodifiableSortedBag.java 1686855 2015-06-22 13:00:27Z tn $
*/
public final class UnmodifiableSortedBag<E>
extends AbstractSortedBagDecorator<E> implements Unmodifiable {
/** 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 <E> the type of the elements in the bag
* @param bag the bag to decorate, must not be null
* @return an unmodifiable SortedBag
* @throws NullPointerException if bag is null
* @since 4.0
*/
public static <E> SortedBag<E> unmodifiableSortedBag(final 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 NullPointerException if bag is null
*/
private UnmodifiableSortedBag(final SortedBag<E> bag) {
super(bag);
}
//-----------------------------------------------------------------------
/**
* Write the collection out using a custom routine.
*
* @param out the output stream
* @throws IOException
*/
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(decorated());
}
/**
* Read the collection in using a custom routine.
*
* @param in the input stream
* @throws IOException
* @throws ClassNotFoundException
* @throws ClassCastException if deserialised object has wrong type
*/
@SuppressWarnings("unchecked") // will throw CCE, see Javadoc
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
setCollection((Collection<E>) in.readObject());
}
//-----------------------------------------------------------------------
@Override
public Iterator<E> iterator() {
return UnmodifiableIterator.unmodifiableIterator(decorated().iterator());
}
@Override
public boolean add(final E object) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(final Collection<? extends E> coll) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(final Object object) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(final Collection<?> coll) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(final Collection<?> coll) {
throw new UnsupportedOperationException();
}
//-----------------------------------------------------------------------
@Override
public boolean add(final E object, final int count) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(final Object object, final int count) {
throw new UnsupportedOperationException();
}
@Override
public Set<E> uniqueSet() {
final Set<E> set = decorated().uniqueSet();
return UnmodifiableSet.unmodifiableSet(set);
}
}

39
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bag/package-info.java

@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This package contains implementations of the {@link org.apache.commons.collections4.Bag Bag} and
* {@link org.apache.commons.collections4.SortedBag SortedBag} interfaces.
* A bag stores an object and a count of the number of occurrences 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>Transformed - transforms each element added to the bag
* <li>Collection - ensures compliance with the java.util.Collection contract
* </ul>
*
* @version $Id: package-info.java 1540804 2013-11-11 18:58:31Z tn $
*/
package com.fr.third.org.apache.commons.collections4.bag;

89
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/AbstractBidiMapDecorator.java

@ -0,0 +1,89 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bidimap;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.BidiMap;
import com.fr.third.org.apache.commons.collections4.MapIterator;
import com.fr.third.org.apache.commons.collections4.map.AbstractMapDecorator;
/**
* 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.
*
* @since 3.0
* @version $Id: AbstractBidiMapDecorator.java 1686855 2015-06-22 13:00:27Z tn $
*/
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 NullPointerException if the collection is null
*/
protected AbstractBidiMapDecorator(final BidiMap<K, V> map) {
super(map);
}
/**
* Gets the map being decorated.
*
* @return the decorated map
*/
@Override
protected BidiMap<K, V> decorated() {
return (BidiMap<K, V>) super.decorated();
}
//-----------------------------------------------------------------------
@Override
public MapIterator<K, V> mapIterator() {
return decorated().mapIterator();
}
@Override
public K getKey(final Object value) {
return decorated().getKey(value);
}
@Override
public K removeValue(final Object value) {
return decorated().removeValue(value);
}
@Override
public BidiMap<V, K> inverseBidiMap() {
return decorated().inverseBidiMap();
}
@Override
public Set<V> values() {
return decorated().values();
}
}

806
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.java

@ -0,0 +1,806 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bidimap;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.keyvalue.AbstractMapEntryDecorator;
import com.fr.third.org.apache.commons.collections4.BidiMap;
import com.fr.third.org.apache.commons.collections4.MapIterator;
import com.fr.third.org.apache.commons.collections4.ResettableIterator;
import com.fr.third.org.apache.commons.collections4.collection.AbstractCollectionDecorator;
import com.fr.third.org.apache.commons.collections4.iterators.AbstractIteratorDecorator;
import com.fr.third.org.apache.commons.collections4.keyvalue.AbstractMapEntryDecorator;
/**
* Abstract {@link BidiMap} implemented using two maps.
* <p>
* An implementation can be written simply by implementing the
* {@link #createBidiMap(Map, Map, BidiMap)} method.
*
* @see DualHashBidiMap
* @see DualTreeBidiMap
* @since 3.0
* @version $Id: AbstractDualBidiMap.java 1683951 2015-06-06 20:19:03Z tn $
*/
public abstract class AbstractDualBidiMap<K, V> implements BidiMap<K, V> {
/**
* Normal delegate map.
*/
transient Map<K, V> normalMap;
/**
* Reverse delegate map.
*/
transient Map<V, K> reverseMap;
/**
* Inverse view of this map.
*/
transient BidiMap<V, K> inverseBidiMap = null;
/**
* View of the keys.
*/
transient Set<K> keySet = null;
/**
* View of the values.
*/
transient Set<V> values = null;
/**
* View of the entries.
*/
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)}.
*/
protected AbstractDualBidiMap() {
super();
}
/**
* 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 3.1
*/
protected AbstractDualBidiMap(final Map<K, V> normalMap, final Map<V, K> reverseMap) {
super();
this.normalMap = normalMap;
this.reverseMap = 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(final Map<K, V> normalMap, final Map<V, K> reverseMap,
final BidiMap<V, K> inverseBidiMap) {
super();
this.normalMap = normalMap;
this.reverseMap = reverseMap;
this.inverseBidiMap = inverseBidiMap;
}
/**
* 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 BidiMap<V, K> createBidiMap(Map<V, K> normalMap, Map<K, V> reverseMap, BidiMap<K, V> inverseMap);
// Map delegation
//-----------------------------------------------------------------------
@Override
public V get(final Object key) {
return normalMap.get(key);
}
@Override
public int size() {
return normalMap.size();
}
@Override
public boolean isEmpty() {
return normalMap.isEmpty();
}
@Override
public boolean containsKey(final Object key) {
return normalMap.containsKey(key);
}
@Override
public boolean equals(final Object obj) {
return normalMap.equals(obj);
}
@Override
public int hashCode() {
return normalMap.hashCode();
}
@Override
public String toString() {
return normalMap.toString();
}
// BidiMap changes
//-----------------------------------------------------------------------
@Override
public V put(final K key, final V value) {
if (normalMap.containsKey(key)) {
reverseMap.remove(normalMap.get(key));
}
if (reverseMap.containsKey(value)) {
normalMap.remove(reverseMap.get(value));
}
final V obj = normalMap.put(key, value);
reverseMap.put(value, key);
return obj;
}
@Override
public void putAll(final Map<? extends K, ? extends V> map) {
for (final Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
@Override
public V remove(final Object key) {
V value = null;
if (normalMap.containsKey(key)) {
value = normalMap.remove(key);
reverseMap.remove(value);
}
return value;
}
@Override
public void clear() {
normalMap.clear();
reverseMap.clear();
}
@Override
public boolean containsValue(final Object value) {
return reverseMap.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
*/
@Override
public MapIterator<K, V> mapIterator() {
return new BidiMapIterator<K, V>(this);
}
@Override
public K getKey(final Object value) {
return reverseMap.get(value);
}
@Override
public K removeValue(final Object value) {
K key = null;
if (reverseMap.containsKey(value)) {
key = reverseMap.remove(value);
normalMap.remove(key);
}
return key;
}
@Override
public BidiMap<V, K> inverseBidiMap() {
if (inverseBidiMap == null) {
inverseBidiMap = createBidiMap(reverseMap, normalMap, 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
*/
@Override
public Set<K> keySet() {
if (keySet == null) {
keySet = new KeySet<K>(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(final Iterator<K> iterator) {
return new KeySetIterator<K>(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
*/
@Override
public Set<V> values() {
if (values == null) {
values = new Values<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(final Iterator<V> iterator) {
return new ValuesIterator<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
*/
@Override
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(final 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> {
/** Generated serial version ID. */
private static final long serialVersionUID = 4621510560119690639L;
/** 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(final Collection<E> coll, final AbstractDualBidiMap<K, V> parent) {
super(coll);
this.parent = parent;
}
@Override
public boolean equals(final Object object) {
return object == this || decorated().equals(object);
}
@Override
public int hashCode() {
return decorated().hashCode();
}
@Override
public boolean removeAll(final Collection<?> coll) {
if (parent.isEmpty() || coll.isEmpty()) {
return false;
}
boolean modified = false;
final Iterator<?> it = coll.iterator();
while (it.hasNext()) {
modified |= remove(it.next());
}
return modified;
}
/**
* {@inheritDoc}
* <p>
* This implementation iterates over the elements of this bidi map, checking each element in
* turn to see if it's contained in <code>coll</code>. If it's not contained, it's removed
* from this bidi map. As a consequence, it is advised to use a collection type for
* <code>coll</code> that provides a fast (e.g. O(1)) implementation of
* {@link Collection#contains(Object)}.
*/
@Override
public boolean retainAll(final Collection<?> coll) {
if (parent.isEmpty()) {
return false;
}
if (coll.isEmpty()) {
parent.clear();
return true;
}
boolean modified = false;
final Iterator<E> it = iterator();
while (it.hasNext()) {
if (coll.contains(it.next()) == false) {
it.remove();
modified = true;
}
}
return modified;
}
@Override
public void clear() {
parent.clear();
}
}
//-----------------------------------------------------------------------
/**
* Inner class KeySet.
*/
protected static class KeySet<K> extends View<K, Object, K> implements Set<K> {
/** Serialization version */
private static final long serialVersionUID = -7107935777385040694L;
/**
* Constructs a new view of the BidiMap.
*
* @param parent the parent BidiMap
*/
@SuppressWarnings("unchecked")
protected KeySet(final AbstractDualBidiMap<K, ?> parent) {
super(parent.normalMap.keySet(), (AbstractDualBidiMap<K, Object>) parent);
}
@Override
public Iterator<K> iterator() {
return parent.createKeySetIterator(super.iterator());
}
@Override
public boolean contains(final Object key) {
return parent.normalMap.containsKey(key);
}
@Override
public boolean remove(final Object key) {
if (parent.normalMap.containsKey(key)) {
final Object value = parent.normalMap.remove(key);
parent.reverseMap.remove(value);
return true;
}
return false;
}
}
/**
* Inner class KeySetIterator.
*/
protected static class KeySetIterator<K> extends AbstractIteratorDecorator<K> {
/** The parent map */
protected final AbstractDualBidiMap<K, ?> 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(final Iterator<K> iterator, final AbstractDualBidiMap<K, ?> parent) {
super(iterator);
this.parent = parent;
}
@Override
public K next() {
lastKey = super.next();
canRemove = true;
return lastKey;
}
@Override
public void remove() {
if (canRemove == false) {
throw new IllegalStateException("Iterator remove() can only be called once after next()");
}
final Object value = parent.normalMap.get(lastKey);
super.remove();
parent.reverseMap.remove(value);
lastKey = null;
canRemove = false;
}
}
//-----------------------------------------------------------------------
/**
* Inner class Values.
*/
protected static class Values<V> extends View<Object, V, V> implements Set<V> {
/** Serialization version */
private static final long serialVersionUID = 4023777119829639864L;
/**
* Constructs a new view of the BidiMap.
*
* @param parent the parent BidiMap
*/
@SuppressWarnings("unchecked")
protected Values(final AbstractDualBidiMap<?, V> parent) {
super(parent.normalMap.values(), (AbstractDualBidiMap<Object, V>) parent);
}
@Override
public Iterator<V> iterator() {
return parent.createValuesIterator(super.iterator());
}
@Override
public boolean contains(final Object value) {
return parent.reverseMap.containsKey(value);
}
@Override
public boolean remove(final Object value) {
if (parent.reverseMap.containsKey(value)) {
final Object key = parent.reverseMap.remove(value);
parent.normalMap.remove(key);
return true;
}
return false;
}
}
/**
* Inner class ValuesIterator.
*/
protected static class ValuesIterator<V> extends AbstractIteratorDecorator<V> {
/** The parent map */
protected final AbstractDualBidiMap<Object, 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
*/
@SuppressWarnings("unchecked")
protected ValuesIterator(final Iterator<V> iterator, final AbstractDualBidiMap<?, V> parent) {
super(iterator);
this.parent = (AbstractDualBidiMap<Object, V>) parent;
}
@Override
public V next() {
lastValue = super.next();
canRemove = true;
return lastValue;
}
@Override
public void remove() {
if (canRemove == false) {
throw new IllegalStateException("Iterator remove() can only be called once after next()");
}
super.remove(); // removes from maps[0]
parent.reverseMap.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>> {
/** Serialization version */
private static final long serialVersionUID = 4040410962603292348L;
/**
* Constructs a new view of the BidiMap.
*
* @param parent the parent BidiMap
*/
protected EntrySet(final AbstractDualBidiMap<K, V> parent) {
super(parent.normalMap.entrySet(), parent);
}
@Override
public Iterator<Map.Entry<K, V>> iterator() {
return parent.createEntrySetIterator(super.iterator());
}
@Override
public boolean remove(final Object obj) {
if (obj instanceof Map.Entry == false) {
return false;
}
final Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj;
final Object key = entry.getKey();
if (parent.containsKey(key)) {
final V value = parent.normalMap.get(key);
if (value == null ? entry.getValue() == null : value.equals(entry.getValue())) {
parent.normalMap.remove(key);
parent.reverseMap.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(final Iterator<Map.Entry<K, V>> iterator, final AbstractDualBidiMap<K, V> parent) {
super(iterator);
this.parent = parent;
}
@Override
public Map.Entry<K, V> next() {
last = new MapEntry<K, V>(super.next(), parent);
canRemove = true;
return last;
}
@Override
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)
final Object value = last.getValue();
super.remove();
parent.reverseMap.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(final Map.Entry<K, V> entry, final AbstractDualBidiMap<K, V> parent) {
super(entry);
this.parent = parent;
}
@Override
public V setValue(final V value) {
final K key = MapEntry.this.getKey();
if (parent.reverseMap.containsKey(value) &&
parent.reverseMap.get(value) != key) {
throw new IllegalArgumentException(
"Cannot use setValue() when the object being set is already in the map");
}
parent.put(key, value);
return super.setValue(value);
}
}
/**
* 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(final AbstractDualBidiMap<K, V> parent) {
super();
this.parent = parent;
this.iterator = parent.normalMap.entrySet().iterator();
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public K next() {
last = iterator.next();
canRemove = true;
return last.getKey();
}
@Override
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)
final V value = last.getValue();
iterator.remove();
parent.reverseMap.remove(value);
last = null;
canRemove = false;
}
@Override
public K getKey() {
if (last == null) {
throw new IllegalStateException(
"Iterator getKey() can only be called after next() and before remove()");
}
return last.getKey();
}
@Override
public V getValue() {
if (last == null) {
throw new IllegalStateException(
"Iterator getValue() can only be called after next() and before remove()");
}
return last.getValue();
}
@Override
public V setValue(final V value) {
if (last == null) {
throw new IllegalStateException(
"Iterator setValue() can only be called after next() and before remove()");
}
if (parent.reverseMap.containsKey(value) &&
parent.reverseMap.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);
}
@Override
public void reset() {
iterator = parent.normalMap.entrySet().iterator();
last = null;
canRemove = false;
}
@Override
public String toString() {
if (last != null) {
return "MapIterator[" + getKey() + "=" + getValue() + "]";
}
return "MapIterator[]";
}
}
}

92
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/AbstractOrderedBidiMapDecorator.java

@ -0,0 +1,92 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bidimap;
import com.fr.third.org.apache.commons.collections4.OrderedBidiMap;
import com.fr.third.org.apache.commons.collections4.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.
*
* @since 3.0
* @version $Id: AbstractOrderedBidiMapDecorator.java 1686855 2015-06-22 13:00:27Z tn $
*/
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 NullPointerException if the collection is null
*/
protected AbstractOrderedBidiMapDecorator(final OrderedBidiMap<K, V> map) {
super(map);
}
/**
* Gets the map being decorated.
*
* @return the decorated map
*/
@Override
protected OrderedBidiMap<K, V> decorated() {
return (OrderedBidiMap<K, V>) super.decorated();
}
//-----------------------------------------------------------------------
@Override
public OrderedMapIterator<K, V> mapIterator() {
return decorated().mapIterator();
}
@Override
public K firstKey() {
return decorated().firstKey();
}
@Override
public K lastKey() {
return decorated().lastKey();
}
@Override
public K nextKey(final K key) {
return decorated().nextKey(key);
}
@Override
public K previousKey(final K key) {
return decorated().previousKey(key);
}
@Override
public OrderedBidiMap<V, K> inverseBidiMap() {
return decorated().inverseBidiMap();
}
}

93
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/AbstractSortedBidiMapDecorator.java

@ -0,0 +1,93 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bidimap;
import java.util.Comparator;
import java.util.SortedMap;
import com.fr.third.org.apache.commons.collections4.SortedBidiMap;
/**
* 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.
*
* @since 3.0
* @version $Id: AbstractSortedBidiMapDecorator.java 1686855 2015-06-22 13:00:27Z tn $
*/
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 NullPointerException if the collection is null
*/
public AbstractSortedBidiMapDecorator(final SortedBidiMap<K, V> map) {
super(map);
}
/**
* Gets the map being decorated.
*
* @return the decorated map
*/
@Override
protected SortedBidiMap<K, V> decorated() {
return (SortedBidiMap<K, V>) super.decorated();
}
//-----------------------------------------------------------------------
@Override
public SortedBidiMap<V, K> inverseBidiMap() {
return decorated().inverseBidiMap();
}
@Override
public Comparator<? super K> comparator() {
return decorated().comparator();
}
@Override
public Comparator<? super V> valueComparator() {
return decorated().valueComparator();
}
@Override
public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
return decorated().subMap(fromKey, toKey);
}
@Override
public SortedMap<K, V> headMap(final K toKey) {
return decorated().headMap(toKey);
}
@Override
public SortedMap<K, V> tailMap(final K fromKey) {
return decorated().tailMap(fromKey);
}
}

107
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/DualHashBidiMap.java

@ -0,0 +1,107 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.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;
import com.fr.third.org.apache.commons.collections4.BidiMap;
/**
* Implementation of {@link BidiMap} that uses two {@link HashMap} instances.
* <p>
* Two {@link HashMap} 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 {@link BidiMap} interface.
* <p>
* NOTE: From Commons Collections 3.1, all subclasses will use {@link HashMap}
* and the flawed <code>createMap</code> method is ignored.
*
* @since 3.0
* @version $Id: DualHashBidiMap.java 1533984 2013-10-20 21:12:51Z tn $
*/
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(final 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(final Map<K, V> normalMap, final Map<V, K> reverseMap,
final 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
*/
@Override
protected BidiMap<V, K> createBidiMap(final Map<V, K> normalMap, final Map<K, V> reverseMap,
final BidiMap<K, V> inverseBidiMap) {
return new DualHashBidiMap<V, K>(normalMap, reverseMap, inverseBidiMap);
}
// Serialization
//-----------------------------------------------------------------------
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(normalMap);
}
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
normalMap = new HashMap<K, V>();
reverseMap = new HashMap<V, K>();
@SuppressWarnings("unchecked") // will fail at runtime if stream is incorrect
final Map<K, V> map = (Map<K, V>) in.readObject();
putAll(map);
}
}

101
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/DualLinkedHashBidiMap.java

@ -0,0 +1,101 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bidimap;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
import com.fr.third.org.apache.commons.collections4.BidiMap;
/**
* Implementation of <code>BidiMap</code> that uses two <code>LinkedHashMap</code> instances.
* <p>
* Two <code>LinkedHashMap</code> instances are used in this class.
* This provides fast lookups at the expense of storing two sets of map entries and two linked lists.
*
* @version $Id: DualLinkedHashBidiMap.java 1533984 2013-10-20 21:12:51Z tn $
* @since 4.0
*/
public class DualLinkedHashBidiMap<K, V> extends AbstractDualBidiMap<K, V> implements Serializable {
/** Ensure serialization compatibility */
private static final long serialVersionUID = 721969328361810L;
/**
* Creates an empty <code>HashBidiMap</code>.
*/
public DualLinkedHashBidiMap() {
super(new LinkedHashMap<K, V>(), new LinkedHashMap<V, K>());
}
/**
* Constructs a <code>LinkedHashBidiMap</code> and copies the mappings from
* specified <code>Map</code>.
*
* @param map the map whose mappings are to be placed in this map
*/
public DualLinkedHashBidiMap(final Map<? extends K, ? extends V> map) {
super(new LinkedHashMap<K, V>(), new LinkedHashMap<V, K>());
putAll(map);
}
/**
* Constructs a <code>LinkedHashBidiMap</code> that decorates the specified maps.
*
* @param normalMap the normal direction map
* @param reverseMap the reverse direction map
* @param inverseBidiMap the inverse BidiMap
*/
protected DualLinkedHashBidiMap(final Map<K, V> normalMap, final Map<V, K> reverseMap,
final 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
*/
@Override
protected BidiMap<V, K> createBidiMap(final Map<V, K> normalMap, final Map<K, V> reverseMap,
final BidiMap<K, V> inverseBidiMap) {
return new DualLinkedHashBidiMap<V, K>(normalMap, reverseMap, inverseBidiMap);
}
// Serialization
//-----------------------------------------------------------------------
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(normalMap);
}
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
normalMap = new LinkedHashMap<K, V>();
reverseMap = new LinkedHashMap<V, K>();
@SuppressWarnings("unchecked") // will fail at runtime if stream is incorrect
final Map<K, V> map = (Map<K, V>) in.readObject();
putAll(map);
}
}

416
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/DualTreeBidiMap.java

@ -0,0 +1,416 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bidimap;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import com.fr.third.org.apache.commons.collections4.BidiMap;
import com.fr.third.org.apache.commons.collections4.OrderedBidiMap;
import com.fr.third.org.apache.commons.collections4.OrderedMap;
import com.fr.third.org.apache.commons.collections4.OrderedMapIterator;
import com.fr.third.org.apache.commons.collections4.ResettableIterator;
import com.fr.third.org.apache.commons.collections4.SortedBidiMap;
import com.fr.third.org.apache.commons.collections4.map.AbstractSortedMapDecorator;
/**
* Implementation of {@link BidiMap} that uses two {@link TreeMap} 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 {@link TreeMap}
* and the flawed <code>createMap</code> method is ignored.
*
* @since 3.0
* @version $Id: DualTreeBidiMap.java 1683951 2015-06-06 20:19:03Z tn $
*/
public class DualTreeBidiMap<K, V> extends AbstractDualBidiMap<K, V>
implements SortedBidiMap<K, V>, Serializable {
/** Ensure serialization compatibility */
private static final long serialVersionUID = 721969328361809L;
/** The key comparator to use */
private final Comparator<? super K> comparator;
/** The value comparator to use */
private final Comparator<? super V> valueComparator;
/**
* Creates an empty <code>DualTreeBidiMap</code>
*/
public DualTreeBidiMap() {
super(new TreeMap<K, V>(), new TreeMap<V, K>());
this.comparator = null;
this.valueComparator = null;
}
/**
* 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(final Map<? extends K, ? extends V> map) {
super(new TreeMap<K, V>(), new TreeMap<V, K>());
putAll(map);
this.comparator = null;
this.valueComparator = null;
}
/**
* Constructs a {@link DualTreeBidiMap} using the specified {@link Comparator}.
*
* @param keyComparator the comparator
* @param valueComparator the values comparator to use
*/
public DualTreeBidiMap(final Comparator<? super K> keyComparator, final Comparator<? super V> valueComparator) {
super(new TreeMap<K, V>(keyComparator), new TreeMap<V, K>(valueComparator));
this.comparator = keyComparator;
this.valueComparator = valueComparator;
}
/**
* Constructs a {@link DualTreeBidiMap} that decorates the specified maps.
*
* @param normalMap the normal direction map
* @param reverseMap the reverse direction map
* @param inverseBidiMap the inverse BidiMap
*/
protected DualTreeBidiMap(final Map<K, V> normalMap, final Map<V, K> reverseMap,
final BidiMap<V, K> inverseBidiMap) {
super(normalMap, reverseMap, inverseBidiMap);
this.comparator = ((SortedMap<K, V>) normalMap).comparator();
this.valueComparator = ((SortedMap<V, K>) reverseMap).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
*/
@Override
protected DualTreeBidiMap<V, K> createBidiMap(final Map<V, K> normalMap, final Map<K, V> reverseMap,
final BidiMap<K, V> inverseMap) {
return new DualTreeBidiMap<V, K>(normalMap, reverseMap, inverseMap);
}
//-----------------------------------------------------------------------
@Override
public Comparator<? super K> comparator() {
return ((SortedMap<K, V>) normalMap).comparator();
}
@Override
public Comparator<? super V> valueComparator() {
return ((SortedMap<V, K>) reverseMap).comparator();
}
@Override
public K firstKey() {
return ((SortedMap<K, V>) normalMap).firstKey();
}
@Override
public K lastKey() {
return ((SortedMap<K, V>) normalMap).lastKey();
}
@Override
public K nextKey(final K key) {
if (isEmpty()) {
return null;
}
if (normalMap instanceof OrderedMap) {
return ((OrderedMap<K, ?>) normalMap).nextKey(key);
}
final SortedMap<K, V> sm = (SortedMap<K, V>) normalMap;
final Iterator<K> it = sm.tailMap(key).keySet().iterator();
it.next();
if (it.hasNext()) {
return it.next();
}
return null;
}
@Override
public K previousKey(final K key) {
if (isEmpty()) {
return null;
}
if (normalMap instanceof OrderedMap) {
return ((OrderedMap<K, V>) normalMap).previousKey(key);
}
final SortedMap<K, V> sm = (SortedMap<K, V>) normalMap;
final 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
*/
@Override
public OrderedMapIterator<K, V> mapIterator() {
return new BidiOrderedMapIterator<K, V>(this);
}
public SortedBidiMap<V, K> inverseSortedBidiMap() {
return inverseBidiMap();
}
public OrderedBidiMap<V, K> inverseOrderedBidiMap() {
return inverseBidiMap();
}
//-----------------------------------------------------------------------
@Override
public SortedMap<K, V> headMap(final K toKey) {
final SortedMap<K, V> sub = ((SortedMap<K, V>) normalMap).headMap(toKey);
return new ViewMap<K, V>(this, sub);
}
@Override
public SortedMap<K, V> tailMap(final K fromKey) {
final SortedMap<K, V> sub = ((SortedMap<K, V>) normalMap).tailMap(fromKey);
return new ViewMap<K, V>(this, sub);
}
@Override
public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
final SortedMap<K, V> sub = ((SortedMap<K, V>) normalMap).subMap(fromKey, toKey);
return new ViewMap<K, V>(this, sub);
}
@Override
public SortedBidiMap<V, K> inverseBidiMap() {
return (SortedBidiMap<V, K>) super.inverseBidiMap();
}
//-----------------------------------------------------------------------
/**
* Internal sorted map view.
*/
protected static class ViewMap<K, V> extends AbstractSortedMapDecorator<K, V> {
/**
* Constructor.
* @param bidi the parent bidi map
* @param sm the subMap sorted map
*/
protected ViewMap(final DualTreeBidiMap<K, V> bidi, final SortedMap<K, V> sm) {
// the implementation is not great here...
// use the normalMap as the filtered map, but reverseMap as the full map
// this forces containsValue and clear to be overridden
super(new DualTreeBidiMap<K, V>(sm, bidi.reverseMap, bidi.inverseBidiMap));
}
@Override
public boolean containsValue(final Object value) {
// override as default implementation uses reverseMap
return decorated().normalMap.containsValue(value);
}
@Override
public void clear() {
// override as default implementation uses reverseMap
for (final Iterator<K> it = keySet().iterator(); it.hasNext();) {
it.next();
it.remove();
}
}
@Override
public SortedMap<K, V> headMap(final K toKey) {
return new ViewMap<K, V>(decorated(), super.headMap(toKey));
}
@Override
public SortedMap<K, V> tailMap(final K fromKey) {
return new ViewMap<K, V>(decorated(), super.tailMap(fromKey));
}
@Override
public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
return new ViewMap<K, V>(decorated(), super.subMap(fromKey, toKey));
}
@Override
protected DualTreeBidiMap<K, V> decorated() {
return (DualTreeBidiMap<K, V>) super.decorated();
}
@Override
public K previousKey(final K key) {
return decorated().previousKey(key);
}
@Override
public K nextKey(final K key) {
return decorated().nextKey(key);
}
}
//-----------------------------------------------------------------------
/**
* Inner class MapIterator.
*/
protected static class BidiOrderedMapIterator<K, V> implements OrderedMapIterator<K, V>, ResettableIterator<K> {
/** The parent map */
private final AbstractDualBidiMap<K, V> parent;
/** The iterator being decorated */
private 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(final AbstractDualBidiMap<K, V> parent) {
super();
this.parent = parent;
iterator = new ArrayList<Map.Entry<K, V>>(parent.entrySet()).listIterator();
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public K next() {
last = iterator.next();
return last.getKey();
}
@Override
public boolean hasPrevious() {
return iterator.hasPrevious();
}
@Override
public K previous() {
last = iterator.previous();
return last.getKey();
}
@Override
public void remove() {
iterator.remove();
parent.remove(last.getKey());
last = null;
}
@Override
public K getKey() {
if (last == null) {
throw new IllegalStateException(
"Iterator getKey() can only be called after next() and before remove()");
}
return last.getKey();
}
@Override
public V getValue() {
if (last == null) {
throw new IllegalStateException(
"Iterator getValue() can only be called after next() and before remove()");
}
return last.getValue();
}
@Override
public V setValue(final V value) {
if (last == null) {
throw new IllegalStateException(
"Iterator setValue() can only be called after next() and before remove()");
}
if (parent.reverseMap.containsKey(value) &&
parent.reverseMap.get(value) != last.getKey()) {
throw new IllegalArgumentException(
"Cannot use setValue() when the object being set is already in the map");
}
final V oldValue = parent.put(last.getKey(), value);
// Map.Entry specifies that the behavior is undefined when the backing map
// has been modified (as we did with the put), so we also set the value
// (especially needed for IBM JDK)
last.setValue(value);
return oldValue;
}
@Override
public void reset() {
iterator = new ArrayList<Map.Entry<K, V>>(parent.entrySet()).listIterator();
last = null;
}
@Override
public String toString() {
if (last != null) {
return "MapIterator[" + getKey() + "=" + getValue() + "]";
}
return "MapIterator[]";
}
}
// Serialization
//-----------------------------------------------------------------------
private void writeObject(final ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(normalMap);
}
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
normalMap = new TreeMap<K, V>(comparator);
reverseMap = new TreeMap<V, K>(valueComparator);
@SuppressWarnings("unchecked") // will fail at runtime if the stream is incorrect
final Map<K, V> map = (Map<K, V>) in.readObject();
putAll(map);
}
}

2229
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/TreeBidiMap.java

File diff suppressed because it is too large Load Diff

136
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/UnmodifiableBidiMap.java

@ -0,0 +1,136 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bidimap;
import java.util.Map;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.BidiMap;
import com.fr.third.org.apache.commons.collections4.MapIterator;
import com.fr.third.org.apache.commons.collections4.Unmodifiable;
import com.fr.third.org.apache.commons.collections4.iterators.UnmodifiableMapIterator;
import com.fr.third.org.apache.commons.collections4.map.UnmodifiableEntrySet;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
/**
* Decorates another {@link BidiMap} to ensure it can't be altered.
* <p>
* Attempts to modify it will result in an UnsupportedOperationException.
*
* @since 3.0
* @version $Id: UnmodifiableBidiMap.java 1686855 2015-06-22 13:00:27Z tn $
*/
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 <K> the key type
* @param <V> the value type
* @param map the map to decorate, must not be null
* @return an unmodifiable BidiMap
* @throws NullPointerException if map is null
* @since 4.0
*/
public static <K, V> BidiMap<K, V> unmodifiableBidiMap(final BidiMap<? extends K, ? extends V> map) {
if (map instanceof Unmodifiable) {
@SuppressWarnings("unchecked") // safe to upcast
final BidiMap<K, V> tmpMap = (BidiMap<K, V>) map;
return tmpMap;
}
return new UnmodifiableBidiMap<K, V>(map);
}
//-----------------------------------------------------------------------
/**
* Constructor that wraps (not copies).
*
* @param map the map to decorate, must not be null
* @throws NullPointerException if map is null
*/
@SuppressWarnings("unchecked") // safe to upcast
private UnmodifiableBidiMap(final BidiMap<? extends K, ? extends V> map) {
super((BidiMap<K, V>) map);
}
//-----------------------------------------------------------------------
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public V put(final K key, final V value) {
throw new UnsupportedOperationException();
}
@Override
public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
throw new UnsupportedOperationException();
}
@Override
public V remove(final Object key) {
throw new UnsupportedOperationException();
}
@Override
public Set<Map.Entry<K, V>> entrySet() {
final Set<Map.Entry<K, V>> set = super.entrySet();
return UnmodifiableEntrySet.unmodifiableEntrySet(set);
}
@Override
public Set<K> keySet() {
final Set<K> set = super.keySet();
return UnmodifiableSet.unmodifiableSet(set);
}
@Override
public Set<V> values() {
final Set<V> set = super.values();
return UnmodifiableSet.unmodifiableSet(set);
}
//-----------------------------------------------------------------------
@Override
public K removeValue(final Object value) {
throw new UnsupportedOperationException();
}
@Override
public MapIterator<K, V> mapIterator() {
final MapIterator<K, V> it = decorated().mapIterator();
return UnmodifiableMapIterator.unmodifiableMapIterator(it);
}
@Override
public synchronized BidiMap<V, K> inverseBidiMap() {
if (inverse == null) {
inverse = new UnmodifiableBidiMap<V, K>(decorated().inverseBidiMap());
inverse.inverse = this;
}
return inverse;
}
}

147
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/UnmodifiableOrderedBidiMap.java

@ -0,0 +1,147 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bidimap;
import java.util.Map;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.OrderedBidiMap;
import com.fr.third.org.apache.commons.collections4.OrderedMapIterator;
import com.fr.third.org.apache.commons.collections4.Unmodifiable;
import com.fr.third.org.apache.commons.collections4.iterators.UnmodifiableOrderedMapIterator;
import com.fr.third.org.apache.commons.collections4.map.UnmodifiableEntrySet;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
/**
* Decorates another {@link OrderedBidiMap} to ensure it can't be altered.
* <p>
* Attempts to modify it will result in an UnsupportedOperationException.
*
* @since 3.0
* @version $Id: UnmodifiableOrderedBidiMap.java 1686855 2015-06-22 13:00:27Z tn $
*/
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 <K> the key type
* @param <V> the value type
* @param map the map to decorate, must not be null
* @return an unmodifiable OrderedBidiMap
* @throws NullPointerException if map is null
* @since 4.0
*/
public static <K, V> OrderedBidiMap<K, V> unmodifiableOrderedBidiMap(
final OrderedBidiMap<? extends K, ? extends V> map) {
if (map instanceof Unmodifiable) {
@SuppressWarnings("unchecked") // safe to upcast
final OrderedBidiMap<K, V> tmpMap = (OrderedBidiMap<K, V>) map;
return tmpMap;
}
return new UnmodifiableOrderedBidiMap<K, V>(map);
}
//-----------------------------------------------------------------------
/**
* Constructor that wraps (not copies).
*
* @param map the map to decorate, must not be null
* @throws NullPointerException if map is null
*/
@SuppressWarnings("unchecked") // safe to upcast
private UnmodifiableOrderedBidiMap(final OrderedBidiMap<? extends K, ? extends V> map) {
super((OrderedBidiMap<K, V>) map);
}
//-----------------------------------------------------------------------
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public V put(final K key, final V value) {
throw new UnsupportedOperationException();
}
@Override
public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
throw new UnsupportedOperationException();
}
@Override
public V remove(final Object key) {
throw new UnsupportedOperationException();
}
@Override
public Set<Map.Entry<K, V>> entrySet() {
final Set<Map.Entry<K, V>> set = super.entrySet();
return UnmodifiableEntrySet.unmodifiableEntrySet(set);
}
@Override
public Set<K> keySet() {
final Set<K> set = super.keySet();
return UnmodifiableSet.unmodifiableSet(set);
}
@Override
public Set<V> values() {
final Set<V> set = super.values();
return UnmodifiableSet.unmodifiableSet(set);
}
//-----------------------------------------------------------------------
@Override
public K removeValue(final Object value) {
throw new UnsupportedOperationException();
}
@Override
public OrderedBidiMap<V, K> inverseBidiMap() {
return inverseOrderedBidiMap();
}
//-----------------------------------------------------------------------
@Override
public OrderedMapIterator<K, V> mapIterator() {
final OrderedMapIterator<K, V> it = decorated().mapIterator();
return UnmodifiableOrderedMapIterator.unmodifiableOrderedMapIterator(it);
}
/**
* Gets an unmodifiable view of this map where the keys and values are reversed.
*
* @return an inverted unmodifiable bidirectional map
*/
public OrderedBidiMap<V, K> inverseOrderedBidiMap() {
if (inverse == null) {
inverse = new UnmodifiableOrderedBidiMap<V, K>(decorated().inverseBidiMap());
inverse.inverse = this;
}
return inverse;
}
}

158
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/UnmodifiableSortedBidiMap.java

@ -0,0 +1,158 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.bidimap;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import com.fr.third.org.apache.commons.collections4.OrderedMapIterator;
import com.fr.third.org.apache.commons.collections4.SortedBidiMap;
import com.fr.third.org.apache.commons.collections4.Unmodifiable;
import com.fr.third.org.apache.commons.collections4.iterators.UnmodifiableOrderedMapIterator;
import com.fr.third.org.apache.commons.collections4.map.UnmodifiableEntrySet;
import com.fr.third.org.apache.commons.collections4.map.UnmodifiableSortedMap;
import com.fr.third.org.apache.commons.collections4.set.UnmodifiableSet;
/**
* Decorates another {@link SortedBidiMap} to ensure it can't be altered.
* <p>
* Attempts to modify it will result in an {@link UnsupportedOperationException}.
*
* @since 3.0
* @version $Id: UnmodifiableSortedBidiMap.java 1686855 2015-06-22 13:00:27Z tn $
*/
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 <K> the key type
* @param <V> the value type
* @param map the map to decorate, must not be null
* @return an unmodifiable SortedBidiMap
* @throws NullPointerException if map is null
* @since 4.0
*/
public static <K, V> SortedBidiMap<K, V> unmodifiableSortedBidiMap(final SortedBidiMap<K, ? extends V> map) {
if (map instanceof Unmodifiable) {
@SuppressWarnings("unchecked") // safe to upcast
final SortedBidiMap<K, V> tmpMap = (SortedBidiMap<K, V>) map;
return tmpMap;
}
return new UnmodifiableSortedBidiMap<K, V>(map);
}
//-----------------------------------------------------------------------
/**
* Constructor that wraps (not copies).
*
* @param map the map to decorate, must not be null
* @throws NullPointerException if map is null
*/
@SuppressWarnings("unchecked") // safe to upcast
private UnmodifiableSortedBidiMap(final SortedBidiMap<K, ? extends V> map) {
super((SortedBidiMap<K, V>) map);
}
//-----------------------------------------------------------------------
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public V put(final K key, final V value) {
throw new UnsupportedOperationException();
}
@Override
public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
throw new UnsupportedOperationException();
}
@Override
public V remove(final Object key) {
throw new UnsupportedOperationException();
}
@Override
public Set<Map.Entry<K, V>> entrySet() {
final Set<Map.Entry<K, V>> set = super.entrySet();
return UnmodifiableEntrySet.unmodifiableEntrySet(set);
}
@Override
public Set<K> keySet() {
final Set<K> set = super.keySet();
return UnmodifiableSet.unmodifiableSet(set);
}
@Override
public Set<V> values() {
final Set<V> set = super.values();
return UnmodifiableSet.unmodifiableSet(set);
}
//-----------------------------------------------------------------------
@Override
public K removeValue(final Object value) {
throw new UnsupportedOperationException();
}
//-----------------------------------------------------------------------
@Override
public OrderedMapIterator<K, V> mapIterator() {
final OrderedMapIterator<K, V> it = decorated().mapIterator();
return UnmodifiableOrderedMapIterator.unmodifiableOrderedMapIterator(it);
}
//-----------------------------------------------------------------------
@Override
public SortedBidiMap<V, K> inverseBidiMap() {
if (inverse == null) {
inverse = new UnmodifiableSortedBidiMap<V, K>(decorated().inverseBidiMap());
inverse.inverse = this;
}
return inverse;
}
@Override
public SortedMap<K, V> subMap(final K fromKey, final K toKey) {
final SortedMap<K, V> sm = decorated().subMap(fromKey, toKey);
return UnmodifiableSortedMap.unmodifiableSortedMap(sm);
}
@Override
public SortedMap<K, V> headMap(final K toKey) {
final SortedMap<K, V> sm = decorated().headMap(toKey);
return UnmodifiableSortedMap.unmodifiableSortedMap(sm);
}
@Override
public SortedMap<K, V> tailMap(final K fromKey) {
final SortedMap<K, V> sm = decorated().tailMap(fromKey);
return UnmodifiableSortedMap.unmodifiableSortedMap(sm);
}
}

41
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/bidimap/package-info.java

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This package contains implementations of the
* {@link org.apache.commons.collections4.BidiMap BidiMap},
* {@link org.apache.commons.collections4.OrderedBidiMap OrderedBidiMap} and
* {@link org.apache.commons.collections4.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>DualLinkedHashBidiMap - uses two LinkedHashMaps 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
* </ul>
*
* @version $Id: package-info.java 1477745 2013-04-30 18:08:32Z tn $
*/
package com.fr.third.org.apache.commons.collections4.bidimap;

178
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/AbstractCollectionDecorator.java

@ -0,0 +1,178 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.collection;
import java.io.Serializable;
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.
* <p>
* This implementation does not forward the hashCode and equals methods through
* to the backing object, but relies on Object's implementation. This is necessary
* to preserve the symmetry of equals. Custom definitions of equality are usually
* based on an interface, such as Set or List, so that the implementation of equals
* can cast the object being tested for equality to the custom interface.
* AbstractCollectionDecorator does not implement such custom interfaces directly;
* they are implemented only in subclasses. Therefore, forwarding equals would break
* symmetry, as the forwarding object might consider itself equal to the object being
* tested, but the reverse could not be true. This behavior is consistent with the
* JDK's collection wrappers, such as {@link java.util.Collections#unmodifiableCollection(Collection)}.
* Use an interface-specific subclass of AbstractCollectionDecorator, such as
* AbstractListDecorator, to preserve equality behavior, or override equals directly.
*
* @param <E> the type of the elements in the collection
* @since 3.0
* @version $Id: AbstractCollectionDecorator.java 1686855 2015-06-22 13:00:27Z tn $
*/
public abstract class AbstractCollectionDecorator<E>
implements Collection<E>, Serializable {
/** Serialization version */
private static final long serialVersionUID = 6249888059822088500L;
/** The collection being decorated */
private Collection<E> collection;
/**
* Constructor only used in deserialization, do not use otherwise.
* @since 3.1
*/
protected AbstractCollectionDecorator() {
super();
}
/**
* Constructor that wraps (not copies).
*
* @param coll the collection to decorate, must not be null
* @throws NullPointerException if the collection is null
*/
protected AbstractCollectionDecorator(final Collection<E> coll) {
if (coll == null) {
throw new NullPointerException("Collection must not be null.");
}
this.collection = coll;
}
/**
* Gets the collection being decorated.
* All access to the decorated collection goes via this method.
*
* @return the decorated collection
*/
protected Collection<E> decorated() {
return collection;
}
/**
* Sets the collection being decorated.
* <p>
* <b>NOTE:</b> this method should only be used during deserialization
*
* @param coll the decorated collection
*/
protected void setCollection(final Collection<E> coll) {
this.collection = coll;
}
//-----------------------------------------------------------------------
@Override
public boolean add(final E object) {
return decorated().add(object);
}
@Override
public boolean addAll(final Collection<? extends E> coll) {
return decorated().addAll(coll);
}
@Override
public void clear() {
decorated().clear();
}
@Override
public boolean contains(final Object object) {
return decorated().contains(object);
}
@Override
public boolean isEmpty() {
return decorated().isEmpty();
}
@Override
public Iterator<E> iterator() {
return decorated().iterator();
}
@Override
public boolean remove(final Object object) {
return decorated().remove(object);
}
@Override
public int size() {
return decorated().size();
}
@Override
public Object[] toArray() {
return decorated().toArray();
}
@Override
public <T> T[] toArray(final T[] object) {
return decorated().toArray(object);
}
@Override
public boolean containsAll(final Collection<?> coll) {
return decorated().containsAll(coll);
}
@Override
public boolean removeAll(final Collection<?> coll) {
return decorated().removeAll(coll);
}
@Override
public boolean retainAll(final Collection<?> coll) {
return decorated().retainAll(coll);
}
@Override
public String toString() {
return decorated().toString();
}
}

483
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/CompositeCollection.java

@ -0,0 +1,483 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.collection;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import com.fr.third.org.apache.commons.collections4.iterators.EmptyIterator;
import com.fr.third.org.apache.commons.collections4.list.UnmodifiableList;
import com.fr.third.org.apache.commons.collections4.iterators.EmptyIterator;
import com.fr.third.org.apache.commons.collections4.iterators.IteratorChain;
import com.fr.third.org.apache.commons.collections4.list.UnmodifiableList;
/**
* Decorates a collection of other collections 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.
*
* @param <E> the type of the elements in the collection
* @since 3.0
* @version $Id: CompositeCollection.java 1683951 2015-06-06 20:19:03Z tn $
*/
public class CompositeCollection<E> implements Collection<E>, Serializable {
/** Serialization version */
private static final long serialVersionUID = 8417515734108306801L;
/** CollectionMutator to handle changes to the collection */
private CollectionMutator<E> mutator;
/** Collections in the composite */
private final List<Collection<E>> all = new ArrayList<Collection<E>>();
/**
* Create an empty CompositeCollection.
*/
public CompositeCollection() {
super();
}
/**
* Create a Composite Collection with one collection.
*
* @param compositeCollection the Collection to be appended to the composite
*/
public CompositeCollection(final Collection<E> compositeCollection) {
super();
addComposited(compositeCollection);
}
/**
* Create a Composite Collection with two collections.
*
* @param compositeCollection1 the Collection to be appended to the composite
* @param compositeCollection2 the Collection to be appended to the composite
*/
public CompositeCollection(final Collection<E> compositeCollection1,
final Collection<E> compositeCollection2) {
super();
addComposited(compositeCollection1, compositeCollection2);
}
/**
* Create a Composite Collection with an array of collections.
*
* @param compositeCollections the collections to composite
*/
public CompositeCollection(final Collection<E>... compositeCollections) {
super();
addComposited(compositeCollections);
}
//-----------------------------------------------------------------------
/**
* 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
*/
@Override
public int size() {
int size = 0;
for (final Collection<E> item : all) {
size += item.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 collections are empty
*/
@Override
public boolean isEmpty() {
for (final Collection<E> item : all) {
if (item.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 collections
*/
@Override
public boolean contains(final Object obj) {
for (final Collection<E> item : all) {
if (item.contains(obj)) {
return true;
}
}
return false;
}
/**
* Gets an iterator over all the collections 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 collections in
* the order they were added, but this behavior should not be relied upon.
* @see IteratorChain
*/
@Override
public Iterator<E> iterator() {
if (all.isEmpty()) {
return EmptyIterator.<E>emptyIterator();
}
final IteratorChain<E> chain = new IteratorChain<E>();
for (final Collection<E> item : all) {
chain.addIterator(item.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
*/
@Override
public Object[] toArray() {
final Object[] result = new Object[size()];
int i = 0;
for (final Iterator<E> it = iterator(); it.hasNext(); i++) {
result[i] = it.next();
}
return result;
}
/**
* Returns an object array, populating the supplied array if possible.
* See <code>Collection</code> interface for full details.
*
* @param <T> the type of the elements in the collection
* @param array the array to use, populating if possible
* @return an array of all the elements in the collection
*/
@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(final T[] array) {
final int size = size();
Object[] result = null;
if (array.length >= size) {
result = array;
} else {
result = (Object[]) Array.newInstance(array.getClass().getComponentType(), size);
}
int offset = 0;
for (final Collection<E> item : all) {
for (final E e : item) {
result[offset++] = e;
}
}
if (result.length > size) {
result[size] = null;
}
return (T[]) result;
}
/**
* Adds an object to the collection, throwing UnsupportedOperationException
* unless a CollectionMutator strategy is specified.
*
* @param obj the object to add
* @return {@code 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
*/
@Override
public boolean add(final E obj) {
if (mutator == null) {
throw new UnsupportedOperationException(
"add() is not supported on CompositeCollection without a CollectionMutator strategy");
}
return mutator.add(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
*/
@Override
public boolean remove(final Object obj) {
if (mutator == null) {
throw new UnsupportedOperationException(
"remove() is not supported on CompositeCollection without a CollectionMutator strategy");
}
return mutator.remove(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
*/
@Override
public boolean containsAll(final Collection<?> coll) {
for (final Object item : coll) {
if (contains(item) == 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
*/
@Override
public boolean addAll(final Collection<? extends E> coll) {
if (mutator == null) {
throw new UnsupportedOperationException(
"addAll() is not supported on CompositeCollection without a CollectionMutator strategy");
}
return mutator.addAll(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
*/
@Override
public boolean removeAll(final Collection<?> coll) {
if (coll.size() == 0) {
return false;
}
boolean changed = false;
for (final Collection<E> item : all) {
changed |= item.removeAll(coll);
}
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
*/
@Override
public boolean retainAll(final Collection<?> coll) {
boolean changed = false;
for (final Collection<E> item : all) {
changed |= item.retainAll(coll);
}
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
*/
@Override
public void clear() {
for (final Collection<E> coll : all) {
coll.clear();
}
}
//-----------------------------------------------------------------------
/**
* Specify a CollectionMutator strategy instance to handle changes.
*
* @param mutator the mutator to use
*/
public void setMutator(final CollectionMutator<E> mutator) {
this.mutator = mutator;
}
/**
* Add these Collections to the list of collections in this composite
*
* @param compositeCollection the Collection to be appended to the composite
*/
public void addComposited(final Collection<E> compositeCollection) {
all.add(compositeCollection);
}
/**
* Add these Collections to the list of collections in this composite
*
* @param compositeCollection1 the Collection to be appended to the composite
* @param compositeCollection2 the Collection to be appended to the composite
*/
public void addComposited(final Collection<E> compositeCollection1,
final Collection<E> compositeCollection2) {
all.add(compositeCollection1);
all.add(compositeCollection2);
}
/**
* Add these Collections to the list of collections in this composite
*
* @param compositeCollections the Collections to be appended to the composite
*/
public void addComposited(final Collection<E>... compositeCollections) {
all.addAll(Arrays.asList(compositeCollections));
}
/**
* Removes a collection from the those being decorated in this composite.
*
* @param coll collection to be removed
*/
public void removeComposited(final Collection<E> coll) {
all.remove(coll);
}
//-----------------------------------------------------------------------
/**
* 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 collections being decorated.
*
* @return Unmodifiable list of all collections in this composite.
*/
public List<Collection<E>> getCollections() {
return UnmodifiableList.unmodifiableList(all);
}
/**
* Get the collection mutator to be used for this CompositeCollection.
* @return CollectionMutator<E>
*/
protected CollectionMutator<E> getMutator() {
return mutator;
}
//-----------------------------------------------------------------------
/**
* Pluggable strategy to handle changes to the composite.
*
* @param <E> the element being held in the collection
*/
public interface CollectionMutator<E> extends Serializable {
/**
* 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
*/
boolean add(CompositeCollection<E> composite, List<Collection<E>> collections, E 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
*/
boolean addAll(CompositeCollection<E> composite,
List<Collection<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
*/
boolean remove(CompositeCollection<E> composite,
List<Collection<E>> collections,
Object obj);
}
}

263
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/IndexedCollection.java

@ -0,0 +1,263 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.collection;
import java.util.Collection;
import java.util.HashMap;
import com.fr.third.org.apache.commons.collections4.MultiMap;
import com.fr.third.org.apache.commons.collections4.Transformer;
import com.fr.third.org.apache.commons.collections4.map.MultiValueMap;
import com.fr.third.org.apache.commons.collections4.MultiMap;
import com.fr.third.org.apache.commons.collections4.Transformer;
import com.fr.third.org.apache.commons.collections4.map.MultiValueMap;
/**
* An IndexedCollection is a Map-like view onto a Collection. It accepts a
* keyTransformer to define how the keys are converted from the values.
* <p>
* Modifications made to this decorator modify the index as well as the
* decorated {@link Collection}. However, modifications to the underlying
* {@link Collection} will not update the index and it will get out of sync.
* <p>
* If modification of the decorated {@link Collection} is unavoidable, then a
* call to {@link #reindex()} will update the index to the current contents of
* the {@link Collection}.
*
* @param <K> the type of object in the index.
* @param <C> the type of object in the collection.
*
* @since 4.0
* @version $Id: IndexedCollection.java 1683018 2015-06-01 22:41:31Z tn $
*/
public class IndexedCollection<K, C> extends AbstractCollectionDecorator<C> {
// TODO: replace with MultiValuedMap
/** Serialization version */
private static final long serialVersionUID = -5512610452568370038L;
/** The {@link Transformer} for generating index keys. */
private final Transformer<C, K> keyTransformer;
/** The map of indexes to collected objects. */
private final MultiMap<K, C> index;
/** The uniqueness constraint for the index. */
private final boolean uniqueIndex;
/**
* Create an {@link IndexedCollection} for a unique index.
* <p>
* If an element is added, which maps to an existing key, an {@link IllegalArgumentException}
* will be thrown.
*
* @param <K> the index object type.
* @param <C> the collection type.
* @param coll the decorated {@link Collection}.
* @param keyTransformer the {@link Transformer} for generating index keys.
* @return the created {@link IndexedCollection}.
*/
public static <K, C> IndexedCollection<K, C> uniqueIndexedCollection(final Collection<C> coll,
final Transformer<C, K> keyTransformer) {
return new IndexedCollection<K, C>(coll, keyTransformer,
MultiValueMap.<K, C>multiValueMap(new HashMap<K, Collection<C>>()),
true);
}
/**
* Create an {@link IndexedCollection} for a non-unique index.
*
* @param <K> the index object type.
* @param <C> the collection type.
* @param coll the decorated {@link Collection}.
* @param keyTransformer the {@link Transformer} for generating index keys.
* @return the created {@link IndexedCollection}.
*/
public static <K, C> IndexedCollection<K, C> nonUniqueIndexedCollection(final Collection<C> coll,
final Transformer<C, K> keyTransformer) {
return new IndexedCollection<K, C>(coll, keyTransformer,
MultiValueMap.<K, C>multiValueMap(new HashMap<K, Collection<C>>()),
false);
}
/**
* Create a {@link IndexedCollection}.
*
* @param coll decorated {@link Collection}
* @param keyTransformer {@link Transformer} for generating index keys
* @param map map to use as index
* @param uniqueIndex if the index shall enforce uniqueness of index keys
*/
public IndexedCollection(final Collection<C> coll, final Transformer<C, K> keyTransformer,
final MultiMap<K, C> map, final boolean uniqueIndex) {
super(coll);
this.keyTransformer = keyTransformer;
this.index = map;
this.uniqueIndex = uniqueIndex;
reindex();
}
/**
* {@inheritDoc}
*
* @throws IllegalArgumentException if the object maps to an existing key and the index
* enforces a uniqueness constraint
*/
@Override
public boolean add(final C object) {
final boolean added = super.add(object);
if (added) {
addToIndex(object);
}
return added;
}
@Override
public boolean addAll(final Collection<? extends C> coll) {
boolean changed = false;
for (final C c: coll) {
changed |= add(c);
}
return changed;
}
@Override
public void clear() {
super.clear();
index.clear();
}
/**
* {@inheritDoc}
* <p>
* Note: uses the index for fast lookup
*/
@SuppressWarnings("unchecked")
@Override
public boolean contains(final Object object) {
return index.containsKey(keyTransformer.transform((C) object));
}
/**
* {@inheritDoc}
* <p>
* Note: uses the index for fast lookup
*/
@Override
public boolean containsAll(final Collection<?> coll) {
for (final Object o : coll) {
if (!contains(o)) {
return false;
}
}
return true;
}
/**
* Get the element associated with the given key.
* <p>
* In case of a non-unique index, this method will return the first
* value associated with the given key. To retrieve all elements associated
* with a key, use {@link #values(Object)}.
*
* @param key key to look up
* @return element found
* @see #values(Object)
*/
public C get(final K key) {
@SuppressWarnings("unchecked") // index is a MultiMap which returns a Collection
final Collection<C> coll = (Collection<C>) index.get(key);
return coll == null ? null : coll.iterator().next();
}
/**
* Get all elements associated with the given key.
*
* @param key key to look up
* @return a collection of elements found, or null if {@code contains(key) == false}
*/
@SuppressWarnings("unchecked") // index is a MultiMap which returns a Collection
public Collection<C> values(final K key) {
return (Collection<C>) index.get(key);
}
/**
* Clears the index and re-indexes the entire decorated {@link Collection}.
*/
public void reindex() {
index.clear();
for (final C c : decorated()) {
addToIndex(c);
}
}
@SuppressWarnings("unchecked")
@Override
public boolean remove(final Object object) {
final boolean removed = super.remove(object);
if (removed) {
removeFromIndex((C) object);
}
return removed;
}
@Override
public boolean removeAll(final Collection<?> coll) {
boolean changed = false;
for (final Object o : coll) {
changed |= remove(o);
}
return changed;
}
@Override
public boolean retainAll(final Collection<?> coll) {
final boolean changed = super.retainAll(coll);
if (changed) {
reindex();
}
return changed;
}
//-----------------------------------------------------------------------
/**
* Provides checking for adding the index.
*
* @param object the object to index
* @throws IllegalArgumentException if the object maps to an existing key and the index
* enforces a uniqueness constraint
*/
private void addToIndex(final C object) {
final K key = keyTransformer.transform(object);
if (uniqueIndex && index.containsKey(key)) {
throw new IllegalArgumentException("Duplicate key in uniquely indexed collection.");
}
index.put(key, object);
}
/**
* Removes an object from the index.
*
* @param object the object to remove
*/
private void removeFromIndex(final C object) {
index.remove(keyTransformer.transform(object));
}
}

455
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/PredicatedCollection.java

@ -0,0 +1,455 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import com.fr.third.org.apache.commons.collections4.Bag;
import com.fr.third.org.apache.commons.collections4.MultiSet;
import com.fr.third.org.apache.commons.collections4.Predicate;
import com.fr.third.org.apache.commons.collections4.bag.HashBag;
import com.fr.third.org.apache.commons.collections4.bag.PredicatedBag;
import com.fr.third.org.apache.commons.collections4.functors.NotNullPredicate;
import com.fr.third.org.apache.commons.collections4.list.PredicatedList;
import com.fr.third.org.apache.commons.collections4.multiset.HashMultiSet;
import com.fr.third.org.apache.commons.collections4.multiset.PredicatedMultiSet;
import com.fr.third.org.apache.commons.collections4.queue.PredicatedQueue;
import com.fr.third.org.apache.commons.collections4.set.PredicatedSet;
import com.fr.third.org.apache.commons.collections4.Bag;
import com.fr.third.org.apache.commons.collections4.MultiSet;
import com.fr.third.org.apache.commons.collections4.Predicate;
import com.fr.third.org.apache.commons.collections4.bag.HashBag;
import com.fr.third.org.apache.commons.collections4.bag.PredicatedBag;
import com.fr.third.org.apache.commons.collections4.functors.NotNullPredicate;
import com.fr.third.org.apache.commons.collections4.list.PredicatedList;
import com.fr.third.org.apache.commons.collections4.multiset.HashMultiSet;
import com.fr.third.org.apache.commons.collections4.multiset.PredicatedMultiSet;
import com.fr.third.org.apache.commons.collections4.queue.PredicatedQueue;
import com.fr.third.org.apache.commons.collections4.set.PredicatedSet;
/**
* Decorates another {@link Collection} 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.predicatedCollection(new ArrayList(), NotNullPredicate.INSTANCE);
* </pre>
* <p>
* This class is Serializable from Commons Collections 3.1.
*
* @param <E> the type of the elements in the collection
* @since 3.0
* @version $Id: PredicatedCollection.java 1714484 2015-11-15 18:20:41Z tn $
*/
public class PredicatedCollection<E> extends AbstractCollectionDecorator<E> {
/** Serialization version */
private static final long serialVersionUID = -5259182142076705162L;
/** The predicate to use */
protected final Predicate<? super E> predicate;
/**
* Returns a Builder with the given predicate.
*
* @param <E> the element type
* @param predicate the predicate to use
* @return a new Builder for predicated collections
* @since 4.1
*/
public static <E> Builder<E> builder(final Predicate<? super E> predicate) {
return new Builder<E>(predicate);
}
/**
* Returns a Builder with a NotNullPredicate.
*
* @param <E> the element type
* @return a new Builder for predicated collections that ignores null values.
* @since 4.1
*/
public static <E> Builder<E> notNullBuilder() {
return new Builder<E>(NotNullPredicate.<E>notNullPredicate());
}
/**
* Factory method to create a predicated (validating) collection.
* <p>
* If there are any elements already in the collection being decorated, they
* are validated.
*
* @param <T> the type of the elements in the collection
* @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 NullPointerException if collection or predicate is null
* @throws IllegalArgumentException if the collection contains invalid elements
* @since 4.0
*/
public static <T> PredicatedCollection<T> predicatedCollection(final Collection<T> coll,
final Predicate<? super T> predicate) {
return new PredicatedCollection<T>(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 NullPointerException if collection or predicate is null
* @throws IllegalArgumentException if the collection contains invalid elements
*/
protected PredicatedCollection(final Collection<E> coll, final Predicate<? super E> predicate) {
super(coll);
if (predicate == null) {
throw new NullPointerException("Predicate must not be null.");
}
this.predicate = predicate;
for (final E item : coll) {
validate(item);
}
}
/**
* 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(final E object) {
if (predicate.evaluate(object) == false) {
throw new IllegalArgumentException("Cannot add Object '" + object + "' - Predicate '" +
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
*/
@Override
public boolean add(final E object) {
validate(object);
return decorated().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
*/
@Override
public boolean addAll(final Collection<? extends E> coll) {
for (final E item : coll) {
validate(item);
}
return decorated().addAll(coll);
}
/**
* Builder for creating predicated collections.
* <p>
* Create a Builder with a predicate to validate elements against, then add any elements
* to the builder. Elements that fail the predicate will be added to a rejected list.
* Finally create or decorate a collection using the createPredicated[List,Set,Bag,Queue] methods.
* <p>
* An example:
* <pre>
* Predicate&lt;String&gt; predicate = NotNullPredicate.notNullPredicate();
* PredicatedCollectionBuilder&lt;String&gt; builder = PredicatedCollection.builder(predicate);
* builder.add("item1");
* builder.add(null);
* builder.add("item2");
* List&lt;String&gt; predicatedList = builder.createPredicatedList();
* </pre>
* <p>
* At the end of the code fragment above predicatedList is protected by the predicate supplied
* to the builder and it contains item1 and item2.
* <p>
* More elements can be added to the builder once a predicated collection has been created,
* but these elements will not be reflected in already created collections.
*
* @param <E> the element type
* @since 4.1
*/
public static class Builder<E> {
/** The predicate to use. */
private final Predicate<? super E> predicate;
/** The buffer containing valid elements. */
private final List<E> accepted = new ArrayList<E>();
/** The buffer containing rejected elements. */
private final List<E> rejected = new ArrayList<E>();
// -----------------------------------------------------------------------
/**
* Constructs a PredicatedCollectionBuilder with the specified Predicate.
*
* @param predicate the predicate to use
* @throws NullPointerException if predicate is null
*/
public Builder(final Predicate<? super E> predicate) {
if (predicate == null) {
throw new NullPointerException("Predicate must not be null");
}
this.predicate = predicate;
}
/**
* Adds the item to the builder.
* <p>
* If the predicate is true, it is added to the list of accepted elements,
* otherwise it is added to the rejected list.
*
* @param item the element to add
* @return the PredicatedCollectionBuilder.
*/
public Builder<E> add(final E item) {
if (predicate.evaluate(item)) {
accepted.add(item);
} else {
rejected.add(item);
}
return this;
}
/**
* Adds all elements from the given collection to the builder.
* <p>
* All elements for which the predicate evaluates to true will be added to the
* list of accepted elements, otherwise they are added to the rejected list.
*
* @param items the elements to add to the builder
* @return the PredicatedCollectionBuilder.
*/
public Builder<E> addAll(final Collection<? extends E> items) {
if (items != null) {
for (E item : items) {
add(item);
}
}
return this;
}
/**
* Create a new predicated list filled with the accepted elements.
* <p>
* The builder is not modified by this method, so it is possible to create more collections
* or add more elements afterwards. Further changes will not propagate to the returned list.
*
* @return a new predicated list.
*/
public List<E> createPredicatedList() {
return createPredicatedList(new ArrayList<E>());
}
/**
* Decorates the given list with validating behavior using the predicate. All accepted elements
* are appended to the list. If the list already contains elements, they are validated.
* <p>
* The builder is not modified by this method, so it is possible to create more collections
* or add more elements afterwards. Further changes will not propagate to the returned list.
*
* @param list the List to decorate, must not be null
* @return the decorated list.
* @throws NullPointerException if list is null
* @throws IllegalArgumentException if list contains invalid elements
*/
public List<E> createPredicatedList(final List<E> list) {
if (list == null) {
throw new NullPointerException("List must not be null.");
}
final List<E> predicatedList = PredicatedList.predicatedList(list, predicate);
predicatedList.addAll(accepted);
return predicatedList;
}
/**
* Create a new predicated set filled with the accepted elements.
* <p>
* The builder is not modified by this method, so it is possible to create more collections
* or add more elements afterwards. Further changes will not propagate to the returned set.
*
* @return a new predicated set.
*/
public Set<E> createPredicatedSet() {
return createPredicatedSet(new HashSet<E>());
}
/**
* Decorates the given list with validating behavior using the predicate. All accepted elements
* are appended to the set. If the set already contains elements, they are validated.
* <p>
* The builder is not modified by this method, so it is possible to create more collections
* or add more elements afterwards. Further changes will not propagate to the returned set.
*
* @param set the set to decorate, must not be null
* @return the decorated set.
* @throws NullPointerException if set is null
* @throws IllegalArgumentException if set contains invalid elements
*/
public Set<E> createPredicatedSet(final Set<E> set) {
if (set == null) {
throw new NullPointerException("Set must not be null.");
}
final PredicatedSet<E> predicatedSet = PredicatedSet.predicatedSet(set, predicate);
predicatedSet.addAll(accepted);
return predicatedSet;
}
/**
* Create a new predicated multiset filled with the accepted elements.
* <p>
* The builder is not modified by this method, so it is possible to create more collections
* or add more elements afterwards. Further changes will not propagate to the returned multiset.
*
* @return a new predicated multiset.
*/
public MultiSet<E> createPredicatedMultiSet() {
return createPredicatedMultiSet(new HashMultiSet<E>());
}
/**
* Decorates the given multiset with validating behavior using the predicate. All accepted elements
* are appended to the multiset. If the multiset already contains elements, they are validated.
* <p>
* The builder is not modified by this method, so it is possible to create more collections
* or add more elements afterwards. Further changes will not propagate to the returned multiset.
*
* @param multiset the multiset to decorate, must not be null
* @return the decorated multiset.
* @throws NullPointerException if multiset is null
* @throws IllegalArgumentException if multiset contains invalid elements
*/
public MultiSet<E> createPredicatedMultiSet(final MultiSet<E> multiset) {
if (multiset == null) {
throw new NullPointerException("MultiSet must not be null.");
}
final PredicatedMultiSet<E> predicatedMultiSet =
PredicatedMultiSet.predicatedMultiSet(multiset, predicate);
predicatedMultiSet.addAll(accepted);
return predicatedMultiSet;
}
/**
* Create a new predicated bag filled with the accepted elements.
* <p>
* The builder is not modified by this method, so it is possible to create more collections
* or add more elements afterwards. Further changes will not propagate to the returned bag.
*
* @return a new predicated bag.
*/
public Bag<E> createPredicatedBag() {
return createPredicatedBag(new HashBag<E>());
}
/**
* Decorates the given bag with validating behavior using the predicate. All accepted elements
* are appended to the bag. If the bag already contains elements, they are validated.
* <p>
* The builder is not modified by this method, so it is possible to create more collections
* or add more elements afterwards. Further changes will not propagate to the returned bag.
*
* @param bag the bag to decorate, must not be null
* @return the decorated bag.
* @throws NullPointerException if bag is null
* @throws IllegalArgumentException if bag contains invalid elements
*/
public Bag<E> createPredicatedBag(final Bag<E> bag) {
if (bag == null) {
throw new NullPointerException("Bag must not be null.");
}
final PredicatedBag<E> predicatedBag = PredicatedBag.predicatedBag(bag, predicate);
predicatedBag.addAll(accepted);
return predicatedBag;
}
/**
* Create a new predicated queue filled with the accepted elements.
* <p>
* The builder is not modified by this method, so it is possible to create more collections
* or add more elements afterwards. Further changes will not propagate to the returned queue.
*
* @return a new predicated queue.
*/
public Queue<E> createPredicatedQueue() {
return createPredicatedQueue(new LinkedList<E>());
}
/**
* Decorates the given queue with validating behavior using the predicate. All accepted elements
* are appended to the queue. If the queue already contains elements, they are validated.
* <p>
* The builder is not modified by this method, so it is possible to create more collections
* or add more elements afterwards. Further changes will not propagate to the returned queue.
*
* @param queue the queue to decorate, must not be null
* @return the decorated queue.
* @throws NullPointerException if queue is null
* @throws IllegalArgumentException if queue contains invalid elements
*/
public Queue<E> createPredicatedQueue(final Queue<E> queue) {
if (queue == null) {
throw new NullPointerException("queue must not be null");
}
final PredicatedQueue<E> predicatedQueue = PredicatedQueue.predicatedQueue(queue, predicate);
predicatedQueue.addAll(accepted);
return predicatedQueue;
}
/**
* Returns an unmodifiable collection containing all rejected elements.
*
* @return an unmodifiable collection
*/
public Collection<E> rejectedElements() {
return Collections.unmodifiableCollection(rejected);
}
}
}

232
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/SynchronizedCollection.java

@ -0,0 +1,232 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.collection;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
/**
* Decorates another {@link Collection} 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.
*
* @param <E> the type of the elements in the collection
* @since 3.0
* @version $Id: SynchronizedCollection.java 1686855 2015-06-22 13:00:27Z tn $
*/
public class SynchronizedCollection<E> implements Collection<E>, Serializable {
/** Serialization version */
private static final long serialVersionUID = 2412805092710877986L;
/** The collection to decorate */
private 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 <T> the type of the elements in the collection
* @param coll the collection to decorate, must not be null
* @return a new synchronized collection
* @throws NullPointerException if collection is null
* @since 4.0
*/
public static <T> SynchronizedCollection<T> synchronizedCollection(final Collection<T> coll) {
return new SynchronizedCollection<T>(coll);
}
//-----------------------------------------------------------------------
/**
* Constructor that wraps (not copies).
*
* @param collection the collection to decorate, must not be null
* @throws NullPointerException if the collection is null
*/
protected SynchronizedCollection(final Collection<E> collection) {
if (collection == null) {
throw new NullPointerException("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 NullPointerException if the collection or lock is null
*/
protected SynchronizedCollection(final Collection<E> collection, final Object lock) {
if (collection == null) {
throw new NullPointerException("Collection must not be null.");
}
if (lock == null) {
throw new NullPointerException("Lock must not be null.");
}
this.collection = collection;
this.lock = lock;
}
/**
* Gets the collection being decorated.
*
* @return the decorated collection
*/
protected Collection<E> decorated() {
return collection;
}
//-----------------------------------------------------------------------
@Override
public boolean add(final E object) {
synchronized (lock) {
return decorated().add(object);
}
}
@Override
public boolean addAll(final Collection<? extends E> coll) {
synchronized (lock) {
return decorated().addAll(coll);
}
}
@Override
public void clear() {
synchronized (lock) {
decorated().clear();
}
}
@Override
public boolean contains(final Object object) {
synchronized (lock) {
return decorated().contains(object);
}
}
@Override
public boolean containsAll(final Collection<?> coll) {
synchronized (lock) {
return decorated().containsAll(coll);
}
}
@Override
public boolean isEmpty() {
synchronized (lock) {
return decorated().isEmpty();
}
}
/**
* Iterators must be manually synchronized.
* <pre>
* synchronized (coll) {
* Iterator it = coll.iterator();
* // do stuff with iterator
* }
* </pre>
*
* @return an iterator that must be manually synchronized on the collection
*/
@Override
public Iterator<E> iterator() {
return decorated().iterator();
}
@Override
public Object[] toArray() {
synchronized (lock) {
return decorated().toArray();
}
}
@Override
public <T> T[] toArray(final T[] object) {
synchronized (lock) {
return decorated().toArray(object);
}
}
@Override
public boolean remove(final Object object) {
synchronized (lock) {
return decorated().remove(object);
}
}
@Override
public boolean removeAll(final Collection<?> coll) {
synchronized (lock) {
return decorated().removeAll(coll);
}
}
@Override
public boolean retainAll(final Collection<?> coll) {
synchronized (lock) {
return decorated().retainAll(coll);
}
}
@Override
public int size() {
synchronized (lock) {
return decorated().size();
}
}
@Override
public boolean equals(final Object object) {
synchronized (lock) {
if (object == this) {
return true;
}
return object == this || decorated().equals(object);
}
}
@Override
public int hashCode() {
synchronized (lock) {
return decorated().hashCode();
}
}
@Override
public String toString() {
synchronized (lock) {
return decorated().toString();
}
}
}

156
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/TransformedCollection.java

@ -0,0 +1,156 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.collection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.fr.third.org.apache.commons.collections4.Transformer;
import com.fr.third.org.apache.commons.collections4.Transformer;
/**
* Decorates another {@link Collection} 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.
*
* @param <E> the type of the elements in the collection
* @since 3.0
* @version $Id: TransformedCollection.java 1686855 2015-06-22 13:00:27Z tn $
*/
public class TransformedCollection<E> extends AbstractCollectionDecorator<E> {
/** Serialization version */
private static final long serialVersionUID = 8692300188161871514L;
/** The transformer to use */
protected final Transformer<? super E, ? extends E> transformer;
/**
* Factory method to create a transforming collection.
* <p>
* If there are any elements already in the collection being decorated, they
* are NOT transformed.
* Contrast this with {@link #transformedCollection(Collection, Transformer)}.
*
* @param <E> the type of the elements in the collection
* @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 NullPointerException if collection or transformer is null
* @since 4.0
*/
public static <E> TransformedCollection<E> transformingCollection(final Collection<E> coll,
final Transformer<? super E, ? extends E> transformer) {
return new TransformedCollection<E>(coll, transformer);
}
/**
* Factory method to create a transforming collection that will transform
* existing contents of the specified collection.
* <p>
* If there are any elements already in the collection being decorated, they
* will be transformed by this method.
* Contrast this with {@link #transformingCollection(Collection, Transformer)}.
*
* @param <E> the type of the elements in the collection
* @param collection 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 NullPointerException if collection or transformer is null
* @since 4.0
*/
public static <E> TransformedCollection<E> transformedCollection(final Collection<E> collection,
final Transformer<? super E, ? extends E> transformer) {
final TransformedCollection<E> decorated = new TransformedCollection<E>(collection, transformer);
// null collection & transformer are disallowed by the constructor call above
if (collection.size() > 0) {
@SuppressWarnings("unchecked") // collection is of type E
final E[] values = (E[]) collection.toArray(); // NOPMD - false positive for generics
collection.clear();
for (final E value : values) {
decorated.decorated().add(transformer.transform(value));
}
}
return decorated;
}
//-----------------------------------------------------------------------
/**
* 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 NullPointerException if collection or transformer is null
*/
protected TransformedCollection(final Collection<E> coll, final Transformer<? super E, ? extends E> transformer) {
super(coll);
if (transformer == null) {
throw new NullPointerException("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 E transform(final E 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<E> transform(final Collection<? extends E> coll) {
final List<E> list = new ArrayList<E>(coll.size());
for (final E item : coll) {
list.add(transform(item));
}
return list;
}
//-----------------------------------------------------------------------
@Override
public boolean add(final E object) {
return decorated().add(transform(object));
}
@Override
public boolean addAll(final Collection<? extends E> coll) {
return decorated().addAll(transform(coll));
}
}

168
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/UnmodifiableBoundedCollection.java

@ -0,0 +1,168 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.collection;
import java.util.Collection;
import java.util.Iterator;
import com.fr.third.org.apache.commons.collections4.BoundedCollection;
import com.fr.third.org.apache.commons.collections4.Unmodifiable;
import com.fr.third.org.apache.commons.collections4.BoundedCollection;
import com.fr.third.org.apache.commons.collections4.Unmodifiable;
import com.fr.third.org.apache.commons.collections4.iterators.UnmodifiableIterator;
/**
* {@link UnmodifiableBoundedCollection} decorates another
* {@link BoundedCollection} 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.
* <p>
* Attempts to modify it will result in an UnsupportedOperationException.
*
* @since 3.0
* @version $Id: UnmodifiableBoundedCollection.java 1686855 2015-06-22 13:00:27Z tn $
*/
public final class UnmodifiableBoundedCollection<E> extends AbstractCollectionDecorator<E>
implements BoundedCollection<E>, Unmodifiable {
/** Serialization version */
private static final long serialVersionUID = -7112672385450340330L;
/**
* Factory method to create an unmodifiable bounded collection.
*
* @param <E> the type of the elements in the collection
* @param coll the <code>BoundedCollection</code> to decorate, must not be null
* @return a new unmodifiable bounded collection
* @throws NullPointerException if {@code coll} is {@code null}
* @since 4.0
*/
public static <E> BoundedCollection<E> unmodifiableBoundedCollection(final BoundedCollection<? extends E> coll) {
if (coll instanceof Unmodifiable) {
@SuppressWarnings("unchecked") // safe to upcast
final BoundedCollection<E> tmpColl = (BoundedCollection<E>) coll;
return tmpColl;
}
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 <E> the type of the elements in the collection
* @param coll the <code>BoundedCollection</code> to decorate, must not be null
* @return a new unmodifiable bounded collection
* @throws NullPointerException if coll is null
* @throws IllegalArgumentException if coll is not a {@code BoundedCollection}
* @since 4.0
*/
@SuppressWarnings("unchecked")
public static <E> BoundedCollection<E> unmodifiableBoundedCollection(Collection<? extends E> coll) {
if (coll == null) {
throw new NullPointerException("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
}
if (coll instanceof AbstractCollectionDecorator) {
coll = ((AbstractCollectionDecorator<E>) coll).decorated();
} else if (coll instanceof SynchronizedCollection) {
coll = ((SynchronizedCollection<E>) coll).decorated();
}
}
if (coll instanceof BoundedCollection == false) {
throw new IllegalArgumentException("Collection is not a bounded collection.");
}
return new UnmodifiableBoundedCollection<E>((BoundedCollection<E>) coll);
}
/**
* Constructor that wraps (not copies).
*
* @param coll the collection to decorate, must not be null
* @throws NullPointerException if coll is null
*/
@SuppressWarnings("unchecked") // safe to upcast
private UnmodifiableBoundedCollection(final BoundedCollection<? extends E> coll) {
super((BoundedCollection<E>) coll);
}
//-----------------------------------------------------------------------
@Override
public Iterator<E> iterator() {
return UnmodifiableIterator.unmodifiableIterator(decorated().iterator());
}
@Override
public boolean add(final E object) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(final Collection<? extends E> coll) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(final Object object) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(final Collection<?> coll) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(final Collection<?> coll) {
throw new UnsupportedOperationException();
}
//-----------------------------------------------------------------------
@Override
public boolean isFull() {
return decorated().isFull();
}
@Override
public int maxSize() {
return decorated().maxSize();
}
@Override
protected BoundedCollection<E> decorated() {
return (BoundedCollection<E>) super.decorated();
}
}

112
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/UnmodifiableCollection.java

@ -0,0 +1,112 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.collection;
import java.util.Collection;
import java.util.Iterator;
import com.fr.third.org.apache.commons.collections4.Unmodifiable;
import com.fr.third.org.apache.commons.collections4.Unmodifiable;
import com.fr.third.org.apache.commons.collections4.iterators.UnmodifiableIterator;
/**
* Decorates another {@link Collection} to ensure it can't be altered.
* <p>
* This class is Serializable from Commons Collections 3.1.
* <p>
* Attempts to modify it will result in an UnsupportedOperationException.
*
* @param <E> the type of the elements in the collection
* @since 3.0
* @version $Id: UnmodifiableCollection.java 1686855 2015-06-22 13:00:27Z tn $
*/
public final class UnmodifiableCollection<E>
extends AbstractCollectionDecorator<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 <T> the type of the elements in the collection
* @param coll the collection to decorate, must not be null
* @return an unmodifiable collection
* @throws NullPointerException if collection is null
* @since 4.0
*/
public static <T> Collection<T> unmodifiableCollection(final Collection<? extends T> coll) {
if (coll instanceof Unmodifiable) {
@SuppressWarnings("unchecked") // safe to upcast
final Collection<T> tmpColl = (Collection<T>) coll;
return tmpColl;
}
return new UnmodifiableCollection<T>(coll);
}
//-----------------------------------------------------------------------
/**
* Constructor that wraps (not copies).
*
* @param coll the collection to decorate, must not be null
* @throws NullPointerException if collection is null
*/
@SuppressWarnings("unchecked") // safe to upcast
private UnmodifiableCollection(final Collection<? extends E> coll) {
super((Collection<E>) coll);
}
//-----------------------------------------------------------------------
@Override
public Iterator<E> iterator() {
return UnmodifiableIterator.unmodifiableIterator(decorated().iterator());
}
@Override
public boolean add(final E object) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(final Collection<? extends E> coll) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(final Object object) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(final Collection<?> coll) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(final Collection<?> coll) {
throw new UnsupportedOperationException();
}
}

36
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/collection/package-info.java

@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* 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>Transformed - transforms elements as they are added
* <li>Indexed - provides a map-like view onto another collection
* </ul>
*
* @version $Id: package-info.java 1477746 2013-04-30 18:11:20Z tn $
*/
package com.fr.third.org.apache.commons.collections4.collection;

192
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/BooleanComparator.java

@ -0,0 +1,192 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.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>
* @see #getTrueFirstComparator()
* @see #getFalseFirstComparator()
* @see #booleanComparator(boolean)
*
* @since 3.0
* @version $Id: BooleanComparator.java 1683951 2015-06-06 20:19:03Z tn $
*/
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>&#x21;<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
* @since 4.0
*/
public static BooleanComparator booleanComparator(final 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>&#x21;<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(final boolean trueFirst) {
this.trueFirst = trueFirst;
}
//-----------------------------------------------------------------------
/**
* Compares two non-<code>null</code> <code>Boolean</code> objects
* according to the value of {@link #sortsTrueFirst()}.
*
* @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>
*/
@Override
public int compare(final Boolean b1, final Boolean b2) {
final boolean v1 = b1.booleanValue();
final 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.
*/
@Override
public int hashCode() {
final 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 value of {@link #sortsTrueFirst()} is equal to mine.
*
* @param object the object to compare to
* @return true if equal
*/
@Override
public boolean equals(final 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;
}
}

130
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/ComparableComparator.java

@ -0,0 +1,130 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.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 {@link java.util.SortedSet SortedSet} and
* {@link java.util.SortedMap 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.
*
* @since 2.0
* @version $Id: ComparableComparator.java 1683951 2015-06-06 20:19:03Z tn $
*
* @see java.util.Collections#reverseOrder()
*/
public class ComparableComparator<E extends Comparable<? super E>> implements Comparator<E>, Serializable {
/** Serialization version. */
private static final long serialVersionUID=-291439688585137865L;
/** The singleton instance. */
@SuppressWarnings("rawtypes")
public 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.
*
* @param <E> the element type
* @return the singleton ComparableComparator
* @since 4.0
*/
@SuppressWarnings("unchecked")
public static <E extends Comparable<? super E>> ComparableComparator<E> comparableComparator() {
return INSTANCE;
}
//-----------------------------------------------------------------------
/**
* Constructor whose use should be avoided.
* <p>
* Please use the {@link #comparableComparator()} 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 if <i>obj1</i> is <code>null</code>,
* or when <code>((Comparable)obj1).compareTo(obj2)</code> does
* @throws ClassCastException if <i>obj1</i> is not a <code>Comparable</code>,
* or when <code>((Comparable)obj1).compareTo(obj2)</code> does
*/
@Override
public int compare(final E obj1, final E 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 3.0
*/
@Override
public int hashCode() {
return "ComparableComparator".hashCode();
}
/**
* Returns {@code true} 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} 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 {@code true} if equal
* @since 3.0
*/
@Override
public boolean equals(final Object object) {
return this == object ||
null != object && object.getClass().equals(this.getClass());
}
}

349
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/ComparatorChain.java

@ -0,0 +1,349 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.comparators;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
/**
* 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>
* To further facilitate SQL-like sorting, the order of any single Comparator in
* the list can be reversed.
* <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>
* 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.
*
* @since 2.0
* @version $Id: ComparatorChain.java 1683951 2015-06-06 20:19:03Z tn $
*/
public class ComparatorChain<E> implements Comparator<E>, Serializable {
/** Serialization version from Collections 2.0. */
private static final long serialVersionUID = -721644942746081630L;
/** The list of comparators in the chain. */
private final List<Comparator<E>> comparatorChain;
/** Order - false (clear) = ascend; true (set) = descend. */
private BitSet orderingBits = null;
/** Whether the chain has been "locked". */
private 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<E>>(), new BitSet());
}
/**
* Construct a ComparatorChain with a single Comparator,
* sorting in the forward order
*
* @param comparator First comparator in the Comparator chain
*/
public ComparatorChain(final Comparator<E> 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(final Comparator<E> comparator, final boolean reverse) {
comparatorChain = new ArrayList<Comparator<E>>(1);
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(final List<Comparator<E>> 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(final List<Comparator<E>> list, final 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(final Comparator<E> 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(final Comparator<E> comparator, final 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
* @exception IndexOutOfBoundsException
* if index &lt; 0 or index &gt;= size()
*/
public void setComparator(final int index, final Comparator<E> 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(final int index, final Comparator<E> comparator, final 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(final 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(final 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;
}
/**
* Throws an exception if the {@link ComparatorChain} is locked.
*
* @throws UnsupportedOperationException if the {@link ComparatorChain} is locked
*/
private void checkLocked() {
if (isLocked == true) {
throw new UnsupportedOperationException(
"Comparator ordering cannot be changed after the first comparison is performed");
}
}
/**
* Throws an exception if the {@link ComparatorChain} is empty.
*
* @throws UnsupportedOperationException if the {@link ComparatorChain} is empty
*/
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
*/
@Override
public int compare(final E o1, final E o2) throws UnsupportedOperationException {
if (isLocked == false) {
checkChainIntegrity();
isLocked = true;
}
// iterate over all comparators in the chain
final Iterator<Comparator<E>> comparators = comparatorChain.iterator();
for (int comparatorIndex = 0; comparators.hasNext(); ++comparatorIndex) {
final Comparator<? super E> 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 (retval > 0) {
retval = -1;
} 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 3.0
*/
@Override
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 3.0
*/
@Override
public boolean equals(final Object object) {
if (this == object) {
return true;
}
if (null == object) {
return false;
}
if (object.getClass().equals(this.getClass())) {
final ComparatorChain<?> chain = (ComparatorChain<?>) object;
return (null == orderingBits ? null == chain.orderingBits : orderingBits.equals(chain.orderingBits)) &&
(null == comparatorChain ? null == chain.comparatorChain :
comparatorChain.equals(chain.comparatorChain));
}
return false;
}
}

299
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/FixedOrderComparator.java

@ -0,0 +1,299 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.comparators;
import java.io.Serializable;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 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.
* <p>
* This class is Serializable from Commons Collections 4.0.
*
* @since 3.0
* @version $Id: FixedOrderComparator.java 1686855 2015-06-22 13:00:27Z tn $
*/
public class FixedOrderComparator<T> implements Comparator<T>, Serializable {
/** Serialization version from Collections 4.0. */
private static final long serialVersionUID = 82794675842863201L;
/**
* Unknown object behavior enum.
* @since 4.0
*/
public static enum UnknownObjectBehavior {
BEFORE, AFTER, EXCEPTION;
}
/** 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 UnknownObjectBehavior unknownObjectBehavior = UnknownObjectBehavior.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 NullPointerException if the array is null
*/
public FixedOrderComparator(final T... items) {
super();
if (items == null) {
throw new NullPointerException("The list of items must not be null");
}
for (final T item : items) {
add(item);
}
}
/**
* 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 NullPointerException if the list is null
*/
public FixedOrderComparator(final List<T> items) {
super();
if (items == null) {
throw new NullPointerException("The list of items must not be null");
}
for (final T t : items) {
add(t);
}
}
// 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 {@link UnknownObjectBehavior}
*/
public UnknownObjectBehavior 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 NullPointerException if unknownObjectBehavior is null
*/
public void setUnknownObjectBehavior(final UnknownObjectBehavior unknownObjectBehavior) {
checkLocked();
if (unknownObjectBehavior == null) {
throw new NullPointerException("Unknown object behavior must not be null");
}
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(final T obj) {
checkLocked();
final Integer position = map.put(obj, Integer.valueOf(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(final T existingObj, final T newObj) {
checkLocked();
final Integer position = map.get(existingObj);
if (position == null) {
throw new IllegalArgumentException(existingObj + " not known to " + this);
}
final 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(UnknownObjectBehavior)}.
*/
@Override
public int compare(final T obj1, final T obj2) {
isLocked = true;
final Integer position1 = map.get(obj1);
final Integer position2 = map.get(obj2);
if (position1 == null || position2 == null) {
switch (unknownObjectBehavior) {
case BEFORE:
return position1 == null ? position2 == null ? 0 : -1 : 1;
case AFTER:
return position1 == null ? position2 == null ? 0 : 1 : -1;
case EXCEPTION:
final Object unknownObj = position1 == null ? obj1 : obj2;
throw new IllegalArgumentException("Attempting to compare unknown object "
+ unknownObj);
default: //could be null
throw new UnsupportedOperationException("Unknown unknownObjectBehavior: "
+ unknownObjectBehavior);
}
}
return position1.compareTo(position2);
}
//-----------------------------------------------------------------------
/**
* Implement a hash code for this comparator that is consistent with
* {@link #equals(Object) equals}.
*
* @return a hash code for this comparator.
*/
@Override
public int hashCode() {
int total = 17;
total = total*37 + (map == null ? 0 : map.hashCode());
total = total*37 + (unknownObjectBehavior == null ? 0 : unknownObjectBehavior.hashCode());
total = total*37 + counter;
total = total*37 + (isLocked ? 0 : 1);
return total;
}
/**
* 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 FixedOrderComparator}
* whose attributes are equal to mine.
*
* @param object the object to compare to
* @return true if equal
*/
@Override
public boolean equals(final Object object) {
if (this == object) {
return true;
}
if (null == object) {
return false;
}
if (object.getClass().equals(this.getClass())) {
final FixedOrderComparator<?> comp = (FixedOrderComparator<?>) object;
return (null == map ? null == comp.map : map.equals(comp.map)) &&
(null == unknownObjectBehavior ? null == comp.unknownObjectBehavior :
unknownObjectBehavior == comp.unknownObjectBehavior &&
counter == comp.counter &&
isLocked == comp.isLocked &&
unknownObjectBehavior == comp.unknownObjectBehavior);
}
return false;
}
}

182
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/NullComparator.java

@ -0,0 +1,182 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.comparators;
import java.io.Serializable;
import java.util.Comparator;
import com.fr.third.org.apache.commons.collections4.ComparatorUtils;
import com.fr.third.org.apache.commons.collections4.ComparatorUtils;
/**
* A Comparator that will compare nulls to be either lower or higher than
* other objects.
*
* @since 2.0
* @version $Id: NullComparator.java 1683951 2015-06-06 20:19:03Z tn $
*/
public class NullComparator<E> implements Comparator<E>, Serializable {
/** Serialization version. */
private static final long serialVersionUID = -5820772575483504339L;
/**
* The comparator to use when comparing two non-<code>null</code> objects.
**/
private final Comparator<? super E> nonNullComparator;
/**
* Specifies whether a <code>null</code> are compared as higher than
* non-<code>null</code> objects.
**/
private final 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 {@link ComparableComparator} is
* used.
**/
@SuppressWarnings("unchecked")
public NullComparator() {
this(ComparatorUtils.NATURAL_COMPARATOR, true);
}
/**
* 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>
*
* @exception NullPointerException if <code>nonNullComparator</code> is
* <code>null</code>
**/
public NullComparator(final Comparator<? super E> 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 {@link ComparableComparator} is
* used.
*
* @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.
**/
@SuppressWarnings("unchecked")
public NullComparator(final boolean nullsAreHigh) {
this(ComparatorUtils.NATURAL_COMPARATOR, nullsAreHigh);
}
/**
* 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.
*
* @exception NullPointerException if <code>nonNullComparator</code> is
* <code>null</code>
**/
public NullComparator(final Comparator<? super E> nonNullComparator, final 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.
**/
@Override
public int compare(final E o1, final E 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.
**/
@Override
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.
**/
@Override
public boolean equals(final Object obj) {
if(obj == null) { return false; }
if(obj == this) { return true; }
if(!obj.getClass().equals(this.getClass())) { return false; }
final NullComparator<?> other = (NullComparator<?>) obj;
return this.nullsAreHigh == other.nullsAreHigh &&
this.nonNullComparator.equals(other.nonNullComparator);
}
}

125
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/ReverseComparator.java

@ -0,0 +1,125 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.comparators;
import java.io.Serializable;
import java.util.Comparator;
import com.fr.third.org.apache.commons.collections4.ComparatorUtils;
import com.fr.third.org.apache.commons.collections4.ComparatorUtils;
/**
* Reverses the order of another comparator by reversing the arguments
* to its {@link #compare(Object, Object) compare} method.
*
* @since 2.0
* @version $Id: ReverseComparator.java 1683951 2015-06-06 20:19:03Z tn $
*
* @see java.util.Collections#reverseOrder()
*/
public class ReverseComparator<E> implements Comparator<E>, Serializable {
/** Serialization version from Collections 2.0. */
private static final long serialVersionUID = 2858887242028539265L;
/** The comparator being decorated. */
private final Comparator<? super E> comparator;
//-----------------------------------------------------------------------
/**
* Creates a comparator that compares objects based on the inverse of their
* natural ordering. Using this Constructor will create a ReverseComparator
* that is functionally identical to the Comparator returned by
* java.util.Collections.<b>reverseOrder()</b>.
*
* @see java.util.Collections#reverseOrder()
*/
public ReverseComparator() {
this(null);
}
/**
* Creates a comparator that inverts the comparison
* of the given comparator. If you pass in <code>null</code>,
* the ReverseComparator defaults to reversing the
* natural order, as per {@link java.util.Collections#reverseOrder()}.
*
* @param comparator Comparator to reverse
*/
@SuppressWarnings("unchecked")
public ReverseComparator(final Comparator<? super E> comparator) {
this.comparator = comparator == null ? ComparatorUtils.NATURAL_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
*/
@Override
public int compare(final E obj1, final E 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 3.0
*/
@Override
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 3.0
*/
@Override
public boolean equals(final Object object) {
if (this == object) {
return true;
}
if (null == object) {
return false;
}
if (object.getClass().equals(this.getClass())) {
final ReverseComparator<?> thatrc = (ReverseComparator<?>) object;
return comparator.equals(thatrc.comparator);
}
return false;
}
}

133
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/TransformingComparator.java

@ -0,0 +1,133 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.comparators;
import java.io.Serializable;
import java.util.Comparator;
import com.fr.third.org.apache.commons.collections4.ComparatorUtils;
import com.fr.third.org.apache.commons.collections4.Transformer;
import com.fr.third.org.apache.commons.collections4.ComparatorUtils;
import com.fr.third.org.apache.commons.collections4.Transformer;
/**
* 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.
* <p>
* This class is Serializable from Commons Collections 4.0.
*
* @since 2.1
* @version $Id: TransformingComparator.java 1683951 2015-06-06 20:19:03Z tn $
*
* @see Transformer
* @see org.apache.commons.collections4.comparators.ComparableComparator
*/
public class TransformingComparator<I, O> implements Comparator<I>, Serializable {
/** Serialization version from Collections 4.0. */
private static final long serialVersionUID = 3456940356043606220L;
/** The decorated comparator. */
private final Comparator<O> decorated;
/** The transformer being used. */
private final Transformer<? super I, ? extends O> transformer;
//-----------------------------------------------------------------------
/**
* Constructs an instance with the given Transformer and a
* {@link ComparableComparator ComparableComparator}.
*
* @param transformer what will transform the arguments to <code>compare</code>
*/
@SuppressWarnings("unchecked")
public TransformingComparator(final Transformer<? super I, ? extends O> transformer) {
this(transformer, ComparatorUtils.NATURAL_COMPARATOR);
}
/**
* 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(final Transformer<? super I, ? extends O> transformer,
final 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
*/
@Override
public int compare(final I obj1, final I obj2) {
final O value1 = this.transformer.transform(obj1);
final O value2 = this.transformer.transform(obj2);
return this.decorated.compare(value1, value2);
}
//-----------------------------------------------------------------------
/**
* Implement a hash code for this comparator that is consistent with
* {@link #equals(Object) equals}.
*
* @return a hash code for this comparator.
*/
@Override
public int hashCode() {
int total = 17;
total = total*37 + (decorated == null ? 0 : decorated.hashCode());
total = total*37 + (transformer == null ? 0 : transformer.hashCode());
return total;
}
/**
* 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 TransformingComparator}
* whose attributes are equal to mine.
*
* @param object the object to compare to
* @return true if equal
*/
@Override
public boolean equals(final Object object) {
if (this == object) {
return true;
}
if (null == object) {
return false;
}
if (object.getClass().equals(this.getClass())) {
final TransformingComparator<?, ?> comp = (TransformingComparator<?, ?>) object;
return (null == decorated ? null == comp.decorated : decorated.equals(comp.decorated)) &&
(null == transformer ? null == comp.transformer : transformer.equals(comp.transformer));
}
return false;
}
}

28
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/comparators/package-info.java

@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This package contains implementations of the
* {@link java.util.Comparator Comparator} interface.
* <p>
* You may also consider using
* {@link com.fr.third.org.apache.commons.collections4.ComparatorUtils ComparatorUtils},
* which is a single class that uses static methods to construct instances
* of the classes in this package.
*
* @version $Id: package-info.java 1477747 2013-04-30 18:16:48Z tn $
*/
package com.fr.third.org.apache.commons.collections4.comparators;

56
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/functors/AbstractQuantifierPredicate.java

@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.functors;
import java.io.Serializable;
import com.fr.third.org.apache.commons.collections4.Predicate;
/**
* Abstract base class for quantification predicates, e.g. All, Any, None.
*
* @since 4.0
* @version $Id: AbstractQuantifierPredicate.java 1543167 2013-11-18 21:21:32Z ggregory $
*/
public abstract class AbstractQuantifierPredicate<T> implements PredicateDecorator<T>, Serializable {
/** Serial version UID */
private static final long serialVersionUID = -3094696765038308799L;
/** The array of predicates to call */
protected final Predicate<? super T>[] iPredicates;
/**
* Constructor that performs no validation.
*
* @param predicates the predicates to check, not cloned, not null
*/
public AbstractQuantifierPredicate(final Predicate<? super T>... predicates) {
iPredicates = predicates;
}
/**
* Gets the predicates.
*
* @return a copy of the predicates
* @since 3.1
*/
public Predicate<? super T>[] getPredicates() {
return FunctorUtils.<T>copy(iPredicates);
}
}

115
fine-commons-collections4/src/com/fr/third/org/apache/commons/collections4/functors/AllPredicate.java

@ -0,0 +1,115 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.fr.third.org.apache.commons.collections4.functors;
import static com.fr.third.org.apache.commons.collections4.functors.FunctorUtils.coerce;
import static com.fr.third.org.apache.commons.collections4.functors.FunctorUtils.validate;
import static com.fr.third.org.apache.commons.collections4.functors.TruePredicate.truePredicate;
import java.util.Collection;
import com.fr.third.org.apache.commons.collections4.Predicate;
/**
* Predicate implementation that returns true if all the
* predicates return true.
* If the array of predicates is empty, then this predicate returns true.
* <p>
* NOTE: In versions prior to 3.2 an array size of zero or one
* threw an exception.
*
* @since 3.0
* @version $Id: AllPredicate.java 1686855 2015-06-22 13:00:27Z tn $
*/
public final class AllPredicate<T> extends AbstractQuantifierPredicate<T> {
/** Serial version UID */
private static final long serialVersionUID = -3094696765038308799L;
/**
* Factory to create the predicate.
* <p>
* If the array is size zero, the predicate always returns true.
* If the array is size one, then that predicate is returned.
*
* @param <T> the type that the predicate queries
* @param predicates the predicates to check, cloned, not null
* @return the <code>all</code> predicate
* @throws NullPointerException if the predicates array is null
* @throws NullPointerException if any predicate in the array is null
*/
public static <T> Predicate<T> allPredicate(final Predicate<? super T>... predicates) {
FunctorUtils.validate(predicates);
if (predicates.length == 0) {
return TruePredicate.truePredicate();
}
if (predicates.length == 1) {
return coerce(predicates[0]);
}
return new AllPredicate<T>(FunctorUtils.copy(predicates));
}
/**
* Factory to create the predicate.
* <p>
* If the collection is size zero, the predicate always returns true.
* If the collection is size one, then that predicate is returned.
*
* @param <T> the type that the predicate queries
* @param predicates the predicates to check, cloned, not null
* @return the <code>all</code> predicate
* @throws NullPointerException if the predicates array is null
* @throws NullPointerException if any predicate in the array is null
*/
public static <T> Predicate<T> allPredicate(final Collection<? extends Predicate<? super T>> predicates) {
final Predicate<? super T>[] preds = validate(predicates);
if (preds.length == 0) {
return TruePredicate.truePredicate();
}
if (preds.length == 1) {
return coerce(preds[0]);
}
return new AllPredicate<T>(preds);
}
/**
* Constructor that performs no validation.
* Use <code>allPredicate</code> if you want that.
*
* @param predicates the predicates to check, not cloned, not null
*/
public AllPredicate(final Predicate<? super T>... predicates) {
super(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(final T object) {
for (final Predicate<? super T> iPredicate : iPredicates) {
if (!iPredicate.evaluate(object)) {
return false;
}
}
return true;
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save