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