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 *      https://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 */
017package org.apache.commons.lang3.tuple;
018
019import java.io.Serializable;
020import java.util.Objects;
021
022import org.apache.commons.lang3.builder.CompareToBuilder;
023
024/**
025 * A triple consisting of three elements.
026 *
027 * <p>
028 * This class is an abstract implementation defining the basic API.
029 * It refers to the elements as 'left', 'middle' and 'right'.
030 * </p>
031 *
032 * <p>
033 * Subclass implementations may be mutable or immutable.
034 * However, there is no restriction on the type of the stored objects that may be stored.
035 * If mutable objects are stored in the triple, then the triple itself effectively becomes mutable.
036 * </p>
037 *
038 * @param <L> The left element type.
039 * @param <M> The middle element type.
040 * @param <R> The right element type.
041 * @since 3.2
042 */
043public abstract class Triple<L, M, R> implements Comparable<Triple<L, M, R>>, Serializable {
044
045    /** Serialization version */
046    private static final long serialVersionUID = 1L;
047
048    /**
049     * An empty array.
050     * <p>
051     * Consider using {@link #emptyArray()} to avoid generics warnings.
052     * </p>
053     *
054     * @since 3.10
055     */
056    public static final Triple<?, ?, ?>[] EMPTY_ARRAY = {};
057
058    /**
059     * Returns the empty array singleton that can be assigned without compiler warning.
060     *
061     * @param <L> The left element type.
062     * @param <M> The middle element type.
063     * @param <R> The right element type.
064     * @return The empty array singleton that can be assigned without compiler warning.
065     * @since 3.10
066     */
067    @SuppressWarnings("unchecked")
068    public static <L, M, R> Triple<L, M, R>[] emptyArray() {
069        return (Triple<L, M, R>[]) EMPTY_ARRAY;
070    }
071
072    /**
073     * Obtains an immutable triple of three objects inferring the generic types.
074     *
075     * @param <L> The left element type.
076     * @param <M> The middle element type.
077     * @param <R> The right element type.
078     * @param left  The left element, may be null.
079     * @param middle The middle element, may be null.
080     * @param right  The right element, may be null.
081     * @return An immutable triple formed from the three parameters, not null.
082     */
083    public static <L, M, R> Triple<L, M, R> of(final L left, final M middle, final R right) {
084        return ImmutableTriple.of(left, middle, right);
085    }
086
087    /**
088     * Obtains an immutable triple of three non-null objects inferring the generic types.
089     *
090     * @param <L> The left element type.
091     * @param <M> The middle element type.
092     * @param <R> The right element type.
093     * @param left  The left element, may not be null.
094     * @param middle  The middle element, may not be null.
095     * @param right  The right element, may not be null.
096     * @return An immutable triple formed from the three parameters, not null.
097     * @throws NullPointerException Thrown if any input is null.
098     * @since 3.13.0
099     */
100    public static <L, M, R> Triple<L, M, R> ofNonNull(final L left, final M middle, final R right) {
101        return ImmutableTriple.ofNonNull(left, middle, right);
102    }
103
104    /**
105     * Constructs a new instance.
106     */
107    public Triple() {
108        // empty
109    }
110
111    /**
112     * Compares the triple based on the left element, followed by the middle element,
113     * finally the right element.
114     * The types must be {@link Comparable}.
115     *
116     * @param other  The other triple, not null.
117     * @return negative if this is less, zero if equal, positive if greater.
118     */
119    @Override
120    public int compareTo(final Triple<L, M, R> other) {
121      return new CompareToBuilder().append(getLeft(), other.getLeft())
122          .append(getMiddle(), other.getMiddle())
123          .append(getRight(), other.getRight()).toComparison();
124    }
125
126    /**
127     * Compares this triple to another based on the three elements.
128     *
129     * @param obj  The object to compare to, null returns false.
130     * @return true if the elements of the triple are equal.
131     */
132    @Override
133    public boolean equals(final Object obj) {
134        if (obj == this) {
135            return true;
136        }
137        if (obj instanceof Triple<?, ?, ?>) {
138            final Triple<?, ?, ?> other = (Triple<?, ?, ?>) obj;
139            return Objects.equals(getLeft(), other.getLeft())
140                && Objects.equals(getMiddle(), other.getMiddle())
141                && Objects.equals(getRight(), other.getRight());
142        }
143        return false;
144    }
145
146    /**
147     * Gets the left element from this triple.
148     *
149     * @return The left element, may be null.
150     */
151    public abstract L getLeft();
152
153    /**
154     * Gets the middle element from this triple.
155     *
156     * @return The middle element, may be null.
157     */
158    public abstract M getMiddle();
159
160    /**
161     * Gets the right element from this triple.
162     *
163     * @return The right element, may be null.
164     */
165    public abstract R getRight();
166
167    /**
168     * Returns a suitable hash code.
169     * <p>
170     * The hash code is adapted from the definition in {@code Map.Entry}.
171     * </p>
172     *
173     * @return The hash code.
174     */
175    @Override
176    public int hashCode() {
177        // See Map.Entry API specification
178        return Objects.hashCode(getLeft()) ^ Objects.hashCode(getMiddle()) ^ Objects.hashCode(getRight());
179    }
180
181    /**
182     * Returns a String representation of this triple using the format {@code (left,middle,right)}.
183     *
184     * @return A string describing this object, not null.
185     */
186    @Override
187    public String toString() {
188        return "(" + getLeft() + "," + getMiddle() + "," + getRight() + ")";
189    }
190
191    /**
192     * Formats the receiver using the given format.
193     *
194     * <p>
195     * This uses {@link java.util.Formattable} to perform the formatting. Three variables may
196     * be used to embed the left and right elements. Use {@code %1$s} for the left
197     * element, {@code %2$s} for the middle and {@code %3$s} for the right element.
198     * The default format used by {@code toString()} is {@code (%1$s,%2$s,%3$s)}.
199     * </p>
200     *
201     * @param format  The format string, optionally containing {@code %1$s}, {@code %2$s} and {@code %3$s}, not null.
202     * @return The formatted string, not null.
203     */
204    public String toString(final String format) {
205        return String.format(format, getLeft(), getMiddle(), getRight());
206    }
207
208}
209