package edu.stanford.nlp.util;
import java.io.Serializable;
import java.util.List;
import edu.stanford.nlp.util.logging.PrettyLoggable;
import edu.stanford.nlp.util.logging.PrettyLogger;
import edu.stanford.nlp.util.logging.Redwood.RedwoodChannels;
/**
* Class representing an ordered triple of objects, possibly typed.
* Useful when you'd like a method to return three objects, or would like to put
* triples of objects in a Collection or Map. equals() and hashcode() should
* work properly.
*
* @author Teg Grenager (grenager@stanford.edu)
*/
public class Triple<T1, T2, T3> implements Comparable<Triple<T1,T2,T3>>, Serializable, PrettyLoggable {
private static final long serialVersionUID = -4182871682751645440L;
public T1 first;
public T2 second;
public T3 third;
public Triple(T1 first, T2 second, T3 third) {
this.first = first;
this.second = second;
this.third = third;
}
public T1 first() {
return first;
}
public T2 second() {
return second;
}
public T3 third() {
return third;
}
public void setFirst(T1 o) {
first = o;
}
public void setSecond(T2 o) {
second = o;
}
public void setThird(T3 o) {
third = o;
}
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Triple)) {
return false;
}
final Triple triple = (Triple) o;
if (first != null ? !first.equals(triple.first) : triple.first != null) {
return false;
}
if (second != null ? !second.equals(triple.second) : triple.second != null) {
return false;
}
if (third != null ? !third.equals(triple.third) : triple.third != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result;
result = (first != null ? first.hashCode() : 0);
result = 29 * result + (second != null ? second.hashCode() : 0);
result = 29 * result + (third != null ? third.hashCode() : 0);
return result;
}
@Override
public String toString() {
return "(" + first + "," + second + "," + third + ")";
}
public List<Object> asList() {
return CollectionUtils.makeList(first, second, third);
}
/**
* Returns a Triple constructed from X, Y, and Z. Convenience method; the
* compiler will disambiguate the classes used for you so that you don't have
* to write out potentially long class names.
*/
public static <X, Y, Z> Triple<X, Y, Z> makeTriple(X x, Y y, Z z) {
return new Triple<>(x, y, z);
}
/**
* {@inheritDoc}
*/
public void prettyLog(RedwoodChannels channels, String description) {
PrettyLogger.log(channels, description, this.asList());
}
@SuppressWarnings("unchecked")
@Override
public int compareTo(Triple<T1, T2, T3> another) {
int comp = ((Comparable<T1>) first()).compareTo(another.first());
if (comp != 0) {
return comp;
} else {
comp = ((Comparable<T2>) second()).compareTo(another.second());
if (comp != 0) {
return comp;
} else {
return ((Comparable<T3>) third()).compareTo(another.third());
}
}
}
}