View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3.tuple;
18  
19  import java.io.Serializable;
20  
21  import org.apache.commons.lang3.ObjectUtils;
22  import org.apache.commons.lang3.builder.CompareToBuilder;
23  
24  /**
25   * <p>A triple consisting of three elements.</p>
26   *
27   * <p>This class is an abstract implementation defining the basic API.
28   * It refers to the elements as 'left', 'middle' and 'right'.</p>
29   *
30   * <p>Subclass implementations may be mutable or immutable.
31   * However, there is no restriction on the type of the stored objects that may be stored.
32   * If mutable objects are stored in the triple, then the triple itself effectively becomes mutable.</p>
33   *
34   * @param <L> the left element type
35   * @param <M> the middle element type
36   * @param <R> the right element type
37   *
38   * @version $Id: Triple.java 1557584 2014-01-12 18:26:49Z britter $
39   * @since 3.2
40   */
41  public abstract class Triple<L, M, R> implements Comparable<Triple<L, M, R>>, Serializable {
42  
43      /** Serialization version */
44      private static final long serialVersionUID = 1L;
45  
46      /**
47       * <p>Obtains an immutable triple of from three objects inferring the generic types.</p>
48       *
49       * <p>This factory allows the triple to be created using inference to
50       * obtain the generic types.</p>
51       *
52       * @param <L> the left element type
53       * @param <M> the middle element type
54       * @param <R> the right element type
55       * @param left  the left element, may be null
56       * @param middle the middle element, may be null
57       * @param right  the right element, may be null
58       * @return a triple formed from the three parameters, not null
59       */
60      public static <L, M, R> Triple<L, M, R> of(final L left, final M middle, final R right) {
61          return new ImmutableTriple<L, M, R>(left, middle, right);
62      }
63  
64      //-----------------------------------------------------------------------
65      /**
66       * <p>Gets the left element from this triple.</p>
67       *
68       * @return the left element, may be null
69       */
70      public abstract L getLeft();
71  
72      /**
73       * <p>Gets the middle element from this triple.</p>
74       *
75       * @return the middle element, may be null
76       */
77      public abstract M getMiddle();
78  
79      /**
80       * <p>Gets the right element from this triple.</p>
81       *
82       * @return the right element, may be null
83       */
84      public abstract R getRight();
85  
86      //-----------------------------------------------------------------------
87      /**
88       * <p>Compares the triple based on the left element, followed by the middle element,
89       * finally the right element.
90       * The types must be {@code Comparable}.</p>
91       *
92       * @param other  the other triple, not null
93       * @return negative if this is less, zero if equal, positive if greater
94       */
95      @Override
96      public int compareTo(final Triple<L, M, R> other) {
97        return new CompareToBuilder().append(getLeft(), other.getLeft())
98            .append(getMiddle(), other.getMiddle())
99            .append(getRight(), other.getRight()).toComparison();
100     }
101 
102     /**
103      * <p>Compares this triple to another based on the three elements.</p>
104      *
105      * @param obj  the object to compare to, null returns false
106      * @return true if the elements of the triple are equal
107      */
108     @SuppressWarnings( "deprecation" ) // ObjectUtils.equals(Object, Object) has been deprecated in 3.2
109     @Override
110     public boolean equals(final Object obj) {
111         if (obj == this) {
112             return true;
113         }
114         if (obj instanceof Triple<?, ?, ?>) {
115             final Triple<?, ?, ?> other = (Triple<?, ?, ?>) obj;
116             return ObjectUtils.equals(getLeft(), other.getLeft())
117                 && ObjectUtils.equals(getMiddle(), other.getMiddle())
118                 && ObjectUtils.equals(getRight(), other.getRight());
119         }
120         return false;
121     }
122 
123     /**
124      * <p>Returns a suitable hash code.</p>
125      *
126      * @return the hash code
127      */
128     @Override
129     public int hashCode() {
130         return (getLeft() == null ? 0 : getLeft().hashCode()) ^
131             (getMiddle() == null ? 0 : getMiddle().hashCode()) ^
132             (getRight() == null ? 0 : getRight().hashCode());
133     }
134 
135     /**
136      * <p>Returns a String representation of this triple using the format {@code ($left,$middle,$right)}.</p>
137      *
138      * @return a string describing this object, not null
139      */
140     @Override
141     public String toString() {
142         return new StringBuilder().append('(').append(getLeft()).append(',').append(getMiddle()).append(',')
143             .append(getRight()).append(')').toString();
144     }
145 
146     /**
147      * <p>Formats the receiver using the given format.</p>
148      *
149      * <p>This uses {@link java.util.Formattable} to perform the formatting. Three variables may
150      * be used to embed the left and right elements. Use {@code %1$s} for the left
151      * element, {@code %2$s} for the middle and {@code %3$s} for the right element.
152      * The default format used by {@code toString()} is {@code (%1$s,%2$s,%3$s)}.</p>
153      *
154      * @param format  the format string, optionally containing {@code %1$s}, {@code %2$s} and {@code %3$s}, not null
155      * @return the formatted string, not null
156      */
157     public String toString(final String format) {
158         return String.format(format, getLeft(), getMiddle(), getRight());
159     }
160 
161 }
162