• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 The Android Open Source Project
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 android.app.appsearch;
17 
18 import android.annotation.FlaggedApi;
19 import android.app.appsearch.annotation.CanIgnoreReturnValue;
20 import android.util.ArrayMap;
21 
22 import com.android.appsearch.flags.Flags;
23 
24 import org.jspecify.annotations.NonNull;
25 import org.jspecify.annotations.Nullable;
26 
27 import java.util.Collections;
28 import java.util.Map;
29 import java.util.Objects;
30 
31 /**
32  * Provides results for AppSearch batch operations which encompass multiple documents.
33  *
34  * <p>Individual results of a batch operation are separated into two maps: one for successes and one
35  * for failures. For successes, {@link #getSuccesses()} will return a map of keys to instances of
36  * the value type. For failures, {@link #getFailures()} will return a map of keys to {@link
37  * AppSearchResult} objects.
38  *
39  * <p>Alternatively, {@link #getAll()} returns a map of keys to {@link AppSearchResult} objects for
40  * both successes and failures.
41  *
42  * @param <KeyType> The type of the keys for which the results will be reported.
43  * @param <ValueType> The type of the result objects for successful results.
44  * @see AppSearchSession#put
45  * @see AppSearchSession#getByDocumentId
46  * @see AppSearchSession#remove
47  */
48 public final class AppSearchBatchResult<KeyType, ValueType> {
49     private final @NonNull Map<KeyType, @Nullable ValueType> mSuccesses;
50     private final @NonNull Map<KeyType, AppSearchResult<ValueType>> mFailures;
51     private final @NonNull Map<KeyType, AppSearchResult<ValueType>> mAll;
52 
AppSearchBatchResult( @onNull Map<KeyType, @Nullable ValueType> successes, @NonNull Map<KeyType, AppSearchResult<ValueType>> failures, @NonNull Map<KeyType, AppSearchResult<ValueType>> all)53     AppSearchBatchResult(
54             @NonNull Map<KeyType, @Nullable ValueType> successes,
55             @NonNull Map<KeyType, AppSearchResult<ValueType>> failures,
56             @NonNull Map<KeyType, AppSearchResult<ValueType>> all) {
57         mSuccesses = Objects.requireNonNull(successes);
58         mFailures = Objects.requireNonNull(failures);
59         mAll = Objects.requireNonNull(all);
60     }
61 
62     /** Returns {@code true} if this {@link AppSearchBatchResult} has no failures. */
isSuccess()63     public boolean isSuccess() {
64         return mFailures.isEmpty();
65     }
66 
67     /**
68      * Returns a {@link Map} of keys mapped to instances of the value type for all successful
69      * individual results.
70      *
71      * <p>Example: {@link AppSearchSession#getByDocumentId} returns an {@link AppSearchBatchResult}.
72      * Each key (the document ID, of {@code String} type) will map to a {@link GenericDocument}
73      * object.
74      *
75      * <p>The values of the {@link Map} will not be {@code null}.
76      */
getSuccesses()77     public @NonNull Map<KeyType, ValueType> getSuccesses() {
78         return Collections.unmodifiableMap(mSuccesses);
79     }
80 
81     /**
82      * Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all failed
83      * individual results.
84      *
85      * <p>The values of the {@link Map} will not be {@code null}.
86      */
getFailures()87     public @NonNull Map<KeyType, AppSearchResult<ValueType>> getFailures() {
88         return Collections.unmodifiableMap(mFailures);
89     }
90 
91     /**
92      * Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all
93      * individual results.
94      *
95      * <p>The values of the {@link Map} will not be {@code null}.
96      */
getAll()97     public @NonNull Map<KeyType, AppSearchResult<ValueType>> getAll() {
98         return Collections.unmodifiableMap(mAll);
99     }
100 
101     /**
102      * Asserts that this {@link AppSearchBatchResult} has no failures.
103      *
104      * @hide
105      */
checkSuccess()106     public void checkSuccess() {
107         if (!isSuccess()) {
108             throw new IllegalStateException("AppSearchBatchResult has failures: " + this);
109         }
110     }
111 
112     @Override
toString()113     public @NonNull String toString() {
114         return "{\n  successes: " + mSuccesses + "\n  failures: " + mFailures + "\n}";
115     }
116 
117     /**
118      * Builder for {@link AppSearchBatchResult} objects.
119      *
120      * @param <KeyType> The type of the keys for which the results will be reported.
121      * @param <ValueType> The type of the result objects for successful results.
122      */
123     public static final class Builder<KeyType, ValueType> {
124         private ArrayMap<KeyType, @Nullable ValueType> mSuccesses = new ArrayMap<>();
125         private ArrayMap<KeyType, AppSearchResult<ValueType>> mFailures = new ArrayMap<>();
126         private ArrayMap<KeyType, AppSearchResult<ValueType>> mAll = new ArrayMap<>();
127         private boolean mBuilt = false;
128 
129         /** Creates a new {@link Builder}. */
Builder()130         public Builder() {}
131 
132         /** Creates a new {@link Builder} from the given {@link AppSearchBatchResult}. */
133         @FlaggedApi(Flags.FLAG_ENABLE_ADDITIONAL_BUILDER_COPY_CONSTRUCTORS)
Builder(@onNull AppSearchBatchResult<KeyType, ValueType> appSearchBatchResult)134         public Builder(@NonNull AppSearchBatchResult<KeyType, ValueType> appSearchBatchResult) {
135             mSuccesses.putAll(appSearchBatchResult.mSuccesses);
136             mFailures.putAll(appSearchBatchResult.mFailures);
137             mAll.putAll(appSearchBatchResult.mAll);
138         }
139 
140         /**
141          * Associates the {@code key} with the provided successful return value.
142          *
143          * <p>Any previous mapping for a key, whether success or failure, is deleted.
144          *
145          * <p>This is a convenience function which is equivalent to {@code setResult(key,
146          * AppSearchResult.newSuccessfulResult(value))}.
147          *
148          * @param key The key to associate the result with; usually corresponds to some identifier
149          *     from the input like an ID or name.
150          * @param value An optional value to associate with the successful result of the operation
151          *     being performed.
152          */
153         @CanIgnoreReturnValue
154         @SuppressWarnings("MissingGetterMatchingBuilder") // See getSuccesses
setSuccess( @onNull KeyType key, @Nullable ValueType value)155         public @NonNull Builder<KeyType, ValueType> setSuccess(
156                 @NonNull KeyType key, @Nullable ValueType value) {
157             Objects.requireNonNull(key);
158             resetIfBuilt();
159             return setResult(key, AppSearchResult.newSuccessfulResult(value));
160         }
161 
162         /**
163          * Associates the {@code key} with the provided failure code and error message.
164          *
165          * <p>Any previous mapping for a key, whether success or failure, is deleted.
166          *
167          * <p>This is a convenience function which is equivalent to {@code setResult(key,
168          * AppSearchResult.newFailedResult(resultCode, errorMessage))}.
169          *
170          * @param key The key to associate the result with; usually corresponds to some identifier
171          *     from the input like an ID or name.
172          * @param resultCode One of the constants documented in {@link
173          *     AppSearchResult#getResultCode}.
174          * @param errorMessage An optional string describing the reason or nature of the failure.
175          */
176         @CanIgnoreReturnValue
177         @SuppressWarnings("MissingGetterMatchingBuilder") // See getFailures
setFailure( @onNull KeyType key, @AppSearchResult.ResultCode int resultCode, @Nullable String errorMessage)178         public @NonNull Builder<KeyType, ValueType> setFailure(
179                 @NonNull KeyType key,
180                 @AppSearchResult.ResultCode int resultCode,
181                 @Nullable String errorMessage) {
182             Objects.requireNonNull(key);
183             resetIfBuilt();
184             return setResult(key, AppSearchResult.newFailedResult(resultCode, errorMessage));
185         }
186 
187         /**
188          * Associates the {@code key} with the provided {@code result}.
189          *
190          * <p>Any previous mapping for a key, whether success or failure, is deleted.
191          *
192          * @param key The key to associate the result with; usually corresponds to some identifier
193          *     from the input like an ID or name.
194          * @param result The result to associate with the key.
195          */
196         @CanIgnoreReturnValue
197         @SuppressWarnings("MissingGetterMatchingBuilder") // See getAll
setResult( @onNull KeyType key, @NonNull AppSearchResult<ValueType> result)198         public @NonNull Builder<KeyType, ValueType> setResult(
199                 @NonNull KeyType key, @NonNull AppSearchResult<ValueType> result) {
200             Objects.requireNonNull(key);
201             Objects.requireNonNull(result);
202             resetIfBuilt();
203             if (result.isSuccess()) {
204                 mSuccesses.put(key, result.getResultValue());
205                 mFailures.remove(key);
206             } else {
207                 mFailures.put(key, result);
208                 mSuccesses.remove(key);
209             }
210             mAll.put(key, result);
211             return this;
212         }
213 
214         /**
215          * Builds an {@link AppSearchBatchResult} object from the contents of this {@link Builder}.
216          */
build()217         public @NonNull AppSearchBatchResult<KeyType, ValueType> build() {
218             mBuilt = true;
219             return new AppSearchBatchResult<>(mSuccesses, mFailures, mAll);
220         }
221 
resetIfBuilt()222         private void resetIfBuilt() {
223             if (mBuilt) {
224                 mSuccesses = new ArrayMap<>(mSuccesses);
225                 mFailures = new ArrayMap<>(mFailures);
226                 mAll = new ArrayMap<>(mAll);
227                 mBuilt = false;
228             }
229         }
230     }
231 }
232