001    /*
002    // $Id: //open/mondrian/src/main/mondrian/util/Pair.java#3 $
003    // This software is subject to the terms of the Common Public License
004    // Agreement, available at the following URL:
005    // http://www.opensource.org/licenses/cpl.html.
006    // Copyright (C) 2007-2008 Julian Hyde
007    // All Rights Reserved.
008    // You must accept the terms of that agreement to use this software.
009    */
010    package mondrian.util;
011    
012    import mondrian.olap.Util;
013    
014    import java.util.Map;
015    
016    /**
017     * Pair of values.
018     *
019     * <p>Because a pair implements {@link #equals(Object)}, {@link #hashCode()} and
020     * {@link #compareTo(Pair)}, it can be used in any kind of
021     * {@link java.util.Collection}.
022     *
023     * @author jhyde
024     * @version $Id: //open/mondrian/src/main/mondrian/util/Pair.java#3 $
025     * @since Apr 19, 2007
026     */
027    public class Pair <L, R>
028        implements Comparable<Pair<L, R>>, Map.Entry<L, R>
029    {
030        public L left;
031        public R right;
032    
033        /**
034         * Creates a pair.
035         *
036         * @param left Left value
037         * @param right Right value
038         */
039        public Pair(L left, R right) {
040            this.left = left;
041            this.right = right;
042        }
043    
044        /**
045         * Creates a pair representing the same mapping as the
046         * specified entry.
047         *
048         * @param entry the entry to copy
049         */
050        public Pair(Map.Entry<? extends L, ? extends R> entry) {
051            this.left = entry.getKey();
052            this.right = entry.getValue();
053        }
054    
055        public boolean equals(Object obj) {
056            if (obj instanceof Pair) {
057                //noinspection unchecked
058                Pair<L, R> pair = (Pair) obj;
059                return Util.equals(this.left, pair.left) &&
060                    Util.equals(this.right, pair.right);
061            }
062            return false;
063        }
064    
065        public int hashCode() {
066            int k = (left == null) ? 0 : left.hashCode();
067            int k1 = (right == null) ? 0 : right.hashCode();
068            return ((k << 4) | k) ^ k1;
069        }
070    
071    
072        public int compareTo(Pair<L, R> that) {
073            int c = compare((Comparable) this.left, (Comparable)that.left);
074            if (c == 0) {
075                c = compare((Comparable) this.right, (Comparable)that.right);
076            }
077            return c;
078        }
079    
080        public String toString() {
081            return "<" + left + ", " + right + ">";
082        }
083    
084        // implement Map.Entry
085        public L getKey() {
086            return left;
087        }
088    
089        // implement Map.Entry
090        public R getValue() {
091            return right;
092        }
093    
094        // implement Map.Entry
095        public R setValue(R value) {
096            R previous = right;
097            right = value;
098            return previous;
099        }
100    
101        /**
102         * Compares a pair of comparable values of the same type. Null collates
103         * less than everything else, but equal to itself.
104         *
105         * @param c1 First value
106         * @param c2 Second value
107         * @return  a negative integer, zero, or a positive integer if c1
108         *          is less than, equal to, or greater than c2.
109         */
110        private static <C extends Comparable<C>> int compare(C c1, C c2) {
111            if (c1 == null) {
112                if (c2 == null) {
113                    return 0;
114                } else {
115                    return -1;
116                }
117            } else if (c2 == null) {
118                return 1;
119            } else {
120                return c1.compareTo(c2);
121            }
122        }
123    }
124    
125    // End Pair.java