2 * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.concepts;
10 import static com.google.common.base.Verify.verifyNotNull;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.annotations.Beta;
14 import com.google.common.base.MoreObjects;
15 import com.google.common.base.MoreObjects.ToStringHelper;
16 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
17 import java.util.Objects;
18 import java.util.Optional;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
23 * Utility holder of a two-variant value. The class design treats both variants as equal.
25 * @param <T> First alternative type
26 * @param <U> Second alternative type
27 * @author Robert Varga
31 public class Either<T, U> implements Immutable {
32 private final @Nullable T first;
33 private final @Nullable U second;
35 @SuppressFBWarnings("NP_STORE_INTO_NONNULL_FIELD")
36 protected Either(final T first) {
37 this.first = requireNonNull(first);
41 @SuppressFBWarnings("NP_STORE_INTO_NONNULL_FIELD")
42 protected Either(final U second, final @Nullable Void dummy) {
44 this.second = requireNonNull(second);
47 protected final T first() {
48 return verifyNotNull(first);
51 protected final U second() {
52 return verifyNotNull(second);
56 * Create a new instance containing specified value.
59 * @param <T> First alternative type
60 * @param <U> Second alternative type
61 * @return A new instance
62 * @throws NullPointerException if {@code value} is null
64 public static <T, U> Either<T, U> ofFirst(final T value) {
65 return new Either<>(value);
69 * Create a new instance containing specified value.
72 * @param <T> First alternative type
73 * @param <U> Second alternative type
74 * @return A new instance
75 * @throws NullPointerException if {@code value} is null
77 public static <T, U> Either<T, U> ofSecond(final U value) {
78 return new Either<>(value, null);
81 public final boolean isFirst() {
85 public final T getFirst() {
86 return tryFirst().get();
89 public final Optional<T> tryFirst() {
90 return Optional.ofNullable(first);
93 public final boolean isSecond() {
94 return second != null;
97 public final U getSecond() {
98 return trySecond().get();
101 public final Optional<U> trySecond() {
102 return Optional.ofNullable(second);
106 public final int hashCode() {
107 return Objects.hash(first, second);
111 public final boolean equals(final @Nullable Object obj) {
115 if (obj == null || !getClass().equals(obj.getClass())) {
118 final Either<?, ?> other = (Either<?, ?>) obj;
119 return Objects.equals(first, other.first) && Objects.equals(second, other.second);
123 public final String toString() {
124 return addToString(MoreObjects.toStringHelper(this).omitNullValues()).toString();
127 protected ToStringHelper addToString(final ToStringHelper helper) {
128 return helper.add("first", first).add("second", second);