/* * Copyright (C) 2007 The Guava Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.eclipse.che.ide.util; import java.io.Serializable; import java.util.Comparator; /** * An immutable, semantic-free ordered pair of nullable values. These can be * accessed using the {@link #getFirst} and {@link #getSecond} methods. Equality * and hashing are defined in the natural way. * <p/> * <p>This type is devoid of semantics, best used for simple mechanical * aggregations of unrelated values in implementation code. Avoid using it in * your APIs, preferring an explicit type that conveys the exact semantics of * the data. For example, instead of: <pre> {@code * <p/> * Pair<T, T> findMinAndMax(List<T> list) {...}}</pre> * <p/> * ... use: <pre> {@code * <p/> * Range<T> findRange(List<T> list) {...}}</pre> * <p/> * This usually involves creating a new custom value-object type. This is * difficult to do "by hand" in Java, but avoid the temptation to extend {@code * Pair} to accomplish this; consider using the utilities {@link * com.google.common.labs.misc.ComparisonKeys} or {@link * com.google.common.labs.misc.ValueType} to help you with this instead. */ public class Pair<A, B> implements Serializable { /** Creates a new pair containing the given elements in order. */ public static <A, B> Pair<A, B> of(A first, B second) { return new Pair<A, B>(first, second); } /** The first element of the pair; see also {@link #getFirst}. */ public final A first; /** The second element of the pair; see also {@link #getSecond}. */ public final B second; /** Constructor. It is usually easier to call {@link #of}. */ public Pair(A first, B second) { this.first = first; this.second = second; } /** Returns the first element of this pair; see also {@link #first}. */ public A getFirst() { return first; } /** Returns the second element of this pair; see also {@link #second}. */ public B getSecond() { return second; } /** Returns a function that yields {@link #first}. */ @SuppressWarnings("unchecked") public static <A, B> Function<Pair<A, B>, A> firstFunction() { // The safety of the unchecked conversion here is implied by the // implementation of the PairFirstFunction which always returns the first // element from a pair (which for Pair<A, B> is of type A). return (Function)PairFirstFunction.INSTANCE; } /** Returns a function that yields {@link #second}. */ @SuppressWarnings("unchecked") public static <A, B> Function<Pair<A, B>, B> secondFunction() { // The safety of the unchecked conversion here is implied by the // implementation of the PairSecondFunction which always returns the second // element from a pair (which for Pair<A, B> is of type B). return (Function)PairSecondFunction.INSTANCE; } /* * If we use the enum singleton pattern for these functions, Flume's type * inference chokes: http://b/4863010 */ private static final class PairFirstFunction<A, B> implements Function<Pair<A, B>, A>, Serializable { static final PairFirstFunction<Object, Object> INSTANCE = new PairFirstFunction<Object, Object>(); @Override public A apply(Pair<A, B> from) { return from.getFirst(); } private Object readResolve() { return INSTANCE; } } private static final class PairSecondFunction<A, B> implements Function<Pair<A, B>, B>, Serializable { static final PairSecondFunction<Object, Object> INSTANCE = new PairSecondFunction<Object, Object>(); @Override public B apply(Pair<A, B> from) { return from.getSecond(); } private Object readResolve() { return INSTANCE; } } /** * Returns a comparator that compares two Pair objects by comparing the * result of {@link #getFirst()} for each. */ @SuppressWarnings("unchecked") public static <A extends Comparable, B> Comparator<Pair<A, B>> compareByFirst() { return (Comparator)FirstComparator.FIRST_COMPARATOR; } /** * Returns a comparator that compares two Pair objects by comparing the * result of {@link #getSecond()} for each. */ @SuppressWarnings("unchecked") public static <A, B extends Comparable> Comparator<Pair<A, B>> compareBySecond() { return (Comparator)SecondComparator.SECOND_COMPARATOR; } // uses raw Comparable to support classes defined without generics @SuppressWarnings("unchecked") private enum FirstComparator implements Comparator<Pair<Comparable, Object>> { FIRST_COMPARATOR; @Override public int compare(Pair<Comparable, Object> pair1, Pair<Comparable, Object> pair2) { return pair1.getFirst().compareTo(pair2.getFirst()); } } // uses raw Comparable to support classes defined without generics @SuppressWarnings("unchecked") private enum SecondComparator implements Comparator<Pair<Object, Comparable>> { SECOND_COMPARATOR; @Override public int compare(Pair<Object, Comparable> pair1, Pair<Object, Comparable> pair2) { return pair1.getSecond().compareTo(pair2.getSecond()); } } // TODO: decide what level of commitment to make to this impl @Override public boolean equals(Object object) { // TODO: it is possible we want to change this to // if (object != null && object.getClass() == getClass()) { if (object instanceof Pair) { Pair<?, ?> that = (Pair<?, ?>)object; return equal(this.first, that.first) && equal(this.second, that.second); } return false; } @Override public int hashCode() { int hash1 = first == null ? 0 : first.hashCode(); int hash2 = second == null ? 0 : second.hashCode(); return 31 * hash1 + hash2; } /** * {@inheritDoc} * <p/> * <p>This implementation returns a string in the form * {@code (first, second)}, where {@code first} and {@code second} are the * String representations of the first and second elements of this pair, as * given by {@link String#valueOf(Object)}. Subclasses are free to override * this behavior. */ @Override public String toString() { // GWT doesn't support String.format(). return "(" + first + ", " + second + ")"; } /** * Determines whether two possibly-null objects are equal. Returns: * <p/> * <ul> * <li>{@code true} if {@code a} and {@code b} are both null. * <li>{@code true} if {@code a} and {@code b} are both non-null and they are * equal according to {@link Object#equals(Object)}. * <li>{@code false} in all other situations. * </ul> * <p/> * <p>This assumes that any non-null objects passed to this function conform * to the {@code equals()} contract. */ private boolean equal(Object a, Object b) { return a == b || (a != null && a.equals(b)); } private static final long serialVersionUID = 747826592375603043L; }