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     * <p>This factory allows the triple to be created using inference to
072     * obtain the generic types.</p>
073     *
074     * @param <L> the left element type.
075     * @param <M> the middle element type.
076     * @param <R> the right element type.
077     * @param left  the left element, may be null.
078     * @param middle the middle element, may be null.
079     * @param right  the right element, may be null.
080     * @return a triple formed from the three parameters, not null.
081     */
082    public static <L, M, R> Triple<L, M, R> of(final L left, final M middle, final R right) {
083        return ImmutableTriple.of(left, middle, right);
084    }
085
086    /**
087     * Obtains an immutable triple of three non-null objects inferring the generic types.
088     *
089     * <p>This factory allows the triple to be created using inference to
090     * obtain the generic types.</p>
091     *
092     * @param <L> the left element type.
093     * @param <M> the middle element type.
094     * @param <R> the right element type.
095     * @param left  the left element, may not be null.
096     * @param middle  the middle element, may not be null.
097     * @param right  the right element, may not be null.
098     * @return a triple formed from the three parameters, not null.
099     * @throws NullPointerException if any input is null.
100     * @since 3.13.0
101     */
102    public static <L, M, R> Triple<L, M, R> ofNonNull(final L left, final M middle, final R right) {
103        return ImmutableTriple.ofNonNull(left, middle, right);
104    }
105
106    /**
107     * Constructs a new instance.
108     */
109    public Triple() {
110        // empty
111    }
112
113    /**
114     * Compares the triple based on the left element, followed by the middle element,
115     * finally the right element.
116     * The types must be {@link Comparable}.
117     *
118     * @param other  the other triple, not null.
119     * @return negative if this is less, zero if equal, positive if greater.
120     */
121    @Override
122    public int compareTo(final Triple<L, M, R> other) {
123      return new CompareToBuilder().append(getLeft(), other.getLeft())
124          .append(getMiddle(), other.getMiddle())
125          .append(getRight(), other.getRight()).toComparison();
126    }
127
128    /**
129     * Compares this triple to another based on the three elements.
130     *
131     * @param obj  the object to compare to, null returns false.
132     * @return true if the elements of the triple are equal.
133     */
134    @Override
135    public boolean equals(final Object obj) {
136        if (obj == this) {
137            return true;
138        }
139        if (obj instanceof Triple<?, ?, ?>) {
140            final Triple<?, ?, ?> other = (Triple<?, ?, ?>) obj;
141            return Objects.equals(getLeft(), other.getLeft())
142                && Objects.equals(getMiddle(), other.getMiddle())
143                && Objects.equals(getRight(), other.getRight());
144        }
145        return false;
146    }
147
148    /**
149     * Gets the left element from this triple.
150     *
151     * @return the left element, may be null.
152     */
153    public abstract L getLeft();
154
155    /**
156     * Gets the middle element from this triple.
157     *
158     * @return the middle element, may be null.
159     */
160    public abstract M getMiddle();
161
162    /**
163     * Gets the right element from this triple.
164     *
165     * @return the right element, may be null.
166     */
167    public abstract R getRight();
168
169    /**
170     * Returns a suitable hash code.
171     * <p>
172     * The hash code is adapted from the definition in {@code Map.Entry}.
173     * </p>
174     *
175     * @return the hash code.
176     */
177    @Override
178    public int hashCode() {
179        // See Map.Entry API specification
180        return Objects.hashCode(getLeft()) ^ Objects.hashCode(getMiddle()) ^ Objects.hashCode(getRight());
181    }
182
183    /**
184     * Returns a String representation of this triple using the format {@code (left,middle,right)}.
185     *
186     * @return a string describing this object, not null.
187     */
188    @Override
189    public String toString() {
190        return "(" + getLeft() + "," + getMiddle() + "," + getRight() + ")";
191    }
192
193    /**
194     * Formats the receiver using the given format.
195     *
196     * <p>This uses {@link java.util.Formattable} to perform the formatting. Three variables may
197     * be used to embed the left and right elements. Use {@code %1$s} for the left
198     * element, {@code %2$s} for the middle and {@code %3$s} for the right element.
199     * The default format used by {@code toString()} is {@code (%1$s,%2$s,%3$s)}.</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