001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.lang3.tuple;
018    
019    import java.io.Serializable;
020    import java.util.Map;
021    
022    import org.apache.commons.lang3.ObjectUtils;
023    import org.apache.commons.lang3.builder.CompareToBuilder;
024    
025    /**
026     * <p>A pair consisting of two elements.</p>
027     * 
028     * <p>This class is an abstract implementation defining the basic API.
029     * It refers to the elements as 'left' and 'right'. It also implements the
030     * {@code Map.Entry} interface where the key is 'left' and the value is 'right'.</p>
031     * 
032     * <p>Subclass implementations may be mutable or immutable.
033     * However, there is no restriction on the type of the stored objects that may be stored.
034     * If mutable objects are stored in the pair, then the pair itself effectively becomes mutable.</p>
035     *
036     * @param <L> the left element type
037     * @param <R> the right element type
038     *
039     * @since Lang 3.0
040     * @version $Id: Pair.java 1142401 2011-07-03 08:30:12Z bayard $
041     */
042    public abstract class Pair<L, R> implements Map.Entry<L, R>, Comparable<Pair<L, R>>, Serializable {
043    
044        /** Serialization version */
045        private static final long serialVersionUID = 4954918890077093841L;
046    
047        /**
048         * <p>Obtains an immutable pair of from two objects inferring the generic types.</p>
049         * 
050         * <p>This factory allows the pair to be created using inference to
051         * obtain the generic types.</p>
052         * 
053         * @param <L> the left element type
054         * @param <R> the right element type
055         * @param left  the left element, may be null
056         * @param right  the right element, may be null
057         * @return a pair formed from the two parameters, not null
058         */
059        public static <L, R> Pair<L, R> of(L left, R right) {
060            return new ImmutablePair<L, R>(left, right);
061        }
062    
063        //-----------------------------------------------------------------------
064        /**
065         * <p>Gets the left element from this pair.</p>
066         * 
067         * <p>When treated as a key-value pair, this is the key.</p>
068         * 
069         * @return the left element, may be null
070         */
071        public abstract L getLeft();
072    
073        /**
074         * <p>Gets the right element from this pair.</p>
075         * 
076         * <p>When treated as a key-value pair, this is the value.</p>
077         * 
078         * @return the right element, may be null
079         */
080        public abstract R getRight();
081    
082        /**
083         * <p>Gets the key from this pair.</p>
084         * 
085         * <p>This method implements the {@code Map.Entry} interface returning the
086         * left element as the key.</p>
087         * 
088         * @return the left element as the key, may be null
089         */
090        public final L getKey() {
091            return getLeft();
092        }
093    
094        /**
095         * <p>Gets the value from this pair.</p>
096         * 
097         * <p>This method implements the {@code Map.Entry} interface returning the
098         * right element as the value.</p>
099         * 
100         * @return the right element as the value, may be null
101         */
102        public R getValue() {
103            return getRight();
104        }
105    
106        //-----------------------------------------------------------------------
107        /**
108         * <p>Compares the pair based on the left element followed by the right element.
109         * The types must be {@code Comparable}.</p>
110         * 
111         * @param other  the other pair, not null
112         * @return negative if this is less, zero if equal, positive if greater
113         */
114        public int compareTo(Pair<L, R> other) {
115          return new CompareToBuilder().append(getLeft(), other.getLeft())
116                  .append(getRight(), other.getRight()).toComparison();
117        }
118    
119        /**
120         * <p>Compares this pair to another based on the two elements.</p>
121         * 
122         * @param obj  the object to compare to, null returns false
123         * @return true if the elements of the pair are equal
124         */
125        @Override
126        public boolean equals(Object obj) {
127            if (obj == this) {
128                return true;
129            }
130            if (obj instanceof Map.Entry<?, ?>) {
131                Map.Entry<?, ?> other = (Map.Entry<?, ?>) obj;
132                return ObjectUtils.equals(getKey(), other.getKey())
133                        && ObjectUtils.equals(getValue(), other.getValue());
134            }
135            return false;
136        }
137    
138        /**
139         * <p>Returns a suitable hash code.
140         * The hash code follows the definition in {@code Map.Entry}.</p>
141         * 
142         * @return the hash code
143         */
144        @Override
145        public int hashCode() {
146            // see Map.Entry API specification
147            return (getKey() == null ? 0 : getKey().hashCode()) ^
148                    (getValue() == null ? 0 : getValue().hashCode());
149        }
150    
151        /**
152         * <p>Returns a String representation of this pair using the format {@code ($left,$right)}.</p>
153         * 
154         * @return a string describing this object, not null
155         */
156        @Override
157        public String toString() {
158            return new StringBuilder().append('(').append(getLeft()).append(',').append(getRight()).append(')').toString();
159        }
160    
161        /**
162         * <p>Formats the receiver using the given format.</p>
163         * 
164         * <p>This uses {@link java.util.Formattable} to perform the formatting. Two variables may
165         * be used to embed the left and right elements. Use {@code %1$s} for the left
166         * element (key) and {@code %2$s} for the right element (value).
167         * The default format used by {@code toString()} is {@code (%1$s,%2$s)}.</p>
168         * 
169         * @param format  the format string, optionally containing {@code %1$s} and {@code %2$s}, not null
170         * @return the formatted string, not null
171         */
172        public String toString(String format) {
173            return String.format(format, getLeft(), getRight());
174        }
175    
176    }