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