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