package org.jcommons.type;
import java.io.*;
import java.util.*;
/**
* A generic-typed pair of objects.
*
* from berkeley
*/
public class Pair<F, S> implements Serializable, Comparable<Pair<F, S>> {
static final long serialVersionUID = 42;
F first;
S second;
public F getFirst() {
return first;
}
public S getSecond() {
return second;
}
public void setFirst(F pFirst) {
first = pFirst;
}
public void setSecond(S pSecond) {
second = pSecond;
}
public Pair<S, F> reverse() {
return new Pair<S, F>(second, first);
}
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof Pair))
return false;
final Pair pair = (Pair) o;
return !(first != null ? !first.equals(pair.first) : pair.first != null)
&& !(second != null ? !second.equals(pair.second)
: pair.second != null);
}
public int hashCode() {
int result;
result = (first != null ? first.hashCode() : 0);
result = 29 * result + (second != null ? second.hashCode() : 0);
return result;
}
public String toString() {
return "(" + getFirst() + ", " + getSecond() + ")";
}
public Pair(F first, S second) {
this.first = first;
this.second = second;
}
/**
* Compares this object with the specified object for order. Returns a
* negative integer, zero, or a positive integer as this object is less
* than, equal to, or greater than the specified object.
* <p/>
* <p>
* The implementor must ensure <tt>sgn(x.compareTo(y)) ==
* -sgn(y.compareTo(x))</tt> for all <tt>x</tt> and <tt>y</tt>. (This
* implies that <tt>x.compareTo(y)</tt> must throw an exception iff
* <tt>y.compareTo(x)</tt> throws an exception.)
* <p/>
* <p>
* The implementor must also ensure that the relation is transitive:
* <tt>(x.compareTo(y)>0 && y.compareTo(z)>0)</tt> implies
* <tt>x.compareTo(z)>0</tt>.
* <p/>
* <p>
* Finally, the implementor must ensure that <tt>x.compareTo(y)==0</tt>
* implies that <tt>sgn(x.compareTo(z)) == sgn(y.compareTo(z))</tt>, for all
* <tt>z</tt>.
* <p/>
* <p>
* It is strongly recommended, but <i>not</i> strictly required that
* <tt>(x.compareTo(y)==0) == (x.equals(y))</tt>. Generally speaking, any
* class that implements the <tt>Comparable</tt> interface and violates this
* condition should clearly indicate this fact. The recommended language is
* "Note: this class has a natural ordering that is inconsistent with
* equals."
* <p/>
* <p>
* In the foregoing description, the notation <tt>sgn(</tt><i>expression</i>
* <tt>)</tt> designates the mathematical <i>signum</i> function, which is
* defined to return one of <tt>-1</tt>, <tt>0</tt>, or <tt>1</tt> according
* to whether the value of <i>expression</i> is negative, zero or positive.
*
* @param o
* the object to be compared.
* @return a negative integer, zero, or a positive integer as this object is
* less than, equal to, or greater than the specified object.
* @throws NullPointerException
* if the specified object is null
* @throws ClassCastException
* if the specified object's type prevents it from being
* compared to this object.
*/
@Override
public int compareTo(Pair<F, S> o) {
return new DefaultLexicographicPairComparator().compare(this, o);
}
// Compares only first values
public static class FirstComparator<S extends Comparable<? super S>, T>
implements Comparator<Pair<S, T>> {
public int compare(Pair<S, T> p1, Pair<S, T> p2) {
return p1.getFirst().compareTo(p2.getFirst());
}
}
public static class ReverseFirstComparator<S extends Comparable<? super S>, T>
implements Comparator<Pair<S, T>> {
public int compare(Pair<S, T> p1, Pair<S, T> p2) {
return p2.getFirst().compareTo(p1.getFirst());
}
}
// Compares only second values
public static class SecondComparator<S, T extends Comparable<? super T>>
implements Comparator<Pair<S, T>> {
public int compare(Pair<S, T> p1, Pair<S, T> p2) {
return p1.getSecond().compareTo(p2.getSecond());
}
}
public static class ReverseSecondComparator<S, T extends Comparable<? super T>>
implements Comparator<Pair<S, T>> {
public int compare(Pair<S, T> p1, Pair<S, T> p2) {
return p2.getSecond().compareTo(p1.getSecond());
}
}
public static <S, T> Pair<S, T> newPair(S first, T second) {
return new Pair<S, T>(first, second);
}
// Duplicate method to faccilitate backwards compatibility
// - aria42
public static <S, T> Pair<S, T> makePair(S first, T second) {
return new Pair<S, T>(first, second);
}
public static class LexicographicPairComparator<F, S> implements
Comparator<Pair<F, S>> {
Comparator<F> firstComparator;
Comparator<S> secondComparator;
public int compare(Pair<F, S> pair1, Pair<F, S> pair2) {
int firstCompare = firstComparator.compare(pair1.getFirst(),
pair2.getFirst());
if (firstCompare != 0)
return firstCompare;
return secondComparator.compare(pair1.getSecond(),
pair2.getSecond());
}
public LexicographicPairComparator(Comparator<F> firstComparator,
Comparator<S> secondComparator) {
this.firstComparator = firstComparator;
this.secondComparator = secondComparator;
}
}
public static class DefaultLexicographicPairComparator<F extends Comparable<F>, S extends Comparable<S>>
implements Comparator<Pair<F, S>> {
public int compare(Pair<F, S> o1, Pair<F, S> o2) {
int firstCompare = o1.getFirst().compareTo(o2.getFirst());
if (firstCompare != 0) {
return firstCompare;
}
return o1.getSecond().compareTo(o2.getSecond());
}
}
}