Loading apex/appsearch/framework/java/android/app/appsearch/SearchResults.java +31 −27 Original line number Diff line number Diff line Loading @@ -45,33 +45,35 @@ public class SearchResults implements Closeable { private final IAppSearchManager mService; // The database name to search over. If null, this will search over all database names. @Nullable private final String mDatabaseName; @UserIdInt private final int mUserId; private final String mQueryExpression; private final SearchSpec mSearchSpec; @UserIdInt private final int mUserId; private final Executor mExecutor; private long mNextPageToken; private boolean mIsFirstLoad = true; SearchResults(@NonNull IAppSearchManager service, SearchResults( @NonNull IAppSearchManager service, @Nullable String databaseName, @NonNull String queryExpression, @NonNull SearchSpec searchSpec, @UserIdInt int userId, @NonNull @CallbackExecutor Executor executor) { mService = Objects.requireNonNull(service); mUserId = userId; mDatabaseName = Objects.requireNonNull(databaseName); mDatabaseName = databaseName; mQueryExpression = Objects.requireNonNull(queryExpression); mSearchSpec = Objects.requireNonNull(searchSpec); mUserId = userId; mExecutor = Objects.requireNonNull(executor); } Loading @@ -90,11 +92,14 @@ public class SearchResults implements Closeable { if (mIsFirstLoad) { mIsFirstLoad = false; if (mDatabaseName == null) { // Global query, there's no one package-database combination to check. mService.globalQuery(mQueryExpression, mSearchSpec.getBundle(), mUserId, wrapCallback(callback)); } else { mService.query(mDatabaseName, mQueryExpression, mSearchSpec.getBundle(), mUserId, wrapCallback(callback)); // Normal local query, pass in specified database. mService.query( mDatabaseName, mQueryExpression, mSearchSpec.getBundle(), mUserId, wrapCallback(callback)); } } else { mService.getNextPage(mNextPageToken, mUserId, wrapCallback(callback)); Loading @@ -104,31 +109,13 @@ public class SearchResults implements Closeable { } } private void invokeCallback(AppSearchResult result, @NonNull Consumer<AppSearchResult<List<SearchResult>>> callback) { if (result.isSuccess()) { try { SearchResultPage searchResultPage = new SearchResultPage((Bundle) result.getResultValue()); mNextPageToken = searchResultPage.getNextPageToken(); callback.accept(AppSearchResult.newSuccessfulResult( searchResultPage.getResults())); } catch (Throwable t) { callback.accept(AppSearchResult.throwableToFailedResult(t)); } } else { callback.accept(result); } } @Override public void close() { mExecutor.execute(() -> { try { mService.invalidateNextPageToken(mNextPageToken, mUserId); } catch (RemoteException e) { Log.d(TAG, "Unable to close the SearchResults", e); } }); } private IAppSearchResultCallback wrapCallback( Loading @@ -139,4 +126,21 @@ public class SearchResults implements Closeable { } }; } private void invokeCallback(AppSearchResult result, @NonNull Consumer<AppSearchResult<List<SearchResult>>> callback) { if (result.isSuccess()) { try { SearchResultPage searchResultPage = new SearchResultPage((Bundle) result.getResultValue()); mNextPageToken = searchResultPage.getNextPageToken(); callback.accept(AppSearchResult.newSuccessfulResult( searchResultPage.getResults())); } catch (Throwable t) { callback.accept(AppSearchResult.throwableToFailedResult(t)); } } else { callback.accept(result); } } } apex/appsearch/framework/java/external/android/app/appsearch/SearchSpec.java +140 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.annotation.SuppressLint; import android.app.appsearch.exceptions.AppSearchException; import android.app.appsearch.exceptions.IllegalSearchSpecException; import android.os.Bundle; import android.util.ArrayMap; import com.android.internal.util.Preconditions; Loading @@ -33,6 +34,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; /** * This class represents the specification logic for AppSearch. It can be used to set the type of Loading @@ -40,6 +43,15 @@ import java.util.List; */ // TODO(sidchhabra) : AddResultSpec fields for Snippets etc. public final class SearchSpec { /** * Schema type to be used in {@link SearchSpec.Builder#addProjectionTypePropertyPath} to apply * property paths to all results, excepting any types that have had their own, specific property * paths set. * * @hide */ public static final String PROJECTION_SCHEMA_TYPE_WILDCARD = "*"; static final String TERM_MATCH_TYPE_FIELD = "termMatchType"; static final String SCHEMA_TYPE_FIELD = "schemaType"; static final String NAMESPACE_FIELD = "namespace"; Loading @@ -49,6 +61,7 @@ public final class SearchSpec { static final String SNIPPET_COUNT_FIELD = "snippetCount"; static final String SNIPPET_COUNT_PER_PROPERTY_FIELD = "snippetCountPerProperty"; static final String MAX_SNIPPET_FIELD = "maxSnippet"; static final String PROJECTION_TYPE_PROPERTY_PATHS_FIELD = "projectionTypeFieldMasks"; /** @hide */ public static final int DEFAULT_NUM_PER_PAGE = 10; Loading Loading @@ -206,12 +219,35 @@ public final class SearchSpec { return mBundle.getInt(MAX_SNIPPET_FIELD); } /** * Returns a map from schema type to property paths to be used for projection. * * <p>If the map is empty, then all properties will be retrieved for all results. * * <p>Calling this function repeatedly is inefficient. Prefer to retain the Map returned by this * function, rather than calling it multiple times. * * @hide */ @NonNull public Map<String, List<String>> getProjectionTypePropertyPaths() { Bundle typePropertyPathsBundle = mBundle.getBundle(PROJECTION_TYPE_PROPERTY_PATHS_FIELD); Set<String> schemaTypes = typePropertyPathsBundle.keySet(); Map<String, List<String>> typePropertyPathsMap = new ArrayMap<>(schemaTypes.size()); for (String schemaType : schemaTypes) { typePropertyPathsMap.put( schemaType, typePropertyPathsBundle.getStringArrayList(schemaType)); } return typePropertyPathsMap; } /** Builder for {@link SearchSpec objects}. */ public static final class Builder { private final Bundle mBundle; private final ArrayList<String> mSchemaTypes = new ArrayList<>(); private final ArrayList<String> mNamespaces = new ArrayList<>(); private final Bundle mProjectionTypePropertyMasks = new Bundle(); private boolean mBuilt = false; /** Creates a new {@link SearchSpec.Builder}. */ Loading Loading @@ -385,6 +421,109 @@ public final class SearchSpec { return this; } /** * Adds property paths for the specified type to be used for projection. If property paths * are added for a type, then only the properties referred to will be retrieved for results * of that type. If a property path that is specified isn't present in a result, it will be * ignored for that result. Property paths cannot be null. * * <p>If no property paths are added for a particular type, then all properties of results * of that type will be retrieved. * * <p>If property path is added for the {@link SearchSpec#PROJECTION_SCHEMA_TYPE_WILDCARD}, * then those property paths will apply to all results, excepting any types that have their * own, specific property paths set. * * <p>Suppose the following document is in the index. * * <pre>{@code * Email: Document { * sender: Document { * name: "Mr. Person" * email: "mrperson123@google.com" * } * recipients: [ * Document { * name: "John Doe" * email: "johndoe123@google.com" * } * Document { * name: "Jane Doe" * email: "janedoe123@google.com" * } * ] * subject: "IMPORTANT" * body: "Limited time offer!" * } * }</pre> * * <p>Then, suppose that a query for "important" is issued with the following projection * type property paths: * * <pre>{@code * {schemaType: "Email", ["subject", "sender.name", "recipients.name"]} * }</pre> * * <p>The above document will be returned as: * * <pre>{@code * Email: Document { * sender: Document { * name: "Mr. Body" * } * recipients: [ * Document { * name: "John Doe" * } * Document { * name: "Jane Doe" * } * ] * subject: "IMPORTANT" * } * }</pre> * * @hide */ @NonNull public SearchSpec.Builder addProjectionTypePropertyPaths( @NonNull String schemaType, @NonNull String... propertyPaths) { Preconditions.checkNotNull(propertyPaths); return addProjectionTypePropertyPaths(schemaType, Arrays.asList(propertyPaths)); } /** * Adds property paths for the specified type to be used for projection. If property paths * are added for a type, then only the properties referred to will be retrieved for results * of that type. If a property path that is specified isn't present in a result, it will be * ignored for that result. Property paths cannot be null. * * <p>If no property paths are added for a particular type, then all properties of results * of that type will be retrieved. * * <p>If property path is added for the {@link SearchSpec#PROJECTION_SCHEMA_TYPE_WILDCARD}, * then those property paths will apply to all results, excepting any types that have their * own, specific property paths set. * * <p>{@see SearchSpec.Builder#addProjectionTypePropertyPath(String, String...)} * * @hide */ @NonNull public SearchSpec.Builder addProjectionTypePropertyPaths( @NonNull String schemaType, @NonNull Collection<String> propertyPaths) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkNotNull(schemaType); Preconditions.checkNotNull(propertyPaths); ArrayList<String> propertyPathsArrayList = new ArrayList<>(propertyPaths.size()); for (String propertyPath : propertyPaths) { Preconditions.checkNotNull(propertyPath); propertyPathsArrayList.add(propertyPath); } mProjectionTypePropertyMasks.putStringArrayList(schemaType, propertyPathsArrayList); return this; } /** * Constructs a new {@link SearchSpec} from the contents of this builder. * Loading @@ -398,6 +537,7 @@ public final class SearchSpec { } mBundle.putStringArrayList(NAMESPACE_FIELD, mNamespaces); mBundle.putStringArrayList(SCHEMA_TYPE_FIELD, mSchemaTypes); mBundle.putBundle(PROJECTION_TYPE_PROPERTY_PATHS_FIELD, mProjectionTypePropertyMasks); mBuilt = true; return new SearchSpec(mBundle); } Loading apex/appsearch/synced_jetpack_changeid.txt +1 −1 Original line number Diff line number Diff line I0577839bfddf95a555399df441d317b00c7c7c48 Idd770a064edfeb6dc648571fc6706c087b8e605a apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShimImpl.java +3 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.app.appsearch.AppSearchManager; import android.app.appsearch.AppSearchResult; import android.app.appsearch.GlobalSearchSession; import android.app.appsearch.GlobalSearchSessionShim; import android.app.appsearch.SearchResults; import android.app.appsearch.SearchResultsShim; import android.app.appsearch.SearchSpec; Loading @@ -40,7 +41,7 @@ import java.util.concurrent.Executors; * a consistent interface. * @hide */ public class GlobalSearchSessionShimImpl { public class GlobalSearchSessionShimImpl implements GlobalSearchSessionShim { private final GlobalSearchSession mGlobalSearchSession; private final ExecutorService mExecutor; Loading @@ -64,6 +65,7 @@ public class GlobalSearchSessionShimImpl { } @NonNull @Override public SearchResultsShim query( @NonNull String queryExpression, @NonNull SearchSpec searchSpec) { SearchResults searchResults = Loading apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java +4 −5 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.appsearch.testing; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import android.app.appsearch.AppSearchBatchResult; import android.app.appsearch.AppSearchSessionShim; Loading @@ -25,8 +26,6 @@ import android.app.appsearch.GetByUriRequest; import android.app.appsearch.SearchResult; import android.app.appsearch.SearchResultsShim; import junit.framework.AssertionFailedError; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Future; Loading @@ -36,9 +35,9 @@ public class AppSearchTestUtils { public static <K, V> AppSearchBatchResult<K, V> checkIsBatchResultSuccess( Future<AppSearchBatchResult<K, V>> future) throws Exception { AppSearchBatchResult<K, V> result = future.get(); if (!result.isSuccess()) { throw new AssertionFailedError("AppSearchBatchResult not successful: " + result); } assertWithMessage("AppSearchBatchResult not successful: " + result) .that(result.isSuccess()) .isTrue(); return result; } Loading Loading
apex/appsearch/framework/java/android/app/appsearch/SearchResults.java +31 −27 Original line number Diff line number Diff line Loading @@ -45,33 +45,35 @@ public class SearchResults implements Closeable { private final IAppSearchManager mService; // The database name to search over. If null, this will search over all database names. @Nullable private final String mDatabaseName; @UserIdInt private final int mUserId; private final String mQueryExpression; private final SearchSpec mSearchSpec; @UserIdInt private final int mUserId; private final Executor mExecutor; private long mNextPageToken; private boolean mIsFirstLoad = true; SearchResults(@NonNull IAppSearchManager service, SearchResults( @NonNull IAppSearchManager service, @Nullable String databaseName, @NonNull String queryExpression, @NonNull SearchSpec searchSpec, @UserIdInt int userId, @NonNull @CallbackExecutor Executor executor) { mService = Objects.requireNonNull(service); mUserId = userId; mDatabaseName = Objects.requireNonNull(databaseName); mDatabaseName = databaseName; mQueryExpression = Objects.requireNonNull(queryExpression); mSearchSpec = Objects.requireNonNull(searchSpec); mUserId = userId; mExecutor = Objects.requireNonNull(executor); } Loading @@ -90,11 +92,14 @@ public class SearchResults implements Closeable { if (mIsFirstLoad) { mIsFirstLoad = false; if (mDatabaseName == null) { // Global query, there's no one package-database combination to check. mService.globalQuery(mQueryExpression, mSearchSpec.getBundle(), mUserId, wrapCallback(callback)); } else { mService.query(mDatabaseName, mQueryExpression, mSearchSpec.getBundle(), mUserId, wrapCallback(callback)); // Normal local query, pass in specified database. mService.query( mDatabaseName, mQueryExpression, mSearchSpec.getBundle(), mUserId, wrapCallback(callback)); } } else { mService.getNextPage(mNextPageToken, mUserId, wrapCallback(callback)); Loading @@ -104,31 +109,13 @@ public class SearchResults implements Closeable { } } private void invokeCallback(AppSearchResult result, @NonNull Consumer<AppSearchResult<List<SearchResult>>> callback) { if (result.isSuccess()) { try { SearchResultPage searchResultPage = new SearchResultPage((Bundle) result.getResultValue()); mNextPageToken = searchResultPage.getNextPageToken(); callback.accept(AppSearchResult.newSuccessfulResult( searchResultPage.getResults())); } catch (Throwable t) { callback.accept(AppSearchResult.throwableToFailedResult(t)); } } else { callback.accept(result); } } @Override public void close() { mExecutor.execute(() -> { try { mService.invalidateNextPageToken(mNextPageToken, mUserId); } catch (RemoteException e) { Log.d(TAG, "Unable to close the SearchResults", e); } }); } private IAppSearchResultCallback wrapCallback( Loading @@ -139,4 +126,21 @@ public class SearchResults implements Closeable { } }; } private void invokeCallback(AppSearchResult result, @NonNull Consumer<AppSearchResult<List<SearchResult>>> callback) { if (result.isSuccess()) { try { SearchResultPage searchResultPage = new SearchResultPage((Bundle) result.getResultValue()); mNextPageToken = searchResultPage.getNextPageToken(); callback.accept(AppSearchResult.newSuccessfulResult( searchResultPage.getResults())); } catch (Throwable t) { callback.accept(AppSearchResult.throwableToFailedResult(t)); } } else { callback.accept(result); } } }
apex/appsearch/framework/java/external/android/app/appsearch/SearchSpec.java +140 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.annotation.SuppressLint; import android.app.appsearch.exceptions.AppSearchException; import android.app.appsearch.exceptions.IllegalSearchSpecException; import android.os.Bundle; import android.util.ArrayMap; import com.android.internal.util.Preconditions; Loading @@ -33,6 +34,8 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; /** * This class represents the specification logic for AppSearch. It can be used to set the type of Loading @@ -40,6 +43,15 @@ import java.util.List; */ // TODO(sidchhabra) : AddResultSpec fields for Snippets etc. public final class SearchSpec { /** * Schema type to be used in {@link SearchSpec.Builder#addProjectionTypePropertyPath} to apply * property paths to all results, excepting any types that have had their own, specific property * paths set. * * @hide */ public static final String PROJECTION_SCHEMA_TYPE_WILDCARD = "*"; static final String TERM_MATCH_TYPE_FIELD = "termMatchType"; static final String SCHEMA_TYPE_FIELD = "schemaType"; static final String NAMESPACE_FIELD = "namespace"; Loading @@ -49,6 +61,7 @@ public final class SearchSpec { static final String SNIPPET_COUNT_FIELD = "snippetCount"; static final String SNIPPET_COUNT_PER_PROPERTY_FIELD = "snippetCountPerProperty"; static final String MAX_SNIPPET_FIELD = "maxSnippet"; static final String PROJECTION_TYPE_PROPERTY_PATHS_FIELD = "projectionTypeFieldMasks"; /** @hide */ public static final int DEFAULT_NUM_PER_PAGE = 10; Loading Loading @@ -206,12 +219,35 @@ public final class SearchSpec { return mBundle.getInt(MAX_SNIPPET_FIELD); } /** * Returns a map from schema type to property paths to be used for projection. * * <p>If the map is empty, then all properties will be retrieved for all results. * * <p>Calling this function repeatedly is inefficient. Prefer to retain the Map returned by this * function, rather than calling it multiple times. * * @hide */ @NonNull public Map<String, List<String>> getProjectionTypePropertyPaths() { Bundle typePropertyPathsBundle = mBundle.getBundle(PROJECTION_TYPE_PROPERTY_PATHS_FIELD); Set<String> schemaTypes = typePropertyPathsBundle.keySet(); Map<String, List<String>> typePropertyPathsMap = new ArrayMap<>(schemaTypes.size()); for (String schemaType : schemaTypes) { typePropertyPathsMap.put( schemaType, typePropertyPathsBundle.getStringArrayList(schemaType)); } return typePropertyPathsMap; } /** Builder for {@link SearchSpec objects}. */ public static final class Builder { private final Bundle mBundle; private final ArrayList<String> mSchemaTypes = new ArrayList<>(); private final ArrayList<String> mNamespaces = new ArrayList<>(); private final Bundle mProjectionTypePropertyMasks = new Bundle(); private boolean mBuilt = false; /** Creates a new {@link SearchSpec.Builder}. */ Loading Loading @@ -385,6 +421,109 @@ public final class SearchSpec { return this; } /** * Adds property paths for the specified type to be used for projection. If property paths * are added for a type, then only the properties referred to will be retrieved for results * of that type. If a property path that is specified isn't present in a result, it will be * ignored for that result. Property paths cannot be null. * * <p>If no property paths are added for a particular type, then all properties of results * of that type will be retrieved. * * <p>If property path is added for the {@link SearchSpec#PROJECTION_SCHEMA_TYPE_WILDCARD}, * then those property paths will apply to all results, excepting any types that have their * own, specific property paths set. * * <p>Suppose the following document is in the index. * * <pre>{@code * Email: Document { * sender: Document { * name: "Mr. Person" * email: "mrperson123@google.com" * } * recipients: [ * Document { * name: "John Doe" * email: "johndoe123@google.com" * } * Document { * name: "Jane Doe" * email: "janedoe123@google.com" * } * ] * subject: "IMPORTANT" * body: "Limited time offer!" * } * }</pre> * * <p>Then, suppose that a query for "important" is issued with the following projection * type property paths: * * <pre>{@code * {schemaType: "Email", ["subject", "sender.name", "recipients.name"]} * }</pre> * * <p>The above document will be returned as: * * <pre>{@code * Email: Document { * sender: Document { * name: "Mr. Body" * } * recipients: [ * Document { * name: "John Doe" * } * Document { * name: "Jane Doe" * } * ] * subject: "IMPORTANT" * } * }</pre> * * @hide */ @NonNull public SearchSpec.Builder addProjectionTypePropertyPaths( @NonNull String schemaType, @NonNull String... propertyPaths) { Preconditions.checkNotNull(propertyPaths); return addProjectionTypePropertyPaths(schemaType, Arrays.asList(propertyPaths)); } /** * Adds property paths for the specified type to be used for projection. If property paths * are added for a type, then only the properties referred to will be retrieved for results * of that type. If a property path that is specified isn't present in a result, it will be * ignored for that result. Property paths cannot be null. * * <p>If no property paths are added for a particular type, then all properties of results * of that type will be retrieved. * * <p>If property path is added for the {@link SearchSpec#PROJECTION_SCHEMA_TYPE_WILDCARD}, * then those property paths will apply to all results, excepting any types that have their * own, specific property paths set. * * <p>{@see SearchSpec.Builder#addProjectionTypePropertyPath(String, String...)} * * @hide */ @NonNull public SearchSpec.Builder addProjectionTypePropertyPaths( @NonNull String schemaType, @NonNull Collection<String> propertyPaths) { Preconditions.checkState(!mBuilt, "Builder has already been used"); Preconditions.checkNotNull(schemaType); Preconditions.checkNotNull(propertyPaths); ArrayList<String> propertyPathsArrayList = new ArrayList<>(propertyPaths.size()); for (String propertyPath : propertyPaths) { Preconditions.checkNotNull(propertyPath); propertyPathsArrayList.add(propertyPath); } mProjectionTypePropertyMasks.putStringArrayList(schemaType, propertyPathsArrayList); return this; } /** * Constructs a new {@link SearchSpec} from the contents of this builder. * Loading @@ -398,6 +537,7 @@ public final class SearchSpec { } mBundle.putStringArrayList(NAMESPACE_FIELD, mNamespaces); mBundle.putStringArrayList(SCHEMA_TYPE_FIELD, mSchemaTypes); mBundle.putBundle(PROJECTION_TYPE_PROPERTY_PATHS_FIELD, mProjectionTypePropertyMasks); mBuilt = true; return new SearchSpec(mBundle); } Loading
apex/appsearch/synced_jetpack_changeid.txt +1 −1 Original line number Diff line number Diff line I0577839bfddf95a555399df441d317b00c7c7c48 Idd770a064edfeb6dc648571fc6706c087b8e605a
apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShimImpl.java +3 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.app.appsearch.AppSearchManager; import android.app.appsearch.AppSearchResult; import android.app.appsearch.GlobalSearchSession; import android.app.appsearch.GlobalSearchSessionShim; import android.app.appsearch.SearchResults; import android.app.appsearch.SearchResultsShim; import android.app.appsearch.SearchSpec; Loading @@ -40,7 +41,7 @@ import java.util.concurrent.Executors; * a consistent interface. * @hide */ public class GlobalSearchSessionShimImpl { public class GlobalSearchSessionShimImpl implements GlobalSearchSessionShim { private final GlobalSearchSession mGlobalSearchSession; private final ExecutorService mExecutor; Loading @@ -64,6 +65,7 @@ public class GlobalSearchSessionShimImpl { } @NonNull @Override public SearchResultsShim query( @NonNull String queryExpression, @NonNull SearchSpec searchSpec) { SearchResults searchResults = Loading
apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java +4 −5 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.appsearch.testing; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import android.app.appsearch.AppSearchBatchResult; import android.app.appsearch.AppSearchSessionShim; Loading @@ -25,8 +26,6 @@ import android.app.appsearch.GetByUriRequest; import android.app.appsearch.SearchResult; import android.app.appsearch.SearchResultsShim; import junit.framework.AssertionFailedError; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Future; Loading @@ -36,9 +35,9 @@ public class AppSearchTestUtils { public static <K, V> AppSearchBatchResult<K, V> checkIsBatchResultSuccess( Future<AppSearchBatchResult<K, V>> future) throws Exception { AppSearchBatchResult<K, V> result = future.get(); if (!result.isSuccess()) { throw new AssertionFailedError("AppSearchBatchResult not successful: " + result); } assertWithMessage("AppSearchBatchResult not successful: " + result) .that(result.isSuccess()) .isTrue(); return result; } Loading