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.juneau.commons.function;
018
019import static org.apache.juneau.commons.utils.Utils.*;
020
021import java.util.Optional;
022
023import org.apache.juneau.commons.lang.*;
024
025/**
026 * Represents a simple tuple of 3 objects.
027 *
028 * <p>
029 * This class is useful when you need a three-value composite key for HashMap lookups that properly implements
030 * {@link #equals(Object)} and {@link #hashCode()} based on content rather than identity.
031 *
032 * <h5 class='section'>Array Support:</h5>
033 * <p>
034 * Unlike using arrays directly as HashMap keys, this class properly handles arrays by using
035 * content-based equality and hashing via {@link HashCode#of(Object...)} which internally uses
036 * {@link java.util.Arrays#hashCode(Object[])} for arrays.
037 *
038 * <h5 class='section'>See Also:</h5><ul>
039 *    <li class='jc'>{@link Tuple1}
040 *    <li class='jc'>{@link Tuple2}
041 *    <li class='jc'>{@link Tuple4}
042 *    <li class='jc'>{@link Tuple5}
043 * </ul>
044 *
045 * @param <A> Object 1 type.
046 * @param <B> Object 2 type.
047 * @param <C> Object 3 type.
048 */
049public class Tuple3<A,B,C> {
050
051   /**
052    * Static creator.
053    *
054    * @param <A> Object 1 type.
055    * @param <B> Object 2 type.
056    * @param <C> Object 3 type.
057    * @param a Object 1.
058    * @param b Object 2.
059    * @param c Object 3.
060    * @return A new tuple object.
061    */
062   public static <A,B,C> Tuple3<A,B,C> of(A a, B b, C c) {
063      return new Tuple3<>(a, b, c);
064   }
065
066   private final A a;
067   private final B b;
068   private final C c;
069   private final int hashCode;
070
071   /**
072    * Constructor.
073    *
074    * @param a Object 1.
075    * @param b Object 2.
076    * @param c Object 3.
077    */
078   public Tuple3(A a, B b, C c) {
079      this.a = a;
080      this.b = b;
081      this.c = c;
082      this.hashCode = h(a, b, c);
083   }
084
085   @Override /* Overridden from Object */
086   public boolean equals(Object o) {
087      return o instanceof Tuple3<?,?,?> o2 && eq(this, o2, (x, y) -> eq(x.a, y.a) && eq(x.b, y.b) && eq(x.c, y.c));
088   }
089
090   /**
091    * Returns the first object in this tuple.
092    *
093    * @return The first object in this tuple.
094    */
095   public A getA() { return a; }
096
097   /**
098    * Returns the second object in this tuple.
099    *
100    * @return The second object in this tuple.
101    */
102   public B getB() { return b; }
103
104   /**
105    * Returns the third object in this tuple.
106    *
107    * @return The third object in this tuple.
108    */
109   public C getC() { return c; }
110
111   /**
112    * Returns the first object in this tuple wrapped in an {@link Optional}.
113    *
114    * @return The first object wrapped in an Optional, or Optional.empty() if the value is null.
115    */
116   public Optional<A> optA() {
117      return Optional.ofNullable(a);
118   }
119
120   /**
121    * Returns the second object in this tuple wrapped in an {@link Optional}.
122    *
123    * @return The second object wrapped in an Optional, or Optional.empty() if the value is null.
124    */
125   public Optional<B> optB() {
126      return Optional.ofNullable(b);
127   }
128
129   /**
130    * Returns the third object in this tuple wrapped in an {@link Optional}.
131    *
132    * @return The third object wrapped in an Optional, or Optional.empty() if the value is null.
133    */
134   public Optional<C> optC() {
135      return Optional.ofNullable(c);
136   }
137
138   @Override /* Overridden from Object */
139   public int hashCode() {
140      return hashCode;
141   }
142}