Loading apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +5 −1 Original line number Diff line number Diff line Loading @@ -224,7 +224,11 @@ public class AppSearchManager { } AndroidFuture<AppSearchResult> future = new AndroidFuture<>(); try { mService.setSchema(DEFAULT_DATABASE_NAME, schemaBundles, request.isForceOverride(), mService.setSchema( DEFAULT_DATABASE_NAME, schemaBundles, new ArrayList<>(request.getSchemasNotPlatformSurfaceable()), request.isForceOverride(), new IAppSearchResultCallback.Stub() { public void onResult(AppSearchResult result) { future.complete(result); Loading apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java +50 −6 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.appsearch.exceptions.IllegalSchemaException; import android.app.appsearch.util.BundleUtil; import android.os.Bundle; import android.util.ArraySet; Loading @@ -31,6 +32,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; /** Loading @@ -40,7 +42,7 @@ import java.util.Set; * * <p>The schema consists of type information, properties, and config (like tokenization type). * * @see AppSearchManager#setSchema * @see AppSearchSession#setSchema */ public final class AppSearchSchema { private static final String SCHEMA_TYPE_FIELD = "schemaType"; Loading Loading @@ -94,17 +96,37 @@ public final class AppSearchSchema { return ret; } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!(other instanceof AppSearchSchema)) { return false; } AppSearchSchema otherSchema = (AppSearchSchema) other; if (!getSchemaType().equals(otherSchema.getSchemaType())) { return false; } return getProperties().equals(otherSchema.getProperties()); } @Override public int hashCode() { return Objects.hash(getSchemaType(), getProperties()); } /** Builder for {@link AppSearchSchema objects}. */ public static final class Builder { private final String mTypeName; private final String mSchemaType; private final ArrayList<Bundle> mPropertyBundles = new ArrayList<>(); private final Set<String> mPropertyNames = new ArraySet<>(); private boolean mBuilt = false; /** Creates a new {@link AppSearchSchema.Builder}. */ public Builder(@NonNull String typeName) { Preconditions.checkNotNull(typeName); mTypeName = typeName; public Builder(@NonNull String schemaType) { Preconditions.checkNotNull(schemaType); mSchemaType = schemaType; } /** Adds a property to the given type. */ Loading Loading @@ -133,7 +155,7 @@ public final class AppSearchSchema { public AppSearchSchema build() { Preconditions.checkState(!mBuilt, "Builder has already been used"); Bundle bundle = new Bundle(); bundle.putString(AppSearchSchema.SCHEMA_TYPE_FIELD, mTypeName); bundle.putString(AppSearchSchema.SCHEMA_TYPE_FIELD, mSchemaType); bundle.putParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD, mPropertyBundles); mBuilt = true; return new AppSearchSchema(bundle); Loading Loading @@ -279,6 +301,8 @@ public final class AppSearchSchema { final Bundle mBundle; @Nullable private Integer mHashCode; PropertyConfig(@NonNull Bundle bundle) { mBundle = Preconditions.checkNotNull(bundle); } Loading Loading @@ -327,6 +351,26 @@ public final class AppSearchSchema { return mBundle.getInt(TOKENIZER_TYPE_FIELD); } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!(other instanceof PropertyConfig)) { return false; } PropertyConfig otherProperty = (PropertyConfig) other; return BundleUtil.deepEquals(this.mBundle, otherProperty.mBundle); } @Override public int hashCode() { if (mHashCode == null) { mHashCode = BundleUtil.deepHashCode(mBundle); } return mHashCode; } /** * Builder for {@link PropertyConfig}. * Loading apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java +5 −1 Original line number Diff line number Diff line Loading @@ -140,7 +140,11 @@ public final class AppSearchSession { schemaBundles.add(schema.getBundle()); } try { mService.setSchema(mDatabaseName, schemaBundles, request.isForceOverride(), mService.setSchema( mDatabaseName, schemaBundles, new ArrayList<>(request.getSchemasNotPlatformSurfaceable()), request.isForceOverride(), new IAppSearchResultCallback.Stub() { public void onResult(AppSearchResult result) { executor.execute(() -> callback.accept(result)); Loading apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java +10 −136 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.appsearch.exceptions.AppSearchException; import android.app.appsearch.util.BundleUtil; import android.os.Bundle; import android.util.Log; Loading @@ -37,12 +38,12 @@ import java.util.Set; * * <p>Documents are constructed via {@link GenericDocument.Builder}. * * @see AppSearchManager#putDocuments * @see AppSearchManager#getByUri * @see AppSearchManager#query * @see AppSearchSession#putDocuments * @see AppSearchSession#getByUri * @see AppSearchSession#query */ public class GenericDocument { private static final String TAG = "GenericDocument"; private static final String TAG = "AppSearchGenericDocumen"; /** The default empty namespace. */ public static final String DEFAULT_NAMESPACE = ""; Loading Loading @@ -462,144 +463,17 @@ public class GenericDocument { return false; } GenericDocument otherDocument = (GenericDocument) other; return bundleEquals(this.mBundle, otherDocument.mBundle); } /** * Deeply checks whether two bundles are equal. * * <p>Two bundles will be considered equal if they contain the same content. */ @SuppressWarnings("unchecked") private static boolean bundleEquals(Bundle one, Bundle two) { if (one.size() != two.size()) { return false; } Set<String> keySetOne = one.keySet(); Object valueOne; Object valueTwo; // Bundle inherit its equals() from Object.java, which only compare their memory address. // We should iterate all keys and check their presents and values in both bundle. for (String key : keySetOne) { valueOne = one.get(key); valueTwo = two.get(key); if (valueOne instanceof Bundle && valueTwo instanceof Bundle && !bundleEquals((Bundle) valueOne, (Bundle) valueTwo)) { return false; } else if (valueOne == null && (valueTwo != null || !two.containsKey(key))) { // If we call bundle.get(key) when the 'key' doesn't actually exist in the // bundle, we'll get back a null. So make sure that both values are null and // both keys exist in the bundle. return false; } else if (valueOne instanceof boolean[]) { if (!(valueTwo instanceof boolean[]) || !Arrays.equals((boolean[]) valueOne, (boolean[]) valueTwo)) { return false; } } else if (valueOne instanceof long[]) { if (!(valueTwo instanceof long[]) || !Arrays.equals((long[]) valueOne, (long[]) valueTwo)) { return false; } } else if (valueOne instanceof double[]) { if (!(valueTwo instanceof double[]) || !Arrays.equals((double[]) valueOne, (double[]) valueTwo)) { return false; } } else if (valueOne instanceof Bundle[]) { if (!(valueTwo instanceof Bundle[])) { return false; } Bundle[] bundlesOne = (Bundle[]) valueOne; Bundle[] bundlesTwo = (Bundle[]) valueTwo; if (bundlesOne.length != bundlesTwo.length) { return false; } for (int i = 0; i < bundlesOne.length; i++) { if (!bundleEquals(bundlesOne[i], bundlesTwo[i])) { return false; } } } else if (valueOne instanceof ArrayList) { if (!(valueTwo instanceof ArrayList)) { return false; } ArrayList<Bundle> bundlesOne = (ArrayList<Bundle>) valueOne; ArrayList<Bundle> bundlesTwo = (ArrayList<Bundle>) valueTwo; if (bundlesOne.size() != bundlesTwo.size()) { return false; } for (int i = 0; i < bundlesOne.size(); i++) { if (!bundleEquals(bundlesOne.get(i), bundlesTwo.get(i))) { return false; } } } else if (valueOne instanceof Object[]) { if (!(valueTwo instanceof Object[]) || !Arrays.equals((Object[]) valueOne, (Object[]) valueTwo)) { return false; } } } return true; return BundleUtil.deepEquals(this.mBundle, otherDocument.mBundle); } @Override public int hashCode() { if (mHashCode == null) { mHashCode = bundleHashCode(mBundle); mHashCode = BundleUtil.deepHashCode(mBundle); } return mHashCode; } /** * Calculates the hash code for a bundle. * * <p>The hash code is only effected by the contents in the bundle. Bundles will get consistent * hash code if they have same contents. */ @SuppressWarnings("unchecked") private static int bundleHashCode(Bundle bundle) { int[] hashCodes = new int[bundle.size()]; int i = 0; // Bundle inherit its hashCode() from Object.java, which only relative to their memory // address. Bundle doesn't have an order, so we should iterate all keys and combine // their value's hashcode into an array. And use the hashcode of the array to be // the hashcode of the bundle. for (String key : bundle.keySet()) { Object value = bundle.get(key); if (value instanceof boolean[]) { hashCodes[i++] = Arrays.hashCode((boolean[]) value); } else if (value instanceof long[]) { hashCodes[i++] = Arrays.hashCode((long[]) value); } else if (value instanceof double[]) { hashCodes[i++] = Arrays.hashCode((double[]) value); } else if (value instanceof String[]) { hashCodes[i++] = Arrays.hashCode((Object[]) value); } else if (value instanceof Bundle) { hashCodes[i++] = bundleHashCode((Bundle) value); } else if (value instanceof Bundle[]) { Bundle[] bundles = (Bundle[]) value; int[] innerHashCodes = new int[bundles.length]; for (int j = 0; j < innerHashCodes.length; j++) { innerHashCodes[j] = bundleHashCode(bundles[j]); } hashCodes[i++] = Arrays.hashCode(innerHashCodes); } else if (value instanceof ArrayList) { ArrayList<Bundle> bundles = (ArrayList<Bundle>) value; int[] innerHashCodes = new int[bundles.size()]; for (int j = 0; j < innerHashCodes.length; j++) { innerHashCodes[j] = bundleHashCode(bundles.get(j)); } hashCodes[i++] = Arrays.hashCode(innerHashCodes); } else { hashCodes[i++] = value.hashCode(); } } return Arrays.hashCode(hashCodes); } @Override @NonNull public String toString() { Loading Loading @@ -683,10 +557,10 @@ public class GenericDocument { * * @param uri The uri of {@link GenericDocument}. * @param schemaType The schema type of the {@link GenericDocument}. The passed-in {@code * schemaType} must be defined using {@link AppSearchManager#setSchema} prior to * schemaType} must be defined using {@link AppSearchSession#setSchema} prior to * inserting a document of this {@code schemaType} into the AppSearch index using {@link * AppSearchManager#putDocuments}. Otherwise, the document will be rejected by {@link * AppSearchManager#putDocuments}. * AppSearchSession#putDocuments}. Otherwise, the document will be rejected by {@link * AppSearchSession#putDocuments}. */ @SuppressWarnings("unchecked") public Builder(@NonNull String uri, @NonNull String schemaType) { Loading apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java +1 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ import java.util.Set; /** * Encapsulates a request to retrieve documents by namespace and URI. * * @see AppSearchManager#getByUri * @see AppSearchSession#getByUri */ public final class GetByUriRequest { private final String mNamespace; Loading Loading
apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +5 −1 Original line number Diff line number Diff line Loading @@ -224,7 +224,11 @@ public class AppSearchManager { } AndroidFuture<AppSearchResult> future = new AndroidFuture<>(); try { mService.setSchema(DEFAULT_DATABASE_NAME, schemaBundles, request.isForceOverride(), mService.setSchema( DEFAULT_DATABASE_NAME, schemaBundles, new ArrayList<>(request.getSchemasNotPlatformSurfaceable()), request.isForceOverride(), new IAppSearchResultCallback.Stub() { public void onResult(AppSearchResult result) { future.complete(result); Loading
apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java +50 −6 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.appsearch.exceptions.IllegalSchemaException; import android.app.appsearch.util.BundleUtil; import android.os.Bundle; import android.util.ArraySet; Loading @@ -31,6 +32,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; /** Loading @@ -40,7 +42,7 @@ import java.util.Set; * * <p>The schema consists of type information, properties, and config (like tokenization type). * * @see AppSearchManager#setSchema * @see AppSearchSession#setSchema */ public final class AppSearchSchema { private static final String SCHEMA_TYPE_FIELD = "schemaType"; Loading Loading @@ -94,17 +96,37 @@ public final class AppSearchSchema { return ret; } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!(other instanceof AppSearchSchema)) { return false; } AppSearchSchema otherSchema = (AppSearchSchema) other; if (!getSchemaType().equals(otherSchema.getSchemaType())) { return false; } return getProperties().equals(otherSchema.getProperties()); } @Override public int hashCode() { return Objects.hash(getSchemaType(), getProperties()); } /** Builder for {@link AppSearchSchema objects}. */ public static final class Builder { private final String mTypeName; private final String mSchemaType; private final ArrayList<Bundle> mPropertyBundles = new ArrayList<>(); private final Set<String> mPropertyNames = new ArraySet<>(); private boolean mBuilt = false; /** Creates a new {@link AppSearchSchema.Builder}. */ public Builder(@NonNull String typeName) { Preconditions.checkNotNull(typeName); mTypeName = typeName; public Builder(@NonNull String schemaType) { Preconditions.checkNotNull(schemaType); mSchemaType = schemaType; } /** Adds a property to the given type. */ Loading Loading @@ -133,7 +155,7 @@ public final class AppSearchSchema { public AppSearchSchema build() { Preconditions.checkState(!mBuilt, "Builder has already been used"); Bundle bundle = new Bundle(); bundle.putString(AppSearchSchema.SCHEMA_TYPE_FIELD, mTypeName); bundle.putString(AppSearchSchema.SCHEMA_TYPE_FIELD, mSchemaType); bundle.putParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD, mPropertyBundles); mBuilt = true; return new AppSearchSchema(bundle); Loading Loading @@ -279,6 +301,8 @@ public final class AppSearchSchema { final Bundle mBundle; @Nullable private Integer mHashCode; PropertyConfig(@NonNull Bundle bundle) { mBundle = Preconditions.checkNotNull(bundle); } Loading Loading @@ -327,6 +351,26 @@ public final class AppSearchSchema { return mBundle.getInt(TOKENIZER_TYPE_FIELD); } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!(other instanceof PropertyConfig)) { return false; } PropertyConfig otherProperty = (PropertyConfig) other; return BundleUtil.deepEquals(this.mBundle, otherProperty.mBundle); } @Override public int hashCode() { if (mHashCode == null) { mHashCode = BundleUtil.deepHashCode(mBundle); } return mHashCode; } /** * Builder for {@link PropertyConfig}. * Loading
apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java +5 −1 Original line number Diff line number Diff line Loading @@ -140,7 +140,11 @@ public final class AppSearchSession { schemaBundles.add(schema.getBundle()); } try { mService.setSchema(mDatabaseName, schemaBundles, request.isForceOverride(), mService.setSchema( mDatabaseName, schemaBundles, new ArrayList<>(request.getSchemasNotPlatformSurfaceable()), request.isForceOverride(), new IAppSearchResultCallback.Stub() { public void onResult(AppSearchResult result) { executor.execute(() -> callback.accept(result)); Loading
apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java +10 −136 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.app.appsearch.exceptions.AppSearchException; import android.app.appsearch.util.BundleUtil; import android.os.Bundle; import android.util.Log; Loading @@ -37,12 +38,12 @@ import java.util.Set; * * <p>Documents are constructed via {@link GenericDocument.Builder}. * * @see AppSearchManager#putDocuments * @see AppSearchManager#getByUri * @see AppSearchManager#query * @see AppSearchSession#putDocuments * @see AppSearchSession#getByUri * @see AppSearchSession#query */ public class GenericDocument { private static final String TAG = "GenericDocument"; private static final String TAG = "AppSearchGenericDocumen"; /** The default empty namespace. */ public static final String DEFAULT_NAMESPACE = ""; Loading Loading @@ -462,144 +463,17 @@ public class GenericDocument { return false; } GenericDocument otherDocument = (GenericDocument) other; return bundleEquals(this.mBundle, otherDocument.mBundle); } /** * Deeply checks whether two bundles are equal. * * <p>Two bundles will be considered equal if they contain the same content. */ @SuppressWarnings("unchecked") private static boolean bundleEquals(Bundle one, Bundle two) { if (one.size() != two.size()) { return false; } Set<String> keySetOne = one.keySet(); Object valueOne; Object valueTwo; // Bundle inherit its equals() from Object.java, which only compare their memory address. // We should iterate all keys and check their presents and values in both bundle. for (String key : keySetOne) { valueOne = one.get(key); valueTwo = two.get(key); if (valueOne instanceof Bundle && valueTwo instanceof Bundle && !bundleEquals((Bundle) valueOne, (Bundle) valueTwo)) { return false; } else if (valueOne == null && (valueTwo != null || !two.containsKey(key))) { // If we call bundle.get(key) when the 'key' doesn't actually exist in the // bundle, we'll get back a null. So make sure that both values are null and // both keys exist in the bundle. return false; } else if (valueOne instanceof boolean[]) { if (!(valueTwo instanceof boolean[]) || !Arrays.equals((boolean[]) valueOne, (boolean[]) valueTwo)) { return false; } } else if (valueOne instanceof long[]) { if (!(valueTwo instanceof long[]) || !Arrays.equals((long[]) valueOne, (long[]) valueTwo)) { return false; } } else if (valueOne instanceof double[]) { if (!(valueTwo instanceof double[]) || !Arrays.equals((double[]) valueOne, (double[]) valueTwo)) { return false; } } else if (valueOne instanceof Bundle[]) { if (!(valueTwo instanceof Bundle[])) { return false; } Bundle[] bundlesOne = (Bundle[]) valueOne; Bundle[] bundlesTwo = (Bundle[]) valueTwo; if (bundlesOne.length != bundlesTwo.length) { return false; } for (int i = 0; i < bundlesOne.length; i++) { if (!bundleEquals(bundlesOne[i], bundlesTwo[i])) { return false; } } } else if (valueOne instanceof ArrayList) { if (!(valueTwo instanceof ArrayList)) { return false; } ArrayList<Bundle> bundlesOne = (ArrayList<Bundle>) valueOne; ArrayList<Bundle> bundlesTwo = (ArrayList<Bundle>) valueTwo; if (bundlesOne.size() != bundlesTwo.size()) { return false; } for (int i = 0; i < bundlesOne.size(); i++) { if (!bundleEquals(bundlesOne.get(i), bundlesTwo.get(i))) { return false; } } } else if (valueOne instanceof Object[]) { if (!(valueTwo instanceof Object[]) || !Arrays.equals((Object[]) valueOne, (Object[]) valueTwo)) { return false; } } } return true; return BundleUtil.deepEquals(this.mBundle, otherDocument.mBundle); } @Override public int hashCode() { if (mHashCode == null) { mHashCode = bundleHashCode(mBundle); mHashCode = BundleUtil.deepHashCode(mBundle); } return mHashCode; } /** * Calculates the hash code for a bundle. * * <p>The hash code is only effected by the contents in the bundle. Bundles will get consistent * hash code if they have same contents. */ @SuppressWarnings("unchecked") private static int bundleHashCode(Bundle bundle) { int[] hashCodes = new int[bundle.size()]; int i = 0; // Bundle inherit its hashCode() from Object.java, which only relative to their memory // address. Bundle doesn't have an order, so we should iterate all keys and combine // their value's hashcode into an array. And use the hashcode of the array to be // the hashcode of the bundle. for (String key : bundle.keySet()) { Object value = bundle.get(key); if (value instanceof boolean[]) { hashCodes[i++] = Arrays.hashCode((boolean[]) value); } else if (value instanceof long[]) { hashCodes[i++] = Arrays.hashCode((long[]) value); } else if (value instanceof double[]) { hashCodes[i++] = Arrays.hashCode((double[]) value); } else if (value instanceof String[]) { hashCodes[i++] = Arrays.hashCode((Object[]) value); } else if (value instanceof Bundle) { hashCodes[i++] = bundleHashCode((Bundle) value); } else if (value instanceof Bundle[]) { Bundle[] bundles = (Bundle[]) value; int[] innerHashCodes = new int[bundles.length]; for (int j = 0; j < innerHashCodes.length; j++) { innerHashCodes[j] = bundleHashCode(bundles[j]); } hashCodes[i++] = Arrays.hashCode(innerHashCodes); } else if (value instanceof ArrayList) { ArrayList<Bundle> bundles = (ArrayList<Bundle>) value; int[] innerHashCodes = new int[bundles.size()]; for (int j = 0; j < innerHashCodes.length; j++) { innerHashCodes[j] = bundleHashCode(bundles.get(j)); } hashCodes[i++] = Arrays.hashCode(innerHashCodes); } else { hashCodes[i++] = value.hashCode(); } } return Arrays.hashCode(hashCodes); } @Override @NonNull public String toString() { Loading Loading @@ -683,10 +557,10 @@ public class GenericDocument { * * @param uri The uri of {@link GenericDocument}. * @param schemaType The schema type of the {@link GenericDocument}. The passed-in {@code * schemaType} must be defined using {@link AppSearchManager#setSchema} prior to * schemaType} must be defined using {@link AppSearchSession#setSchema} prior to * inserting a document of this {@code schemaType} into the AppSearch index using {@link * AppSearchManager#putDocuments}. Otherwise, the document will be rejected by {@link * AppSearchManager#putDocuments}. * AppSearchSession#putDocuments}. Otherwise, the document will be rejected by {@link * AppSearchSession#putDocuments}. */ @SuppressWarnings("unchecked") public Builder(@NonNull String uri, @NonNull String schemaType) { Loading
apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java +1 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ import java.util.Set; /** * Encapsulates a request to retrieve documents by namespace and URI. * * @see AppSearchManager#getByUri * @see AppSearchSession#getByUri */ public final class GetByUriRequest { private final String mNamespace; Loading