    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    }