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     * Compares the triple based on the left element, followed by the middle element,
110     * finally the right element.
111     * The types must be {@link Comparable}.
112     *
113     * @param other  the other triple, not null
114     * @return negative if this is less, zero if equal, positive if greater
115     */
116    @Override
117    public int compareTo(final Triple<L, M, R> other) {
118      return new CompareToBuilder().append(getLeft(), other.getLeft())
119          .append(getMiddle(), other.getMiddle())
120          .append(getRight(), other.getRight()).toComparison();
121    }
122
123    /**
124     * Compares this triple to another based on the three elements.
125     *
126     * @param obj  the object to compare to, null returns false
127     * @return true if the elements of the triple are equal
128     */
129    @Override
130    public boolean equals(final Object obj) {
131        if (obj == this) {
132            return true;
133        }
134        if (obj instanceof Triple<?, ?, ?>) {
135            final Triple<?, ?, ?> other = (Triple<?, ?, ?>) obj;
136            return Objects.equals(getLeft(), other.getLeft())
137                && Objects.equals(getMiddle(), other.getMiddle())
138                && Objects.equals(getRight(), other.getRight());
139        }
140        return false;
141    }
142
143    /**
144     * Gets the left element from this triple.
145     *
146     * @return the left element, may be null
147     */
148    public abstract L getLeft();
149
150    /**
151     * Gets the middle element from this triple.
152     *
153     * @return the middle element, may be null
154     */
155    public abstract M getMiddle();
156
157    /**
158     * Gets the right element from this triple.
159     *
160     * @return the right element, may be null
161     */
162    public abstract R getRight();
163
164    /**
165     * Returns a suitable hash code.
166     *
167     * @return the hash code
168     */
169    @Override
170    public int hashCode() {
171        return Objects.hashCode(getLeft()) ^ Objects.hashCode(getMiddle()) ^ Objects.hashCode(getRight());
172    }
173
174    /**
175     * Returns a String representation of this triple using the format {@code ($left,$middle,$right)}.
176     *
177     * @return a string describing this object, not null
178     */
179    @Override
180    public String toString() {
181        return "(" + getLeft() + "," + getMiddle() + "," + getRight() + ")";
182    }
183
184    /**
185     * Formats the receiver using the given format.
186     *
187     * <p>This uses {@link java.util.Formattable} to perform the formatting. Three variables may
188     * be used to embed the left and right elements. Use {@code %1$s} for the left
189     * element, {@code %2$s} for the middle and {@code %3$s} for the right element.
190     * The default format used by {@code toString()} is {@code (%1$s,%2$s,%3$s)}.</p>
191     *
192     * @param format  the format string, optionally containing {@code %1$s}, {@code %2$s} and {@code %3$s}, not null
193     * @return the formatted string, not null
194     */
195    public String toString(final String format) {
196        return String.format(format, getLeft(), getMiddle(), getRight());
197    }
198
199}
200