001 // Copyright 2010 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.func;
016
017 /**
018 * A Tuple holds two values of two different types.
019 *
020 * @param <A>
021 * @param <B>
022 * @since 5.3
023 */
024 public class Tuple<A, B>
025 {
026 public final A first;
027
028 public final B second;
029
030 public Tuple(A first, B second)
031 {
032 this.first = first;
033 this.second = second;
034 }
035
036 public static <X, Y> Tuple<X, Y> create(X first, Y second)
037 {
038 return new Tuple<X, Y>(first, second);
039 }
040
041 /**
042 * Returns the values of the tuple, separated by commas, enclosed in parenthesis. Example:
043 * <code>("Ace", "Spades")</code>.
044 */
045 @Override
046 public String toString()
047 {
048 StringBuilder builder = new StringBuilder("(");
049
050 builder.append(String.valueOf(first));
051 builder.append(", ");
052 builder.append(String.valueOf(second));
053
054 extendDescription(builder);
055
056 return builder.append(")").toString();
057 }
058
059 /**
060 * Overriden in subclasses to write additional values into the
061 * description.
062 *
063 * @param builder
064 */
065 protected void extendDescription(StringBuilder builder)
066 {
067 }
068
069 /** Utility for comparing two values, either of which may be null. */
070 static boolean isEqual(Object left, Object right)
071 {
072 return left == right || (left != null && left.equals(right));
073 }
074
075 /**
076 * Compares this Tuple to another object. Equality is defined by: other object is not null,
077 * is same class as this Tuple, and all values are themselves equal.
078 */
079 @Override
080 public boolean equals(Object obj)
081 {
082 if (obj == this)
083 return true;
084
085 if (obj == null || !(obj.getClass() == getClass()))
086 return false;
087
088 return isMatch(obj);
089 }
090
091 /**
092 * The heart of {@link #equals(Object)}; the other object is the same class as this object.
093 *
094 * @param other
095 * other tuple to compare
096 * @return true if all values stored in tuple match
097 */
098 protected boolean isMatch(Object other)
099 {
100 Tuple<?, ?> tuple = (Tuple<?, ?>) other;
101
102 return isEqual(first, tuple.first) && isEqual(second, tuple.second);
103 }
104 }