script-astra/Android/Sdk/sources/android-35/android/app/appsearch/safeparcel/GenericDocumentParcel.java
localadmin 4380f00a78 init
2025-01-20 18:15:20 +03:00

527 lines
19 KiB
Java

/*
* 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.CurrentTimeMillisLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.AppSearchSession;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.annotation.CanIgnoreReturnValue;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* Holds data for a {@link GenericDocument}.
*
* @hide
*/
@SafeParcelable.Class(creator = "GenericDocumentParcelCreator")
// This won't be used to send data over binder, and we have to use Parcelable for code sync purpose.
@SuppressLint("BanParcelableUsage")
public final class GenericDocumentParcel extends AbstractSafeParcelable implements Parcelable {
@NonNull
public static final Parcelable.Creator<GenericDocumentParcel> CREATOR =
new GenericDocumentParcelCreator();
/** The default score of document. */
private static final int DEFAULT_SCORE = 0;
/** The default time-to-live in millisecond of a document, which is infinity. */
private static final long DEFAULT_TTL_MILLIS = 0L;
/** Default but invalid value for {@code mCreationTimestampMillis}. */
private static final long INVALID_CREATION_TIMESTAMP_MILLIS = -1L;
@Field(id = 1, getter = "getNamespace")
@NonNull
private final String mNamespace;
@Field(id = 2, getter = "getId")
@NonNull
private final String mId;
@Field(id = 3, getter = "getSchemaType")
@NonNull
private final String mSchemaType;
@Field(id = 4, getter = "getCreationTimestampMillis")
private final long mCreationTimestampMillis;
@Field(id = 5, getter = "getTtlMillis")
private final long mTtlMillis;
@Field(id = 6, getter = "getScore")
private final int mScore;
/**
* Contains all properties in {@link GenericDocument} in a list.
*
* <p>Unfortunately SafeParcelable doesn't support map type so we have to use a list here.
*/
@Field(id = 7, getter = "getProperties")
@NonNull
private final List<PropertyParcel> mProperties;
/** Contains all parent properties for this {@link GenericDocument} in a list. */
@Field(id = 8, getter = "getParentTypes")
@Nullable
private final List<String> mParentTypes;
/**
* Contains all properties in {@link GenericDocument} to support getting properties via name
*
* <p>This map is created for quick looking up property by name.
*/
@NonNull private final Map<String, PropertyParcel> mPropertyMap;
@Nullable private Integer mHashCode;
/**
* The constructor taking the property list, and create map internally from this list.
*
* <p>This will be used in createFromParcel, so creating the property map can not be avoided in
* this constructor.
*/
@Constructor
GenericDocumentParcel(
@Param(id = 1) @NonNull String namespace,
@Param(id = 2) @NonNull String id,
@Param(id = 3) @NonNull String schemaType,
@Param(id = 4) long creationTimestampMillis,
@Param(id = 5) long ttlMillis,
@Param(id = 6) int score,
@Param(id = 7) @NonNull List<PropertyParcel> properties,
@Param(id = 8) @Nullable List<String> parentTypes) {
this(
namespace,
id,
schemaType,
creationTimestampMillis,
ttlMillis,
score,
properties,
createPropertyMapFromPropertyArray(properties),
parentTypes);
}
/**
* A constructor taking both property list and property map.
*
* <p>Caller needs to make sure property list and property map matches(map is generated from
* list, or list generated from map).
*/
GenericDocumentParcel(
@NonNull String namespace,
@NonNull String id,
@NonNull String schemaType,
long creationTimestampMillis,
long ttlMillis,
int score,
@NonNull List<PropertyParcel> properties,
@NonNull Map<String, PropertyParcel> propertyMap,
@Nullable List<String> parentTypes) {
mNamespace = Objects.requireNonNull(namespace);
mId = Objects.requireNonNull(id);
mSchemaType = Objects.requireNonNull(schemaType);
mCreationTimestampMillis = creationTimestampMillis;
mTtlMillis = ttlMillis;
mScore = score;
mProperties = Objects.requireNonNull(properties);
mPropertyMap = Objects.requireNonNull(propertyMap);
mParentTypes = parentTypes;
}
private static Map<String, PropertyParcel> createPropertyMapFromPropertyArray(
@NonNull List<PropertyParcel> properties) {
Objects.requireNonNull(properties);
Map<String, PropertyParcel> propertyMap = new ArrayMap<>(properties.size());
for (int i = 0; i < properties.size(); ++i) {
PropertyParcel property = properties.get(i);
propertyMap.put(property.getPropertyName(), property);
}
return propertyMap;
}
/** Returns the unique identifier of the {@link GenericDocument}. */
@NonNull
public String getId() {
return mId;
}
/** Returns the namespace of the {@link GenericDocument}. */
@NonNull
public String getNamespace() {
return mNamespace;
}
/** Returns the {@link AppSearchSchema} type of the {@link GenericDocument}. */
@NonNull
public String getSchemaType() {
return mSchemaType;
}
/** Returns the creation timestamp of the {@link GenericDocument}, in milliseconds. */
@CurrentTimeMillisLong
public long getCreationTimestampMillis() {
return mCreationTimestampMillis;
}
/** Returns the TTL (time-to-live) of the {@link GenericDocument}, in milliseconds. */
public long getTtlMillis() {
return mTtlMillis;
}
/** Returns the score of the {@link GenericDocument}. */
public int getScore() {
return mScore;
}
/** Returns the names of all properties defined in this document. */
@NonNull
public Set<String> getPropertyNames() {
return mPropertyMap.keySet();
}
/** Returns all the properties the document has. */
@NonNull
public List<PropertyParcel> getProperties() {
return mProperties;
}
/** Returns the property map the document has. */
@NonNull
public Map<String, PropertyParcel> getPropertyMap() {
return mPropertyMap;
}
/** Returns the list of parent types for the {@link GenericDocument}. */
@Nullable
public List<String> getParentTypes() {
return mParentTypes;
}
@Override
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
if (!(other instanceof GenericDocumentParcel)) {
return false;
}
GenericDocumentParcel otherDocument = (GenericDocumentParcel) other;
return mNamespace.equals(otherDocument.mNamespace)
&& mId.equals(otherDocument.mId)
&& mSchemaType.equals(otherDocument.mSchemaType)
&& mTtlMillis == otherDocument.mTtlMillis
&& mCreationTimestampMillis == otherDocument.mCreationTimestampMillis
&& mScore == otherDocument.mScore
&& Objects.equals(mProperties, otherDocument.mProperties)
&& Objects.equals(mPropertyMap, otherDocument.mPropertyMap)
&& Objects.equals(mParentTypes, otherDocument.mParentTypes);
}
@Override
public int hashCode() {
if (mHashCode == null) {
mHashCode =
Objects.hash(
mNamespace,
mId,
mSchemaType,
mTtlMillis,
mScore,
mCreationTimestampMillis,
Objects.hashCode(mProperties),
Objects.hashCode(mPropertyMap),
Objects.hashCode(mParentTypes));
}
return mHashCode;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
GenericDocumentParcelCreator.writeToParcel(this, dest, flags);
}
/** The builder class for {@link GenericDocumentParcel}. */
public static final class Builder {
private String mNamespace;
private String mId;
private String mSchemaType;
private long mCreationTimestampMillis;
private long mTtlMillis;
private int mScore;
private Map<String, PropertyParcel> mPropertyMap;
@Nullable private List<String> mParentTypes;
/**
* Creates a new {@link GenericDocument.Builder}.
*
* <p>Document IDs are unique within a namespace.
*
* <p>The number of namespaces per app should be kept small for efficiency reasons.
*/
public Builder(@NonNull String namespace, @NonNull String id, @NonNull String schemaType) {
mNamespace = Objects.requireNonNull(namespace);
mId = Objects.requireNonNull(id);
mSchemaType = Objects.requireNonNull(schemaType);
mCreationTimestampMillis = INVALID_CREATION_TIMESTAMP_MILLIS;
mTtlMillis = DEFAULT_TTL_MILLIS;
mScore = DEFAULT_SCORE;
mPropertyMap = new ArrayMap<>();
}
/**
* Creates a new {@link GenericDocumentParcel.Builder} from the given {@link
* GenericDocumentParcel}.
*/
public Builder(@NonNull GenericDocumentParcel documentSafeParcel) {
Objects.requireNonNull(documentSafeParcel);
mNamespace = documentSafeParcel.mNamespace;
mId = documentSafeParcel.mId;
mSchemaType = documentSafeParcel.mSchemaType;
mCreationTimestampMillis = documentSafeParcel.mCreationTimestampMillis;
mTtlMillis = documentSafeParcel.mTtlMillis;
mScore = documentSafeParcel.mScore;
// Create a shallow copy of the map so we won't change the original one.
Map<String, PropertyParcel> propertyMap = documentSafeParcel.mPropertyMap;
mPropertyMap = new ArrayMap<>(propertyMap.size());
for (PropertyParcel value : propertyMap.values()) {
mPropertyMap.put(value.getPropertyName(), value);
}
// We don't need to create a shallow copy here, as in the setter for ParentTypes we
// will create a new list anyway.
mParentTypes = documentSafeParcel.mParentTypes;
}
/**
* Sets the app-defined namespace this document resides in, changing the value provided in
* the constructor. No special values are reserved or understood by the infrastructure.
*
* <p>Document IDs are unique within a namespace.
*
* <p>The number of namespaces per app should be kept small for efficiency reasons.
*/
@CanIgnoreReturnValue
@NonNull
public Builder setNamespace(@NonNull String namespace) {
Objects.requireNonNull(namespace);
mNamespace = namespace;
return this;
}
/**
* Sets the ID of this document, changing the value provided in the constructor. No special
* values are reserved or understood by the infrastructure.
*
* <p>Document IDs are unique within a namespace.
*/
@CanIgnoreReturnValue
@NonNull
public Builder setId(@NonNull String id) {
Objects.requireNonNull(id);
mId = id;
return this;
}
/**
* Sets the schema type of this document, changing the value provided in the constructor.
*
* <p>To successfully index a document, the schema type must match the name of an {@link
* AppSearchSchema} object previously provided to {@link AppSearchSession#setSchema}.
*/
@CanIgnoreReturnValue
@NonNull
public Builder setSchemaType(@NonNull String schemaType) {
Objects.requireNonNull(schemaType);
mSchemaType = schemaType;
return this;
}
/** Sets the score of the parent {@link GenericDocument}. */
@CanIgnoreReturnValue
@NonNull
public Builder setScore(int score) {
mScore = score;
return this;
}
/**
* Sets the creation timestamp of the {@link GenericDocument}, in milliseconds.
*
* <p>This should be set using a value obtained from the {@link System#currentTimeMillis}
* time base.
*
* <p>If this method is not called, this will be set to the time the object is built.
*
* @param creationTimestampMillis a creation timestamp in milliseconds.
*/
@CanIgnoreReturnValue
@NonNull
public Builder setCreationTimestampMillis(
@CurrentTimeMillisLong long creationTimestampMillis) {
mCreationTimestampMillis = creationTimestampMillis;
return this;
}
/**
* Sets the TTL (time-to-live) of the {@link GenericDocument}, in milliseconds.
*
* <p>The TTL is measured against {@link #getCreationTimestampMillis}. At the timestamp of
* {@code creationTimestampMillis + ttlMillis}, measured in the {@link
* System#currentTimeMillis} time base, the document will be auto-deleted.
*
* <p>The default value is 0, which means the document is permanent and won't be
* auto-deleted until the app is uninstalled or {@link AppSearchSession#remove} is called.
*
* @param ttlMillis a non-negative duration in milliseconds.
* @throws IllegalArgumentException if ttlMillis is negative.
*/
@CanIgnoreReturnValue
@NonNull
public Builder setTtlMillis(long ttlMillis) {
if (ttlMillis < 0) {
throw new IllegalArgumentException("Document ttlMillis cannot be negative.");
}
mTtlMillis = ttlMillis;
return this;
}
/**
* Sets the list of parent types of the {@link GenericDocument}'s type.
*
* <p>Child types must appear before parent types in the list.
*/
@CanIgnoreReturnValue
@NonNull
public Builder setParentTypes(@NonNull List<String> parentTypes) {
Objects.requireNonNull(parentTypes);
mParentTypes = new ArrayList<>(parentTypes);
return this;
}
/**
* Clears the value for the property with the given name.
*
* <p>Note that this method does not support property paths.
*
* @param name The name of the property to clear.
*/
@CanIgnoreReturnValue
@NonNull
public Builder clearProperty(@NonNull String name) {
Objects.requireNonNull(name);
mPropertyMap.remove(name);
return this;
}
/** puts an array of {@link String} in property map. */
@CanIgnoreReturnValue
@NonNull
public Builder putInPropertyMap(@NonNull String name, @NonNull String[] values)
throws IllegalArgumentException {
putInPropertyMap(
name, new PropertyParcel.Builder(name).setStringValues(values).build());
return this;
}
/** puts an array of boolean in property map. */
@CanIgnoreReturnValue
@NonNull
public Builder putInPropertyMap(@NonNull String name, @NonNull boolean[] values) {
putInPropertyMap(
name, new PropertyParcel.Builder(name).setBooleanValues(values).build());
return this;
}
/** puts an array of double in property map. */
@CanIgnoreReturnValue
@NonNull
public Builder putInPropertyMap(@NonNull String name, @NonNull double[] values) {
putInPropertyMap(
name, new PropertyParcel.Builder(name).setDoubleValues(values).build());
return this;
}
/** puts an array of long in property map. */
@CanIgnoreReturnValue
@NonNull
public Builder putInPropertyMap(@NonNull String name, @NonNull long[] values) {
putInPropertyMap(name, new PropertyParcel.Builder(name).setLongValues(values).build());
return this;
}
/** Converts and saves a byte[][] into {@link #mProperties}. */
@CanIgnoreReturnValue
@NonNull
public Builder putInPropertyMap(@NonNull String name, @NonNull byte[][] values) {
putInPropertyMap(name, new PropertyParcel.Builder(name).setBytesValues(values).build());
return this;
}
/** puts an array of {@link GenericDocumentParcel} in property map. */
@CanIgnoreReturnValue
@NonNull
public Builder putInPropertyMap(
@NonNull String name, @NonNull GenericDocumentParcel[] values) {
putInPropertyMap(
name, new PropertyParcel.Builder(name).setDocumentValues(values).build());
return this;
}
/** Directly puts a {@link PropertyParcel} in property map. */
@CanIgnoreReturnValue
@NonNull
public Builder putInPropertyMap(@NonNull String name, @NonNull PropertyParcel value) {
Objects.requireNonNull(value);
mPropertyMap.put(name, value);
return this;
}
/** Builds the {@link GenericDocument} object. */
@NonNull
public GenericDocumentParcel build() {
// Set current timestamp for creation timestamp by default.
if (mCreationTimestampMillis == INVALID_CREATION_TIMESTAMP_MILLIS) {
mCreationTimestampMillis = System.currentTimeMillis();
}
return new GenericDocumentParcel(
mNamespace,
mId,
mSchemaType,
mCreationTimestampMillis,
mTtlMillis,
mScore,
new ArrayList<>(mPropertyMap.values()),
mParentTypes);
}
}
}