• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
3  *
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  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.android.libraries.mobiledatadownload.internal.util;
17 
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Collections;
21 import java.util.Comparator;
22 import java.util.List;
23 import org.checkerframework.checker.nullness.qual.Nullable;
24 
25 /** An object that contains either one of the left field or right field, but not both. */
26 public final class Either<A, B> {
27 
28   private final boolean hasLeft;
29   private final @Nullable A left;
30   private final @Nullable B right;
31 
Either(boolean hasLeft, @Nullable A left, @Nullable B right)32   private Either(boolean hasLeft, @Nullable A left, @Nullable B right) {
33     this.hasLeft = hasLeft;
34     this.left = left;
35     this.right = right;
36   }
37 
makeLeft(A left)38   public static <A, B> Either<A, B> makeLeft(A left) {
39     return new Either<>(true, left, null);
40   }
41 
makeRight(B right)42   public static <A, B> Either<A, B> makeRight(B right) {
43     return new Either<>(false, null, right);
44   }
45 
hasLeft()46   public boolean hasLeft() {
47     return hasLeft;
48   }
49 
hasRight()50   public boolean hasRight() {
51     return !hasLeft;
52   }
53 
getLeft()54   public @Nullable A getLeft() {
55     if (!hasLeft()) {
56       throw new IllegalStateException("Either was not left");
57     }
58     return left;
59   }
60 
getRight()61   public @Nullable B getRight() {
62     if (!hasRight()) {
63       throw new IllegalStateException("Either was not right");
64     }
65     return right;
66   }
67 
68   @Override
69   @SuppressWarnings("unchecked")
equals(@ullable Object obj)70   public boolean equals(@Nullable Object obj) {
71     if (!(obj instanceof Either)) {
72       return false;
73     }
74     Either<A, B> either = (Either<A, B>) obj;
75     if (hasLeft()) {
76       return either.hasLeft() && equals(getLeft(), either.getLeft());
77     } else {
78       return either.hasRight() && equals(getRight(), either.getRight());
79     }
80   }
81 
82   /** Compares two List-based Either by (a copy of) their sorted inner List. */
sortedEquals( @ullable Either<List<A>, B> first, @Nullable Either<List<A>, B> second, Comparator<A> comparatorForSorting)83   public static <A, B> boolean sortedEquals(
84       @Nullable Either<List<A>, B> first,
85       @Nullable Either<List<A>, B> second,
86       Comparator<A> comparatorForSorting) {
87     // Only sort if the Lists will actually be compared. This uses final variable "left" rather than
88     // getLeft() (which "could" change between invocations) to satisfy the Nullness Checker.
89     if (first != null
90         && first.hasLeft()
91         && first.left != null
92         && second != null
93         && second.hasLeft()
94         && second.left != null) {
95       List<A> sortedFirstLeft = new ArrayList<>(first.left);
96       List<A> sortedSecondLeft = new ArrayList<>(second.left);
97       Collections.sort(sortedFirstLeft, comparatorForSorting);
98       Collections.sort(sortedSecondLeft, comparatorForSorting);
99       return sortedFirstLeft.equals(sortedSecondLeft);
100     }
101 
102     return equals(first, second);
103   }
104 
105   // Inline definition of Objects.equals() since it's not available on all API levels.
equals(@ullable Object a, @Nullable Object b)106   public static boolean equals(@Nullable Object a, @Nullable Object b) {
107     return (a == b) || (a != null && a.equals(b));
108   }
109 
110   @Override
hashCode()111   public int hashCode() {
112     return Arrays.hashCode(new Object[] {hasLeft, left, right});
113   }
114 }
115