/*
* Copyright (C) 2012 Jason Gedge <http://www.gedge.ca>
*
* This file is part of the OpGraph project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ca.gedge.opgraph.util;
/**
* A 2-tuple.
*
* @param <F> type of the first element
* @param <S> type of the second element
*/
public class Pair<F, S> implements Comparable<Pair<? extends F, ? extends S>> {
/** The first element */
private F first;
/** The second element */
private S second;
/**
* Constructs a pair with <code>null</code> elements.
*/
public Pair() {
this(null, null);
}
/**
* Constructs a pair with a specified first/second object.
*
* @param first the first element
* @param second the second element
*/
public Pair(F first, S second) {
this.first = first;
this.second = second;
}
/**
* Gets the first element.
*
* @return the first element in this pair
*/
public F getFirst() {
return first;
}
/**
* Sets the first element.
*
* @param first the first element
*/
public void setFirst(F first) {
this.first = first;
}
/**
* Gets the second element.
*
* @return the second element in this pair
*/
public S getSecond() {
return second;
}
/**
* Sets the second element.
*
* @param second the second element
*/
public void setSecond(S second) {
this.second = second;
}
/**
* Gets whether or not two objects are both <code>null</code>, or if they
* are equal, as defined by their implementation of {@link Object#equals(Object)}.
*
* @param a an object
* @param b an object
*
* @return <code>true</code> if objects both <code>null</code> or equal,
* <code>false</code> otherwise
*/
public static boolean objectsEqual(Object a, Object b) {
return (a == null && b == null) || (a != null && a.equals(b));
}
//
// Overrides
//
@Override
public boolean equals(Object o) {
if(o == this) return true;
if(o == null) return false;
if(o instanceof Pair) {
final Pair<?, ?> b = (Pair<?, ?>)o;
return objectsEqual(first, b.first) && objectsEqual(second, b.second);
}
return false;
}
@Override
public int hashCode() {
final int hash1 = (first == null ? 0 : first.hashCode());
final int hash2 = (second == null ? 0 : second.hashCode());
return 19*hash1 + 31*hash2;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append('(');
builder.append(String.valueOf(first));
builder.append(", ");
builder.append(String.valueOf(second));
builder.append(')');
return builder.toString();
}
//
// Comparable
//
@SuppressWarnings("unchecked")
private <T> int compare(T a, T b) {
if(a == null && b == null) return 0;
if(a == null) return 1;
if(b == null) return -1;
if(a instanceof Comparable)
return ((Comparable<T>)a).compareTo(b);
return (a.equals(b) ? 0 : 1);
}
@Override
public int compareTo(Pair<? extends F, ? extends S> o) {
final int firstComp = compare(first, o.first);
if(firstComp == 0)
return compare(second, o.second);
return firstComp;
}
}