001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2011-2012 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.util; 011 012import mondrian.olap.Util; 013 014import java.util.Iterator; 015 016/** 017 * Tuple of three values. 018 * 019 * <p>Because a triple implements {@link #equals(Object)}, {@link #hashCode()} 020 * and {@link #compareTo(mondrian.util.Triple)}, it can be used in any kind of 021 * {@link java.util.Collection}. 022 * 023 * @author jhyde 024 */ 025public class Triple<T0, T1, T2> 026 implements Comparable<Triple<T0, T1, T2>> 027{ 028 public T0 v0; 029 public T1 v1; 030 public T2 v2; 031 032 /** 033 * Creates a Triple. 034 * 035 * @param v0 Value #0 036 * @param v1 Value #1 037 * @param v2 Value #2 038 */ 039 public Triple(T0 v0, T1 v1, T2 v2) { 040 this.v0 = v0; 041 this.v1 = v1; 042 this.v2 = v2; 043 } 044 045 /** 046 * Creates a Triple. 047 * 048 * @param v0 Value #0 049 * @param v1 Value #1 050 * @param v2 Value #2 051 * @return a new Triple 052 */ 053 public static <T0, T1, T2> Triple<T0, T1, T2> of(T0 v0, T1 v1, T2 v2) { 054 return new Triple<T0, T1, T2>(v0, v1, v2); 055 } 056 057 public boolean equals(Object obj) { 058 if (obj instanceof Triple) { 059 //noinspection unchecked 060 Triple<T0, T1, T2> pair = (Triple) obj; 061 return Util.equals(this.v0, pair.v0) 062 && Util.equals(this.v1, pair.v1) 063 && Util.equals(this.v2, pair.v2); 064 } 065 return false; 066 } 067 068 public int hashCode() { 069 int k0 = (v0 == null) ? 0 : v0.hashCode(); 070 int k1 = (v1 == null) ? 0 : v1.hashCode(); 071 int k2 = (v2 == null) ? 0 : v2.hashCode(); 072 return ((k0 << 8) | k0) ^ (k1 << 4 | k1) ^ k2; 073 } 074 075 076 public int compareTo(Triple<T0, T1, T2> that) { 077 int c = compare((Comparable) this.v0, (Comparable)that.v0); 078 if (c == 0) { 079 c = compare((Comparable) this.v1, (Comparable)that.v1); 080 } 081 if (c == 0) { 082 c = compare((Comparable) this.v2, (Comparable)that.v2); 083 } 084 return c; 085 } 086 087 public String toString() { 088 return "<" + v0 + ", " + v1 + ", " + v2 + ">"; 089 } 090 091 /** 092 * Compares a pair of comparable values of the same type. Null collates 093 * less than everything else, but equal to itself. 094 * 095 * @param c1 First value 096 * @param c2 Second value 097 * @return a negative integer, zero, or a positive integer if c1 098 * is less than, equal to, or greater than c2. 099 */ 100 private static <C extends Comparable<C>> int compare(C c1, C c2) { 101 if (c1 == null) { 102 if (c2 == null) { 103 return 0; 104 } else { 105 return -1; 106 } 107 } else if (c2 == null) { 108 return 1; 109 } else { 110 return c1.compareTo(c2); 111 } 112 } 113 114 /** 115 * Returns an iterable over the slice #0 of an iterable. 116 * 117 * @param iterable Iterable over triples 118 * @param <T0> Type #0 119 * @param <T1> Type #1 120 * @param <T2> Type #2 121 * @return Iterable over the 0'th elements of each triple 122 */ 123 public static <T0, T1, T2> Iterable<T0> iter0( 124 final Iterable<Triple<T0, T1, T2>> iterable) 125 { 126 return new Iterable<T0>() { 127 public Iterator<T0> iterator() { 128 final Iterator<Triple<T0, T1, T2>> iterator = 129 iterable.iterator(); 130 return new Iterator<T0>() { 131 public boolean hasNext() { 132 return iterator.hasNext(); 133 } 134 135 public T0 next() { 136 return iterator.next().v0; 137 } 138 139 public void remove() { 140 iterator.remove(); 141 } 142 }; 143 } 144 }; 145 } 146 147 /** 148 * Returns an iterable over the slice #1 of an iterable. 149 * 150 * @param iterable Iterable over triples 151 * @param <T0> Type #0 152 * @param <T1> Type #1 153 * @param <T2> Type #2 154 * @return Iterable over the 1'th elements of each triple 155 */ 156 public static <T0, T1, T2> Iterable<T1> iter1( 157 final Iterable<Triple<T0, T1, T2>> iterable) 158 { 159 return new Iterable<T1>() { 160 public Iterator<T1> iterator() { 161 final Iterator<Triple<T0, T1, T2>> iterator = 162 iterable.iterator(); 163 return new Iterator<T1>() { 164 public boolean hasNext() { 165 return iterator.hasNext(); 166 } 167 168 public T1 next() { 169 return iterator.next().v1; 170 } 171 172 public void remove() { 173 iterator.remove(); 174 } 175 }; 176 } 177 }; 178 } 179 /** 180 * Returns an iterable over the slice #2 of an iterable. 181 * 182 * @param iterable Iterable over triples 183 * @param <T0> Type #0 184 * @param <T1> Type #1 185 * @param <T2> Type #2 186 * @return Iterable over the 2'th elements of each triple 187 */ 188 public static <T0, T1, T2> Iterable<T2> iter2( 189 final Iterable<Triple<T0, T1, T2>> iterable) 190 { 191 return new Iterable<T2>() { 192 public Iterator<T2> iterator() { 193 final Iterator<Triple<T0, T1, T2>> iterator = 194 iterable.iterator(); 195 return new Iterator<T2>() { 196 public boolean hasNext() { 197 return iterator.hasNext(); 198 } 199 200 public T2 next() { 201 return iterator.next().v2; 202 } 203 204 public void remove() { 205 iterator.remove(); 206 } 207 }; 208 } 209 }; 210 } 211} 212 213// End Triple.java