diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java index b38bb0515e96b..67fa6c89ad4ad 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java @@ -22,9 +22,9 @@ import android.os.Bundle; import android.os.RemoteException; import com.android.internal.infra.AndroidFuture; +import com.android.internal.util.Preconditions; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; @@ -96,46 +96,23 @@ public class AppSearchManager { *

It is a no-op to set the same schema as has been previously set; this is handled * efficiently. * - * @param schemas The schema configs for the types used by the calling app. + * @param request The schema update request. * @return the result of performing this operation. * * @hide */ @NonNull - public AppSearchResult setSchema(@NonNull AppSearchSchema... schemas) { - return setSchema(Arrays.asList(schemas), /*forceOverride=*/false); - } - - /** - * Sets the schema being used by documents provided to the {@link #putDocuments} method. - * - *

This method is similar to {@link #setSchema(AppSearchSchema...)}, except for the - * {@code forceOverride} parameter. If a backwards-incompatible schema is specified but the - * {@code forceOverride} parameter is set to {@code true}, instead of returning an - * {@link AppSearchResult} with the {@link AppSearchResult#RESULT_INVALID_SCHEMA} code, all - * documents which are not compatible with the new schema will be deleted and the incompatible - * schema will be applied. - * - * @param schemas The schema configs for the types used by the calling app. - * @param forceOverride Whether to force the new schema to be applied even if there are - * incompatible changes versus the previously set schema. Documents which are incompatible - * with the new schema will be deleted. - * @return the result of performing this operation. - * - * @hide - */ - @NonNull - public AppSearchResult setSchema( - @NonNull List schemas, boolean forceOverride) { + public AppSearchResult setSchema(@NonNull SetSchemaRequest request) { + Preconditions.checkNotNull(request); // TODO: This should use com.android.internal.infra.RemoteStream or another mechanism to // avoid binder limits. - List schemaBundles = new ArrayList<>(schemas.size()); - for (AppSearchSchema schema : schemas) { + List schemaBundles = new ArrayList<>(request.getSchemas().size()); + for (AppSearchSchema schema : request.getSchemas()) { schemaBundles.add(schema.getBundle()); } AndroidFuture future = new AndroidFuture<>(); try { - mService.setSchema(schemaBundles, forceOverride, future); + mService.setSchema(schemaBundles, request.isForceOverride(), future); } catch (RemoteException e) { future.completeExceptionally(e); } @@ -151,19 +128,20 @@ public class AppSearchManager { *

Each {@link GenericDocument}'s {@code schemaType} field must be set to the name of a * schema type previously registered via the {@link #setSchema} method. * - * @param documents {@link GenericDocument}s that need to be indexed. - * @return An {@link AppSearchBatchResult} mapping the document URIs to {@link Void} if they - * were successfully indexed, or a {@link Throwable} describing the failure if they could - * not be indexed. + * @param request {@link PutDocumentsRequest} containing documents to be indexed + * @return The pending result of performing this operation. The keys of the returned + * {@link AppSearchBatchResult} are the URIs of the input documents. The values are + * {@code null} if they were successfully indexed, or a failed {@link AppSearchResult} + * otherwise. * @hide */ - public AppSearchBatchResult putDocuments( - @NonNull List documents) { + public AppSearchBatchResult putDocuments(@NonNull PutDocumentsRequest request) { // TODO(b/146386470): Transmit these documents as a RemoteStream instead of sending them in // one big list. + List documents = request.getDocuments(); List documentBundles = new ArrayList<>(documents.size()); - for (GenericDocument document : documents) { - documentBundles.add(document.getBundle()); + for (int i = 0; i < documents.size(); i++) { + documentBundles.add(documents.get(i).getBundle()); } AndroidFuture future = new AndroidFuture<>(); try { @@ -180,15 +158,18 @@ public class AppSearchManager { *

You should not call this method directly; instead, use the * {@code AppSearch#getDocuments()} API provided by JetPack. * - * @param uris URIs of the documents to look up. - * @return An {@link AppSearchBatchResult} mapping the document URIs to - * {@link GenericDocument} values if they were successfully retrieved, a {@code null} - * failure if they were not found, or a {@link Throwable} failure describing the problem if - * an error occurred. + * @param request {@link GetByUriRequest} containing URIs to be retrieved. + * @return The pending result of performing this operation. The keys of the returned + * {@link AppSearchBatchResult} are the input URIs. The values are the returned + * {@link GenericDocument}s on success, or a failed {@link AppSearchResult} otherwise. + * URIs that are not found will return a failed {@link AppSearchResult} with a result code + * of {@link AppSearchResult#RESULT_NOT_FOUND}. */ - public AppSearchBatchResult getDocuments(@NonNull List uris) { + public AppSearchBatchResult getByUri( + @NonNull GetByUriRequest request) { // TODO(b/146386470): Transmit the result documents as a RemoteStream instead of sending // them in one big list. + List uris = new ArrayList<>(request.getUris()); AndroidFuture future = new AndroidFuture<>(); try { mService.getDocuments(uris, future); @@ -300,12 +281,15 @@ public class AppSearchManager { *

You should not call this method directly; instead, use the {@code AppSearch#delete()} API * provided by JetPack. * - * @param uris URIs of the documents to delete - * @return An {@link AppSearchBatchResult} mapping each URI to a {@code null} success if - * deletion was successful, to a {@code null} failure if the document did not exist, or to a - * {@code throwable} failure if deletion failed for another reason. + * @param request Request containing URIs to be removed. + * @return The pending result of performing this operation. The keys of the returned + * {@link AppSearchBatchResult} are the input URIs. The values are {@code null} on success, + * or a failed {@link AppSearchResult} otherwise. URIs that are not found will return a + * failed {@link AppSearchResult} with a result code of + * {@link AppSearchResult#RESULT_NOT_FOUND}. */ - public AppSearchBatchResult delete(@NonNull List uris) { + public AppSearchBatchResult removeByUri(@NonNull RemoveByUriRequest request) { + List uris = new ArrayList<>(request.getUris()); AndroidFuture future = new AndroidFuture<>(); try { mService.delete(uris, future); diff --git a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java new file mode 100644 index 0000000000000..3c0e746f92ab3 --- /dev/null +++ b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java @@ -0,0 +1,100 @@ +/* + * 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.util.ArraySet; +import com.android.internal.util.Preconditions; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Set; + +/** + * Encapsulates a request to retrieve documents by namespace and URI. + * + * @see AppSearchManager#getByUri + * @hide + */ +public final class GetByUriRequest { + private final String mNamespace; + private final Set mUris; + + GetByUriRequest(@NonNull String namespace, @NonNull Set uris) { + mNamespace = namespace; + mUris = uris; + } + + /** @hide */ + + @NonNull + public String getNamespace() { + return mNamespace; + } + + /** @hide */ + + @NonNull + public Set getUris() { + return mUris; + } + + /** Builder for {@link GetByUriRequest} objects. */ + public static final class Builder { + private String mNamespace = GenericDocument.DEFAULT_NAMESPACE; + private final Set mUris = new ArraySet<>(); + private boolean mBuilt = false; + + /** + * Sets which namespace these documents will be retrieved from. + * + *

If this is not set, it defaults to {@link GenericDocument#DEFAULT_NAMESPACE}. + */ + @NonNull + public Builder setNamespace(@NonNull String namespace) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkNotNull(namespace); + mNamespace = namespace; + return this; + } + + /** Adds one or more URIs to the request. */ + @NonNull + public Builder addUris(@NonNull String... uris) { + Preconditions.checkNotNull(uris); + return addUris(Arrays.asList(uris)); + } + + /** Adds one or more URIs to the request. */ + @NonNull + public Builder addUris(@NonNull Collection uris) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkNotNull(uris); + mUris.addAll(uris); + return this; + } + + /** Builds a new {@link GetByUriRequest}. */ + @NonNull + public GetByUriRequest build() { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + mBuilt = true; + return new GetByUriRequest(mNamespace, mUris); + } + } +} diff --git a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java new file mode 100644 index 0000000000000..7e97542c6f02c --- /dev/null +++ b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java @@ -0,0 +1,77 @@ +/* + * 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 com.android.internal.util.Preconditions; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * Encapsulates a request to index a document into an {@link AppSearchManager} database. + * + * @see AppSearchManager#putDocuments + * @hide + */ +public final class PutDocumentsRequest { + private final List mDocuments; + + PutDocumentsRequest(List documents) { + mDocuments = documents; + } + + /** @hide */ + + @NonNull + public List getDocuments() { + return mDocuments; + } + + /** Builder for {@link PutDocumentsRequest} objects. */ + public static final class Builder { + private final List mDocuments = new ArrayList<>(); + private boolean mBuilt = false; + + /** Adds one or more documents to the request. */ + @NonNull + public Builder addGenericDocument(@NonNull GenericDocument... documents) { + Preconditions.checkNotNull(documents); + return addGenericDocument(Arrays.asList(documents)); + } + + /** Adds one or more documents to the request. */ + @NonNull + public Builder addGenericDocument(@NonNull Collection documents) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkNotNull(documents); + mDocuments.addAll(documents); + return this; + } + + /** Builds a new {@link PutDocumentsRequest}. */ + @NonNull + public PutDocumentsRequest build() { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + mBuilt = true; + return new PutDocumentsRequest(mDocuments); + } + } +} diff --git a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java new file mode 100644 index 0000000000000..a047041a3082e --- /dev/null +++ b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java @@ -0,0 +1,100 @@ +/* + * 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.util.ArraySet; +import com.android.internal.util.Preconditions; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Set; + +/** + * Encapsulates a request to remove documents by namespace and URI. + * + * @see AppSearchManager#removeByUri + * @hide + */ +public final class RemoveByUriRequest { + private final String mNamespace; + private final Set mUris; + + RemoveByUriRequest(String namespace, Set uris) { + mNamespace = namespace; + mUris = uris; + } + + /** @hide */ + + @NonNull + public String getNamespace() { + return mNamespace; + } + + /** @hide */ + + @NonNull + public Set getUris() { + return mUris; + } + + /** Builder for {@link RemoveByUriRequest} objects. */ + public static final class Builder { + private String mNamespace = GenericDocument.DEFAULT_NAMESPACE; + private final Set mUris = new ArraySet<>(); + private boolean mBuilt = false; + + /** + * Sets which namespace these documents will be removed from. + * + *

If this is not set, it defaults to {@link GenericDocument#DEFAULT_NAMESPACE}. + */ + @NonNull + public Builder setNamespace(@NonNull String namespace) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkNotNull(namespace); + mNamespace = namespace; + return this; + } + + /** Adds one or more URIs to the request. */ + @NonNull + public Builder addUris(@NonNull String... uris) { + Preconditions.checkNotNull(uris); + return addUris(Arrays.asList(uris)); + } + + /** Adds one or more URIs to the request. */ + @NonNull + public Builder addUris(@NonNull Collection uris) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkNotNull(uris); + mUris.addAll(uris); + return this; + } + + /** Builds a new {@link RemoveByUriRequest}. */ + @NonNull + public RemoveByUriRequest build() { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + mBuilt = true; + return new RemoveByUriRequest(mNamespace, mUris); + } + } +} diff --git a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java new file mode 100644 index 0000000000000..b2e9d469764d5 --- /dev/null +++ b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java @@ -0,0 +1,101 @@ +/* + * 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.util.ArraySet; + +import com.android.internal.util.Preconditions; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Set; + +/** + * Encapsulates a request to update the schema of an {@link AppSearchManager} database. + * + * @see AppSearchManager#setSchema + * @hide + */ +public final class SetSchemaRequest { + private final Set mSchemas; + private final boolean mForceOverride; + + SetSchemaRequest(Set schemas, boolean forceOverride) { + mSchemas = schemas; + mForceOverride = forceOverride; + } + + /** @hide */ + + @NonNull + public Set getSchemas() { + return mSchemas; + } + + /** @hide */ + + public boolean isForceOverride() { + return mForceOverride; + } + + /** Builder for {@link SetSchemaRequest} objects. */ + public static final class Builder { + private final Set mSchemas = new ArraySet<>(); + private boolean mForceOverride = false; + private boolean mBuilt = false; + + /** Adds one or more types to the schema. */ + @NonNull + public Builder addSchema(@NonNull AppSearchSchema... schemas) { + Preconditions.checkNotNull(schemas); + return addSchema(Arrays.asList(schemas)); + } + + /** Adds one or more types to the schema. */ + @NonNull + public Builder addSchema(@NonNull Collection schemas) { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + Preconditions.checkNotNull(schemas); + mSchemas.addAll(schemas); + return this; + } + + /** + * Configures the {@link SetSchemaRequest} to delete any existing documents that don't + * follow the new schema. + * + *

By default, this is {@code false} and schema incompatibility causes the + * {@link AppSearchManager#setSchema} call to fail. + * + * @see AppSearchManager#setSchema + */ + @NonNull + public Builder setForceOverride(boolean forceOverride) { + mForceOverride = forceOverride; + return this; + } + + /** Builds a new {@link SetSchemaRequest}. */ + @NonNull + public SetSchemaRequest build() { + Preconditions.checkState(!mBuilt, "Builder has already been used"); + mBuilt = true; + return new SetSchemaRequest(mSchemas, mForceOverride); + } + } +}