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