/* * Copyright 2023 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.safeparcel; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.appsearch.AppSearchSchema; import android.app.appsearch.AppSearchSchema.PropertyConfig.Cardinality; import android.app.appsearch.AppSearchSchema.PropertyConfig.DataType; import android.app.appsearch.AppSearchSchema.StringPropertyConfig.JoinableValueType; import android.app.appsearch.AppSearchSchema.StringPropertyConfig.TokenizerType; import android.os.Parcel; import android.os.Parcelable; import java.util.List; import java.util.Objects; /** * Class to hold property configuration for one property defined in {@link AppSearchSchema}. * *

It is defined as same as PropertyConfigProto for the native code to handle different property * types in one class. * *

Currently it can handle String, long, double, boolean, bytes and document type. * * @hide */ @SafeParcelable.Class(creator = "PropertyConfigParcelCreator") public final class PropertyConfigParcel extends AbstractSafeParcelable { @NonNull public static final Parcelable.Creator CREATOR = new PropertyConfigParcelCreator(); @Field(id = 1, getter = "getName") private final String mName; @AppSearchSchema.PropertyConfig.DataType @Field(id = 2, getter = "getDataType") private final int mDataType; @AppSearchSchema.PropertyConfig.Cardinality @Field(id = 3, getter = "getCardinality") private final int mCardinality; @Field(id = 4, getter = "getSchemaType") @Nullable private final String mSchemaType; @Field(id = 5, getter = "getStringIndexingConfigParcel") @Nullable private final StringIndexingConfigParcel mStringIndexingConfigParcel; @Field(id = 6, getter = "getDocumentIndexingConfigParcel") @Nullable private final DocumentIndexingConfigParcel mDocumentIndexingConfigParcel; @Field(id = 7, getter = "getIntegerIndexingConfigParcel") @Nullable private final IntegerIndexingConfigParcel mIntegerIndexingConfigParcel; @Field(id = 8, getter = "getJoinableConfigParcel") @Nullable private final JoinableConfigParcel mJoinableConfigParcel; @Field(id = 9, getter = "getDescription") private final String mDescription; @Nullable private Integer mHashCode; /** Constructor for {@link PropertyConfigParcel}. */ @Constructor PropertyConfigParcel( @Param(id = 1) @NonNull String name, @Param(id = 2) @DataType int dataType, @Param(id = 3) @Cardinality int cardinality, @Param(id = 4) @Nullable String schemaType, @Param(id = 5) @Nullable StringIndexingConfigParcel stringIndexingConfigParcel, @Param(id = 6) @Nullable DocumentIndexingConfigParcel documentIndexingConfigParcel, @Param(id = 7) @Nullable IntegerIndexingConfigParcel integerIndexingConfigParcel, @Param(id = 8) @Nullable JoinableConfigParcel joinableConfigParcel, @Param(id = 9) @NonNull String description) { mName = Objects.requireNonNull(name); mDataType = dataType; mCardinality = cardinality; mSchemaType = schemaType; mStringIndexingConfigParcel = stringIndexingConfigParcel; mDocumentIndexingConfigParcel = documentIndexingConfigParcel; mIntegerIndexingConfigParcel = integerIndexingConfigParcel; mJoinableConfigParcel = joinableConfigParcel; mDescription = Objects.requireNonNull(description); } /** Creates a {@link PropertyConfigParcel} for String. */ @NonNull public static PropertyConfigParcel createForString( @NonNull String propertyName, @NonNull String description, @Cardinality int cardinality, @NonNull StringIndexingConfigParcel stringIndexingConfigParcel, @NonNull JoinableConfigParcel joinableConfigParcel) { return new PropertyConfigParcel( Objects.requireNonNull(propertyName), AppSearchSchema.PropertyConfig.DATA_TYPE_STRING, cardinality, /* schemaType= */ null, Objects.requireNonNull(stringIndexingConfigParcel), /* documentIndexingConfigParcel= */ null, /* integerIndexingConfigParcel= */ null, Objects.requireNonNull(joinableConfigParcel), Objects.requireNonNull(description)); } /** Creates a {@link PropertyConfigParcel} for Long. */ @NonNull public static PropertyConfigParcel createForLong( @NonNull String propertyName, @NonNull String description, @Cardinality int cardinality, @AppSearchSchema.LongPropertyConfig.IndexingType int indexingType) { return new PropertyConfigParcel( Objects.requireNonNull(propertyName), AppSearchSchema.PropertyConfig.DATA_TYPE_LONG, cardinality, /* schemaType= */ null, /* stringIndexingConfigParcel= */ null, /* documentIndexingConfigParcel= */ null, new IntegerIndexingConfigParcel(indexingType), /* joinableConfigParcel= */ null, Objects.requireNonNull(description)); } /** Creates a {@link PropertyConfigParcel} for Double. */ @NonNull public static PropertyConfigParcel createForDouble( @NonNull String propertyName, @NonNull String description, @Cardinality int cardinality) { return new PropertyConfigParcel( Objects.requireNonNull(propertyName), AppSearchSchema.PropertyConfig.DATA_TYPE_DOUBLE, cardinality, /* schemaType= */ null, /* stringIndexingConfigParcel= */ null, /* documentIndexingConfigParcel= */ null, /* integerIndexingConfigParcel= */ null, /* joinableConfigParcel= */ null, Objects.requireNonNull(description)); } /** Creates a {@link PropertyConfigParcel} for Boolean. */ @NonNull public static PropertyConfigParcel createForBoolean( @NonNull String propertyName, @NonNull String description, @Cardinality int cardinality) { return new PropertyConfigParcel( Objects.requireNonNull(propertyName), AppSearchSchema.PropertyConfig.DATA_TYPE_BOOLEAN, cardinality, /* schemaType= */ null, /* stringIndexingConfigParcel= */ null, /* documentIndexingConfigParcel= */ null, /* integerIndexingConfigParcel= */ null, /* joinableConfigParcel= */ null, Objects.requireNonNull(description)); } /** Creates a {@link PropertyConfigParcel} for Bytes. */ @NonNull public static PropertyConfigParcel createForBytes( @NonNull String propertyName, @NonNull String description, @Cardinality int cardinality) { return new PropertyConfigParcel( Objects.requireNonNull(propertyName), AppSearchSchema.PropertyConfig.DATA_TYPE_BYTES, cardinality, /* schemaType= */ null, /* stringIndexingConfigParcel= */ null, /* documentIndexingConfigParcel= */ null, /* integerIndexingConfigParcel= */ null, /* joinableConfigParcel= */ null, Objects.requireNonNull(description)); } /** Creates a {@link PropertyConfigParcel} for Document. */ @NonNull public static PropertyConfigParcel createForDocument( @NonNull String propertyName, @NonNull String description, @Cardinality int cardinality, @NonNull String schemaType, @NonNull DocumentIndexingConfigParcel documentIndexingConfigParcel) { return new PropertyConfigParcel( Objects.requireNonNull(propertyName), AppSearchSchema.PropertyConfig.DATA_TYPE_DOCUMENT, cardinality, Objects.requireNonNull(schemaType), /* stringIndexingConfigParcel= */ null, Objects.requireNonNull(documentIndexingConfigParcel), /* integerIndexingConfigParcel= */ null, /* joinableConfigParcel= */ null, Objects.requireNonNull(description)); } /** Gets name for the property. */ @NonNull public String getName() { return mName; } /** Gets description for the property. */ @NonNull public String getDescription() { return mDescription; } /** Gets data type for the property. */ @DataType public int getDataType() { return mDataType; } /** Gets cardinality for the property. */ @Cardinality public int getCardinality() { return mCardinality; } /** Gets schema type. */ @Nullable public String getSchemaType() { return mSchemaType; } /** Gets the {@link StringIndexingConfigParcel}. */ @Nullable public StringIndexingConfigParcel getStringIndexingConfigParcel() { return mStringIndexingConfigParcel; } /** Gets the {@link DocumentIndexingConfigParcel}. */ @Nullable public DocumentIndexingConfigParcel getDocumentIndexingConfigParcel() { return mDocumentIndexingConfigParcel; } /** Gets the {@link IntegerIndexingConfigParcel}. */ @Nullable public IntegerIndexingConfigParcel getIntegerIndexingConfigParcel() { return mIntegerIndexingConfigParcel; } /** Gets the {@link JoinableConfigParcel}. */ @Nullable public JoinableConfigParcel getJoinableConfigParcel() { return mJoinableConfigParcel; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { PropertyConfigParcelCreator.writeToParcel(this, dest, flags); } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!(other instanceof PropertyConfigParcel)) { return false; } PropertyConfigParcel otherProperty = (PropertyConfigParcel) other; return Objects.equals(mName, otherProperty.mName) && Objects.equals(mDescription, otherProperty.mDescription) && Objects.equals(mDataType, otherProperty.mDataType) && Objects.equals(mCardinality, otherProperty.mCardinality) && Objects.equals(mSchemaType, otherProperty.mSchemaType) && Objects.equals( mStringIndexingConfigParcel, otherProperty.mStringIndexingConfigParcel) && Objects.equals( mDocumentIndexingConfigParcel, otherProperty.mDocumentIndexingConfigParcel) && Objects.equals( mIntegerIndexingConfigParcel, otherProperty.mIntegerIndexingConfigParcel) && Objects.equals(mJoinableConfigParcel, otherProperty.mJoinableConfigParcel); } @Override public int hashCode() { if (mHashCode == null) { mHashCode = Objects.hash( mName, mDescription, mDataType, mCardinality, mSchemaType, mStringIndexingConfigParcel, mDocumentIndexingConfigParcel, mIntegerIndexingConfigParcel, mJoinableConfigParcel); } return mHashCode; } @Override @NonNull public String toString() { return "{name: " + mName + ", description: " + mDescription + ", dataType: " + mDataType + ", cardinality: " + mCardinality + ", schemaType: " + mSchemaType + ", stringIndexingConfigParcel: " + mStringIndexingConfigParcel + ", documentIndexingConfigParcel: " + mDocumentIndexingConfigParcel + ", integerIndexingConfigParcel: " + mIntegerIndexingConfigParcel + ", joinableConfigParcel: " + mJoinableConfigParcel + "}"; } /** Class to hold join configuration for a String type. */ @SafeParcelable.Class(creator = "JoinableConfigParcelCreator") public static class JoinableConfigParcel extends AbstractSafeParcelable { @NonNull public static final Parcelable.Creator CREATOR = new JoinableConfigParcelCreator(); @JoinableValueType @Field(id = 1, getter = "getJoinableValueType") private final int mJoinableValueType; @Field(id = 2, getter = "getDeletionPropagation") private final boolean mDeletionPropagation; /** Constructor for {@link JoinableConfigParcel}. */ @Constructor public JoinableConfigParcel( @Param(id = 1) @JoinableValueType int joinableValueType, @Param(id = 2) boolean deletionPropagation) { mJoinableValueType = joinableValueType; mDeletionPropagation = deletionPropagation; } /** Gets {@link JoinableValueType} of the join. */ @JoinableValueType public int getJoinableValueType() { return mJoinableValueType; } /** Gets whether delete will be propagated. */ public boolean getDeletionPropagation() { return mDeletionPropagation; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { JoinableConfigParcelCreator.writeToParcel(this, dest, flags); } @Override public int hashCode() { return Objects.hash(mJoinableValueType, mDeletionPropagation); } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!(other instanceof JoinableConfigParcel)) { return false; } JoinableConfigParcel otherObject = (JoinableConfigParcel) other; return Objects.equals(mJoinableValueType, otherObject.mJoinableValueType) && Objects.equals(mDeletionPropagation, otherObject.mDeletionPropagation); } @Override @NonNull public String toString() { return "{joinableValueType: " + mJoinableValueType + ", deletePropagation " + mDeletionPropagation + "}"; } } /** Class to hold configuration a string type. */ @SafeParcelable.Class(creator = "StringIndexingConfigParcelCreator") public static class StringIndexingConfigParcel extends AbstractSafeParcelable { @NonNull public static final Parcelable.Creator CREATOR = new StringIndexingConfigParcelCreator(); @AppSearchSchema.StringPropertyConfig.IndexingType @Field(id = 1, getter = "getIndexingType") private final int mIndexingType; @TokenizerType @Field(id = 2, getter = "getTokenizerType") private final int mTokenizerType; /** Constructor for {@link StringIndexingConfigParcel}. */ @Constructor public StringIndexingConfigParcel( @Param(id = 1) @AppSearchSchema.StringPropertyConfig.IndexingType int indexingType, @Param(id = 2) @TokenizerType int tokenizerType) { mIndexingType = indexingType; mTokenizerType = tokenizerType; } /** Gets the indexing type for this property. */ @AppSearchSchema.StringPropertyConfig.IndexingType public int getIndexingType() { return mIndexingType; } /** Gets the tokenization type for this property. */ @TokenizerType public int getTokenizerType() { return mTokenizerType; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { StringIndexingConfigParcelCreator.writeToParcel(this, dest, flags); } @Override public int hashCode() { return Objects.hash(mIndexingType, mTokenizerType); } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!(other instanceof StringIndexingConfigParcel)) { return false; } StringIndexingConfigParcel otherObject = (StringIndexingConfigParcel) other; return Objects.equals(mIndexingType, otherObject.mIndexingType) && Objects.equals(mTokenizerType, otherObject.mTokenizerType); } @Override @NonNull public String toString() { return "{indexingType: " + mIndexingType + ", tokenizerType " + mTokenizerType + "}"; } } /** Class to hold configuration for integer property type. */ @SafeParcelable.Class(creator = "IntegerIndexingConfigParcelCreator") public static class IntegerIndexingConfigParcel extends AbstractSafeParcelable { @NonNull public static final Parcelable.Creator CREATOR = new IntegerIndexingConfigParcelCreator(); @AppSearchSchema.LongPropertyConfig.IndexingType @Field(id = 1, getter = "getIndexingType") private final int mIndexingType; /** Constructor for {@link IntegerIndexingConfigParcel}. */ @Constructor public IntegerIndexingConfigParcel( @Param(id = 1) @AppSearchSchema.LongPropertyConfig.IndexingType int indexingType) { mIndexingType = indexingType; } /** Gets the indexing type for this integer property. */ @AppSearchSchema.LongPropertyConfig.IndexingType public int getIndexingType() { return mIndexingType; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { IntegerIndexingConfigParcelCreator.writeToParcel(this, dest, flags); } @Override public int hashCode() { return Objects.hash(mIndexingType); } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!(other instanceof IntegerIndexingConfigParcel)) { return false; } IntegerIndexingConfigParcel otherObject = (IntegerIndexingConfigParcel) other; return Objects.equals(mIndexingType, otherObject.mIndexingType); } @Override @NonNull public String toString() { return "{indexingType: " + mIndexingType + "}"; } } /** Class to hold configuration for document property type. */ @SafeParcelable.Class(creator = "DocumentIndexingConfigParcelCreator") public static class DocumentIndexingConfigParcel extends AbstractSafeParcelable { @NonNull public static final Parcelable.Creator CREATOR = new DocumentIndexingConfigParcelCreator(); @Field(id = 1, getter = "shouldIndexNestedProperties") private final boolean mIndexNestedProperties; @NonNull @Field(id = 2, getter = "getIndexableNestedPropertiesList") private final List mIndexableNestedPropertiesList; /** Constructor for {@link DocumentIndexingConfigParcel}. */ @Constructor public DocumentIndexingConfigParcel( @Param(id = 1) boolean indexNestedProperties, @Param(id = 2) @NonNull List indexableNestedPropertiesList) { mIndexNestedProperties = indexNestedProperties; mIndexableNestedPropertiesList = Objects.requireNonNull(indexableNestedPropertiesList); } /** Nested properties should be indexed. */ public boolean shouldIndexNestedProperties() { return mIndexNestedProperties; } /** Gets the list for nested property list. */ @NonNull public List getIndexableNestedPropertiesList() { return mIndexableNestedPropertiesList; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { DocumentIndexingConfigParcelCreator.writeToParcel(this, dest, flags); } @Override public int hashCode() { return Objects.hash(mIndexNestedProperties, mIndexableNestedPropertiesList); } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!(other instanceof DocumentIndexingConfigParcel)) { return false; } DocumentIndexingConfigParcel otherObject = (DocumentIndexingConfigParcel) other; return Objects.equals(mIndexNestedProperties, otherObject.mIndexNestedProperties) && Objects.equals( mIndexableNestedPropertiesList, otherObject.mIndexableNestedPropertiesList); } @Override @NonNull public String toString() { return "{indexNestedProperties: " + mIndexNestedProperties + ", indexableNestedPropertiesList: " + mIndexableNestedPropertiesList + "}"; } } }