11/*
2- * Licensed to the Apache Software Foundation (ASF) under one
3- * or more contributor license agreements. See the NOTICE file
4- * distributed with this work for additional information
5- * regarding copyright ownership. The ASF licenses this file
6- * to you under the Apache License, Version 2.0 (the
7- * "License"); you may not use this file except in compliance
8- * with the License. You may obtain a copy of the License at
2+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
93 *
10- * http://www.apache.org/licenses/LICENSE-2.0
4+ * Licensed under the Apache License, Version 2.0 (the "License").
5+ * You may not use this file except in compliance with the License.
6+ * A copy of the License is located at
117 *
12- * Unless required by applicable law or agreed to in writing,
13- * software distributed under the License is distributed on an
14- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15- * KIND, either express or implied. See the License for the
16- * specific language governing permissions and limitations
17- * under the License.
8+ * http://aws.amazon.com/apache2.0
9+ *
10+ * or in the "license" file accompanying this file. This file is distributed
11+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+ * express or implied. See the License for the specific language governing
13+ * permissions and limitations under the License.
1814 */
1915
2016package org .apache .gravitino .listener .api .info ;
2117
18+ import com .google .common .base .Preconditions ;
2219import java .util .Optional ;
23- import org .glassfish .jersey .internal .guava .Preconditions ;
20+ import java .util .function .Consumer ;
21+ import java .util .function .Function ;
2422
2523/**
26- * Either represents a value of two possible types (a disjoint union) .
24+ * Represents a value that can be one of two types .
2725 *
2826 * @param <L> Left type
2927 * @param <R> Right type
3028 */
3129public final class Either <L , R > {
30+
3231 private final Optional <L > left ;
3332 private final Optional <R > right ;
3433
34+ private Either (Optional <L > l , Optional <R > r ) {
35+ left = l ;
36+ right = r ;
37+ }
38+
3539 /**
36- * Create a new {@code Either} instance with a left value.
40+ * Maps the Either to a type and returns the resolved value (which may be from the left or the
41+ * right value).
42+ *
43+ * @param lFunc Function that maps the left value if present.
44+ * @param rFunc Function that maps the right value if present.
45+ * @param <T> Type that both the left and right should be mapped to.
46+ * @return Mapped value from either lFunc or rFunc depending on which value is present.
47+ */
48+ public <T > T map (Function <? super L , ? extends T > lFunc , Function <? super R , ? extends T > rFunc ) {
49+ return left .<T >map (lFunc ).orElseGet (() -> right .map (rFunc ).get ());
50+ }
51+
52+ /**
53+ * Map the left most value and return a new Either reflecting the new types.
54+ *
55+ * @param lFunc Function that maps the left value if present.
56+ * @param <T> New type of left value.
57+ * @return New Either bound to the new left type and the same right type.
58+ */
59+ public <T > Either <T , R > mapLeft (Function <? super L , ? extends T > lFunc ) {
60+ return new Either <>(left .map (lFunc ), right );
61+ }
62+
63+ /**
64+ * Map the right most value and return a new Either reflecting the new types.
65+ *
66+ * @param rFunc Function that maps the right value if present.
67+ * @param <T> New type of right value.
68+ * @return New Either bound to the same left type and the new right type.
69+ */
70+ public <T > Either <L , T > mapRight (Function <? super R , ? extends T > rFunc ) {
71+ return new Either <>(left , right .map (rFunc ));
72+ }
73+
74+ /**
75+ * Apply the consumers to the left or the right value depending on which is present.
76+ *
77+ * @param lFunc Consumer of left value, invoked if left value is present.
78+ * @param rFunc Consumer of right value, invoked if right value is present.
79+ */
80+ public void apply (Consumer <? super L > lFunc , Consumer <? super R > rFunc ) {
81+ left .ifPresent (lFunc );
82+ right .ifPresent (rFunc );
83+ }
84+
85+ /**
86+ * Create a new Either with the left type.
3787 *
3888 * @param value Left value
39- * @return Either with left value
4089 * @param <L> Left type
4190 * @param <R> Right type
4291 */
@@ -46,10 +95,9 @@ public static <L, R> Either<L, R> left(L value) {
4695 }
4796
4897 /**
49- * Create a new {@code Either} instance with a right value .
98+ * Create a new Either with the right type .
5099 *
51100 * @param value Right value
52- * @return Either with right value
53101 * @param <L> Left type
54102 * @param <R> Right type
55103 */
@@ -58,53 +106,60 @@ public static <L, R> Either<L, R> right(R value) {
58106 return new Either <>(Optional .empty (), Optional .of (value ));
59107 }
60108
61- /** Private constructor. */
62- private Either (Optional <L > l , Optional <R > r ) {
63- left = l ;
64- right = r ;
109+ /** @return the left value */
110+ public Optional <L > left () {
111+ return left ;
65112 }
66113
67- /**
68- * Returns true if this is a left value.
69- *
70- * @return True if this is a left value
71- */
72- public boolean isLeft () {
73- return left .isPresent ();
114+ /** @return the right value */
115+ public Optional <R > right () {
116+ return right ;
74117 }
75118
76119 /**
77- * Returns true if this is a right value .
120+ * Create a new {@code Optional<Either>} from two possibly null values .
78121 *
79- * @return True if this is a right value
80- */
81- public boolean isRight () {
82- return right .isPresent ();
83- }
84-
85- /**
86- * Returns the left value if this is a left value, otherwise throws an exception.
122+ * <p>If both values are null, {@link Optional#empty()} is returned. Only one of the left or right
123+ * values is allowed to be non-null, otherwise an {@link IllegalArgumentException} is thrown.
87124 *
88- * @return Left value
89- * @throws IllegalStateException if this is a right value
125+ * @param left The left value (possibly null)
126+ * @param right The right value (possibly null)
127+ * @param <L> Left type
128+ * @param <R> Right type
129+ * @return an Optional Either representing one of the two values or empty if both are null
90130 */
91- public L getLeft () {
92- if (isRight ()) {
93- throw new IllegalStateException ("Not a left value" );
131+ public static <L , R > Optional <Either <L , R >> fromNullable (L left , R right ) {
132+ if (left != null && right == null ) {
133+ return Optional .of (left (left ));
134+ }
135+ if (left == null && right != null ) {
136+ return Optional .of (right (right ));
94137 }
95- return left .get ();
138+ if (left == null && right == null ) {
139+ return Optional .empty ();
140+ }
141+ throw new IllegalArgumentException (
142+ String .format (
143+ "Only one of either left or right should be non-null. " + "Got (left: %s, right: %s)" ,
144+ left , right ));
96145 }
97146
98- /**
99- * Returns the right value if this is a right value, otherwise throws an exception.
100- *
101- * @return Right value
102- * @throws IllegalStateException if this is a left value
103- */
104- public R getRight () {
105- if (isLeft ()) {
106- throw new IllegalStateException ("Not a right value" );
147+ @ Override
148+ public boolean equals (Object o ) {
149+ if (this == o ) {
150+ return true ;
151+ }
152+ if (!(o instanceof Either )) {
153+ return false ;
107154 }
108- return right .get ();
155+
156+ Either <?, ?> either = (Either <?, ?>) o ;
157+
158+ return left .equals (either .left ) && right .equals (either .right );
159+ }
160+
161+ @ Override
162+ public int hashCode () {
163+ return 31 * left .hashCode () + right .hashCode ();
109164 }
110165}
0 commit comments