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 4 objects.
027 *
028 * <p>
029 * This class is useful when you need a four-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 Tuple3}
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 * @param <D> Object 4 type.
049 */
050public class Tuple4<A,B,C,D> {
051
052   /**
053    * Static creator.
054    *
055    * @param <A> Object 1 type.
056    * @param <B> Object 2 type.
057    * @param <C> Object 3 type.
058    * @param <D> Object 4 type.
059    * @param a Object 1.
060    * @param b Object 2.
061    * @param c Object 3.
062    * @param d Object 4.
063    * @return A new tuple object.
064    */
065   public static <A,B,C,D> Tuple4<A,B,C,D> of(A a, B b, C c, D d) {
066      return new Tuple4<>(a, b, c, d);
067   }
068
069   private final A a;
070   private final B b;
071   private final C c;
072   private final D d;
073   private final int hashCode;
074
075   /**
076    * Constructor.
077    *
078    * @param a Object 1.
079    * @param b Object 2.
080    * @param c Object 3.
081    * @param d Object 4.
082    */
083   public Tuple4(A a, B b, C c, D d) {
084      this.a = a;
085      this.b = b;
086      this.c = c;
087      this.d = d;
088      this.hashCode = h(a, b, c, d);
089   }
090
091   @Override /* Overridden from Object */
092   public boolean equals(Object o) {
093      return o instanceof Tuple4<?,?,?,?> o2 && eq(this, o2, (x, y) -> eq(x.a, y.a) && eq(x.b, y.b) && eq(x.c, y.c) && eq(x.d, y.d));
094   }
095
096   /**
097    * Returns the first object in this tuple.
098    *
099    * @return The first object in this tuple.
100    */
101   public A getA() { return a; }
102
103   /**
104    * Returns the second object in this tuple.
105    *
106    * @return The second object in this tuple.
107    */
108   public B getB() { return b; }
109
110   /**
111    * Returns the third object in this tuple.
112    *
113    * @return The third object in this tuple.
114    */
115   public C getC() { return c; }
116
117   /**
118    * Returns the fourth object in this tuple.
119    *
120    * @return The fourth object in this tuple.
121    */
122   public D getD() { return d; }
123
124   /**
125    * Returns the first object in this tuple wrapped in an {@link Optional}.
126    *
127    * @return The first object wrapped in an Optional, or Optional.empty() if the value is null.
128    */
129   public Optional<A> optA() {
130      return Optional.ofNullable(a);
131   }
132
133   /**
134    * Returns the second object in this tuple wrapped in an {@link Optional}.
135    *
136    * @return The second object wrapped in an Optional, or Optional.empty() if the value is null.
137    */
138   public Optional<B> optB() {
139      return Optional.ofNullable(b);
140   }
141
142   /**
143    * Returns the third object in this tuple wrapped in an {@link Optional}.
144    *
145    * @return The third object wrapped in an Optional, or Optional.empty() if the value is null.
146    */
147   public Optional<C> optC() {
148      return Optional.ofNullable(c);
149   }
150
151   /**
152    * Returns the fourth object in this tuple wrapped in an {@link Optional}.
153    *
154    * @return The fourth object wrapped in an Optional, or Optional.empty() if the value is null.
155    */
156   public Optional<D> optD() {
157      return Optional.ofNullable(d);
158   }
159
160   @Override /* Overridden from Object */
161   public int hashCode() {
162      return hashCode;
163   }
164}