/* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.appsearch; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.appsearch.annotation.CanIgnoreReturnValue; import android.util.ArrayMap; import java.util.Collections; import java.util.Map; import java.util.Objects; /** * Provides results for AppSearch batch operations which encompass multiple documents. * *

Individual results of a batch operation are separated into two maps: one for successes and one * for failures. For successes, {@link #getSuccesses()} will return a map of keys to instances of * the value type. For failures, {@link #getFailures()} will return a map of keys to {@link * AppSearchResult} objects. * *

Alternatively, {@link #getAll()} returns a map of keys to {@link AppSearchResult} objects for * both successes and failures. * * @param The type of the keys for which the results will be reported. * @param The type of the result objects for successful results. * @see AppSearchSession#put * @see AppSearchSession#getByDocumentId * @see AppSearchSession#remove */ public final class AppSearchBatchResult { @NonNull private final Map mSuccesses; @NonNull private final Map> mFailures; @NonNull private final Map> mAll; AppSearchBatchResult( @NonNull Map successes, @NonNull Map> failures, @NonNull Map> all) { mSuccesses = Objects.requireNonNull(successes); mFailures = Objects.requireNonNull(failures); mAll = Objects.requireNonNull(all); } /** Returns {@code true} if this {@link AppSearchBatchResult} has no failures. */ public boolean isSuccess() { return mFailures.isEmpty(); } /** * Returns a {@link Map} of keys mapped to instances of the value type for all successful * individual results. * *

Example: {@link AppSearchSession#getByDocumentId} returns an {@link AppSearchBatchResult}. * Each key (the document ID, of {@code String} type) will map to a {@link GenericDocument} * object. * *

The values of the {@link Map} will not be {@code null}. */ @NonNull public Map getSuccesses() { return Collections.unmodifiableMap(mSuccesses); } /** * Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all failed * individual results. * *

The values of the {@link Map} will not be {@code null}. */ @NonNull public Map> getFailures() { return Collections.unmodifiableMap(mFailures); } /** * Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all * individual results. * *

The values of the {@link Map} will not be {@code null}. */ @NonNull public Map> getAll() { return Collections.unmodifiableMap(mAll); } /** * Asserts that this {@link AppSearchBatchResult} has no failures. * * @hide */ public void checkSuccess() { if (!isSuccess()) { throw new IllegalStateException("AppSearchBatchResult has failures: " + this); } } @Override @NonNull public String toString() { return "{\n successes: " + mSuccesses + "\n failures: " + mFailures + "\n}"; } /** * Builder for {@link AppSearchBatchResult} objects. * * @param The type of the keys for which the results will be reported. * @param The type of the result objects for successful results. */ public static final class Builder { private ArrayMap mSuccesses = new ArrayMap<>(); private ArrayMap> mFailures = new ArrayMap<>(); private ArrayMap> mAll = new ArrayMap<>(); private boolean mBuilt = false; /** * Associates the {@code key} with the provided successful return value. * *

Any previous mapping for a key, whether success or failure, is deleted. * *

This is a convenience function which is equivalent to {@code setResult(key, * AppSearchResult.newSuccessfulResult(value))}. * * @param key The key to associate the result with; usually corresponds to some identifier * from the input like an ID or name. * @param value An optional value to associate with the successful result of the operation * being performed. */ @CanIgnoreReturnValue @SuppressWarnings("MissingGetterMatchingBuilder") // See getSuccesses @NonNull public Builder setSuccess( @NonNull KeyType key, @Nullable ValueType value) { Objects.requireNonNull(key); resetIfBuilt(); return setResult(key, AppSearchResult.newSuccessfulResult(value)); } /** * Associates the {@code key} with the provided failure code and error message. * *

Any previous mapping for a key, whether success or failure, is deleted. * *

This is a convenience function which is equivalent to {@code setResult(key, * AppSearchResult.newFailedResult(resultCode, errorMessage))}. * * @param key The key to associate the result with; usually corresponds to some identifier * from the input like an ID or name. * @param resultCode One of the constants documented in {@link * AppSearchResult#getResultCode}. * @param errorMessage An optional string describing the reason or nature of the failure. */ @CanIgnoreReturnValue @SuppressWarnings("MissingGetterMatchingBuilder") // See getFailures @NonNull public Builder setFailure( @NonNull KeyType key, @AppSearchResult.ResultCode int resultCode, @Nullable String errorMessage) { Objects.requireNonNull(key); resetIfBuilt(); return setResult(key, AppSearchResult.newFailedResult(resultCode, errorMessage)); } /** * Associates the {@code key} with the provided {@code result}. * *

Any previous mapping for a key, whether success or failure, is deleted. * * @param key The key to associate the result with; usually corresponds to some identifier * from the input like an ID or name. * @param result The result to associate with the key. */ @CanIgnoreReturnValue @SuppressWarnings("MissingGetterMatchingBuilder") // See getAll @NonNull public Builder setResult( @NonNull KeyType key, @NonNull AppSearchResult result) { Objects.requireNonNull(key); Objects.requireNonNull(result); resetIfBuilt(); if (result.isSuccess()) { mSuccesses.put(key, result.getResultValue()); mFailures.remove(key); } else { mFailures.put(key, result); mSuccesses.remove(key); } mAll.put(key, result); return this; } /** * Builds an {@link AppSearchBatchResult} object from the contents of this {@link Builder}. */ @NonNull public AppSearchBatchResult build() { mBuilt = true; return new AppSearchBatchResult<>(mSuccesses, mFailures, mAll); } private void resetIfBuilt() { if (mBuilt) { mSuccesses = new ArrayMap<>(mSuccesses); mFailures = new ArrayMap<>(mFailures); mAll = new ArrayMap<>(mAll); mBuilt = false; } } } }