001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2015-2016 ForgeRock AS. 015 */ 016package org.forgerock.util; 017 018import java.util.Comparator; 019 020/** 021 * Ordered pair of arbitrary objects. Use of Pair is strictly restricted to internal (non-public) APIs:<br> 022 * - Pair cannot be used in public APIs 023 * - Consider using dedicated classes over Pair. Dedicated classes are more readable while Pair is meaningless.<br> 024 * - Pair should only be used to return two values from a method, just like a tuple. If you need more than two 025 * values, create a dedicated class. 026 * 027 * @param <F> 028 * type of the first pair element 029 * @param <S> 030 * type of the second pair element 031 */ 032public final class Pair<F, S> { 033 034 private static final class ComparablePairComparator 035 <F extends Comparable<F>, S extends Comparable<S>> 036 implements Comparator<Pair<F, S>> { 037 /** {@inheritDoc} */ 038 @Override 039 public int compare(Pair<F, S> o1, Pair<F, S> o2) { 040 final int compareResult = o1.getFirst().compareTo(o2.getFirst()); 041 if (compareResult == 0) { 042 return o1.getSecond().compareTo(o2.getSecond()); 043 } 044 return compareResult; 045 } 046 } 047 048 /** An empty Pair. */ 049 public static final Pair<?, ?> EMPTY = Pair.of(null, null); 050 051 /** 052 * {@link Comparator} for {@link Pair}s made of {@link Comparable} elements. 053 */ 054 @SuppressWarnings("rawtypes") 055 public static final Comparator COMPARATOR = new ComparablePairComparator(); 056 057 /** The first pair element. */ 058 private final F first; 059 060 /** The second pair element. */ 061 private final S second; 062 063 /** 064 * Creates a pair. 065 * 066 * @param first 067 * the first element of the constructed pair 068 * @param second 069 * the second element of the constructed pair 070 */ 071 private Pair(F first, S second) { 072 this.first = first; 073 this.second = second; 074 } 075 076 /** 077 * Creates a new {@code Pair}. 078 * 079 * @param first 080 * the first element of the constructed pair 081 * @param second 082 * the second element of the constructed pair 083 * @param <F> 084 * type of the first pair element 085 * @param <S> 086 * type of the second pair element 087 * @return A new Pair built with the provided elements 088 */ 089 public static <F, S> Pair<F, S> of(F first, S second) { 090 return new Pair<>(first, second); 091 } 092 093 /** 094 * Returns an empty Pair matching the required types. 095 * 096 * @param <F> 097 * type of the first pair element 098 * @param <S> 099 * 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}