1 /* 2 * The contents of this file are subject to the terms of the Common Development and 3 * Distribution License (the License). You may not use this file except in compliance with the 4 * License. 5 * 6 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 7 * specific language governing permission and limitations under the License. 8 * 9 * When distributing Covered Software, include this CDDL Header Notice in each file and include 10 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 11 * Header, with the fields enclosed by brackets [] replaced by your own identifying 12 * information: "Portions copyright [year] [name of copyright owner]". 13 * 14 * Copyright 2015-2016 ForgeRock AS. 15 */ 16 package org.forgerock.util; 17 18 import java.util.Comparator; 19 20 /** 21 * Ordered pair of arbitrary objects. Use of Pair is strictly restricted to internal (non-public) APIs:<br> 22 * - Pair cannot be used in public APIs 23 * - Consider using dedicated classes over Pair. Dedicated classes are more readable while Pair is meaningless.<br> 24 * - Pair should only be used to return two values from a method, just like a tuple. If you need more than two 25 * values, create a dedicated class. 26 * 27 * @param <F> 28 * type of the first pair element 29 * @param <S> 30 * type of the second pair element 31 */ 32 public final class Pair<F, S> { 33 34 private static final class ComparablePairComparator 35 <F extends Comparable<F>, S extends Comparable<S>> 36 implements Comparator<Pair<F, S>> { 37 /** {@inheritDoc} */ 38 @Override 39 public int compare(Pair<F, S> o1, Pair<F, S> o2) { 40 final int compareResult = o1.getFirst().compareTo(o2.getFirst()); 41 if (compareResult == 0) { 42 return o1.getSecond().compareTo(o2.getSecond()); 43 } 44 return compareResult; 45 } 46 } 47 48 /** An empty Pair. */ 49 public static final Pair<?, ?> EMPTY = Pair.of(null, null); 50 51 /** 52 * {@link Comparator} for {@link Pair}s made of {@link Comparable} elements. 53 */ 54 @SuppressWarnings("rawtypes") 55 public static final Comparator COMPARATOR = new ComparablePairComparator(); 56 57 /** The first pair element. */ 58 private final F first; 59 60 /** The second pair element. */ 61 private final S second; 62 63 /** 64 * Creates a pair. 65 * 66 * @param first 67 * the first element of the constructed pair 68 * @param second 69 * the second element of the constructed pair 70 */ 71 private Pair(F first, S second) { 72 this.first = first; 73 this.second = second; 74 } 75 76 /** 77 * Creates a new {@code Pair}. 78 * 79 * @param first 80 * the first element of the constructed pair 81 * @param second 82 * the second element of the constructed pair 83 * @param <F> 84 * type of the first pair element 85 * @param <S> 86 * type of the second pair element 87 * @return A new Pair built with the provided elements 88 */ 89 public static <F, S> Pair<F, S> of(F first, S second) { 90 return new Pair<>(first, second); 91 } 92 93 /** 94 * Returns an empty Pair matching the required types. 95 * 96 * @param <F> 97 * type of the first pair element 98 * @param <S> 99 * type of the second pair element 100 * @return An empty Pair matching the required types 101 */ 102 @SuppressWarnings("unchecked") 103 public static <F, S> Pair<F, S> empty() { 104 return (Pair<F, S>) EMPTY; 105 } 106 107 /** 108 * Returns a comparator for Pairs of comparable objects. 109 * 110 * @param <F> 111 * type of the first pair element 112 * @param <S> 113 * type of the second pair element 114 * @return a comparator for Pairs of comparable objects. 115 */ 116 @SuppressWarnings("unchecked") 117 public static <F extends Comparable<F>, S extends Comparable<S>> Comparator<Pair<F, S>> getPairComparator() { 118 return COMPARATOR; 119 } 120 121 /** 122 * Returns the first element of this pair. 123 * 124 * @return the first element of this pair 125 */ 126 public F getFirst() { 127 return first; 128 } 129 130 /** 131 * Returns the second element of this pair. 132 * 133 * @return the second element of this pair 134 */ 135 public S getSecond() { 136 return second; 137 } 138 139 /** {@inheritDoc} */ 140 @Override 141 public int hashCode() { 142 final int prime = 31; 143 int result = 1; 144 result = prime * result + ((first == null) ? 0 : first.hashCode()); 145 result = prime * result + ((second == null) ? 0 : second.hashCode()); 146 return result; 147 } 148 149 /** {@inheritDoc} */ 150 @Override 151 public boolean equals(Object obj) { 152 if (this == obj) { 153 return true; 154 } 155 156 if (!(obj instanceof Pair)) { 157 return false; 158 } 159 160 Pair<?, ?> other = (Pair<?, ?>) obj; 161 if (first == null) { 162 if (other.first != null) { 163 return false; 164 } 165 } else if (!first.equals(other.first)) { 166 return false; 167 } 168 169 if (second == null) { 170 if (other.second != null) { 171 return false; 172 } 173 } else { 174 return second.equals(other.second); 175 } 176 177 return true; 178 } 179 180 /** {@inheritDoc} */ 181 @Override 182 public String toString() { 183 return "Pair [" + first + ", " + second + "]"; 184 } 185 }