diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java index 0aa685d6e1bfa..300ef367dfb73 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java @@ -74,10 +74,10 @@ public class AppSearchManager { *
The schema is the set of document types, properties, and config (like tokenization type) - * understood by AppSearch for this app. + *
For example, an e-mail message or a music recording could be a schema type. + * + *
The schema consists of type information, properties, and config (like tokenization type).
*
* @hide
*/
public final class AppSearchSchema {
- private final SchemaProto mProto;
+ private final SchemaTypeConfigProto mProto;
- private AppSearchSchema(SchemaProto proto) {
+ private AppSearchSchema(SchemaTypeConfigProto proto) {
mProto = proto;
}
/** Creates a new {@link AppSearchSchema.Builder}. */
@NonNull
- public static AppSearchSchema.Builder newBuilder() {
- return new AppSearchSchema.Builder();
- }
-
- /** Creates a new {@link SchemaType.Builder}. */
- @NonNull
- public static SchemaType.Builder newSchemaTypeBuilder(@NonNull String typeName) {
- return new SchemaType.Builder(typeName);
+ public static AppSearchSchema.Builder newBuilder(@NonNull String typeName) {
+ return new AppSearchSchema.Builder(typeName);
}
/** Creates a new {@link PropertyConfig.Builder}. */
@@ -61,32 +58,34 @@ public final class AppSearchSchema {
return new PropertyConfig.Builder(propertyName);
}
- /** Creates a new {@link IndexingConfig.Builder}. */
- @NonNull
- public static IndexingConfig.Builder newIndexingConfigBuilder() {
- return new IndexingConfig.Builder();
- }
-
/**
- * Returns the schema proto populated by the {@link AppSearchSchema} builders.
+ * Returns the {@link SchemaTypeConfigProto} populated by this builder.
* @hide
*/
@NonNull
@VisibleForTesting
- public SchemaProto getProto() {
+ public SchemaTypeConfigProto getProto() {
return mProto;
}
+ @Override
+ public String toString() {
+ return mProto.toString();
+ }
+
/** Builder for {@link AppSearchSchema objects}. */
public static final class Builder {
- private final SchemaProto.Builder mProtoBuilder = SchemaProto.newBuilder();
+ private final SchemaTypeConfigProto.Builder mProtoBuilder =
+ SchemaTypeConfigProto.newBuilder();
- private Builder() {}
+ private Builder(@NonNull String typeName) {
+ mProtoBuilder.setSchemaType(typeName);
+ }
- /** Adds a supported type to this app's AppSearch schema. */
+ /** Adds a property to the given type. */
@NonNull
- public AppSearchSchema.Builder addType(@NonNull SchemaType schemaType) {
- mProtoBuilder.addTypes(schemaType.mProto);
+ public AppSearchSchema.Builder addProperty(@NonNull PropertyConfig propertyConfig) {
+ mProtoBuilder.addProperties(propertyConfig.mProto);
return this;
}
@@ -97,50 +96,18 @@ public final class AppSearchSchema {
*/
@NonNull
public AppSearchSchema build() {
+ Set For example, an e-mail message or a music recording could be a schema type.
- */
- public static final class SchemaType {
- private final SchemaTypeConfigProto mProto;
-
- private SchemaType(SchemaTypeConfigProto proto) {
- mProto = proto;
- }
-
- /** Builder for {@link SchemaType} objects. */
- public static final class Builder {
- private final SchemaTypeConfigProto.Builder mProtoBuilder =
- SchemaTypeConfigProto.newBuilder();
-
- private Builder(@NonNull String typeName) {
- mProtoBuilder.setSchemaType(typeName);
- }
-
- /** Adds a property to the given type. */
- @NonNull
- public SchemaType.Builder addProperty(@NonNull PropertyConfig propertyConfig) {
- mProtoBuilder.addProperties(propertyConfig.mProto);
- return this;
- }
-
- /**
- * Constructs a new {@link SchemaType} from the contents of this builder.
- *
- * After calling this method, the builder must no longer be used.
- */
- @NonNull
- public SchemaType build() {
- return new SchemaType(mProtoBuilder.build());
- }
- }
- }
-
/**
* Configuration for a single property (field) of a document type.
*
@@ -197,130 +164,14 @@ public final class AppSearchSchema {
/** Exactly one value [1]. */
public static final int CARDINALITY_REQUIRED = 3;
- private final PropertyConfigProto mProto;
-
- private PropertyConfig(PropertyConfigProto proto) {
- mProto = proto;
- }
-
- /**
- * Builder for {@link PropertyConfig}.
- *
- * The following properties must be set, or {@link PropertyConfig} construction will
- * fail:
- * In addition, if {@code schemaType} is {@link #DATA_TYPE_DOCUMENT}, {@code schemaType}
- * is also required.
- */
- public static final class Builder {
- private final PropertyConfigProto.Builder mProtoBuilder =
- PropertyConfigProto.newBuilder();
-
- private Builder(String propertyName) {
- mProtoBuilder.setPropertyName(propertyName);
- }
-
- /**
- * Type of data the property contains (e.g. string, int, bytes, etc).
- *
- * This property must be set.
- */
- @NonNull
- public PropertyConfig.Builder setDataType(@DataType int dataType) {
- PropertyConfigProto.DataType.Code dataTypeProto =
- PropertyConfigProto.DataType.Code.forNumber(dataType);
- if (dataTypeProto == null) {
- throw new IllegalArgumentException("Invalid dataType: " + dataType);
- }
- mProtoBuilder.setDataType(dataTypeProto);
- return this;
- }
-
- /**
- * The logical schema-type of the contents of this property.
- *
- * Only required when {@link #setDataType(int)} is set to
- * {@link #DATA_TYPE_DOCUMENT}. Otherwise, it is ignored.
- */
- @NonNull
- public PropertyConfig.Builder setSchemaType(@NonNull String schemaType) {
- mProtoBuilder.setSchemaType(schemaType);
- return this;
- }
-
- /**
- * The cardinality of the property (whether it is optional, required or repeated).
- *
- * This property must be set.
- */
- @NonNull
- public PropertyConfig.Builder setCardinality(@Cardinality int cardinality) {
- PropertyConfigProto.Cardinality.Code cardinalityProto =
- PropertyConfigProto.Cardinality.Code.forNumber(cardinality);
- if (cardinalityProto == null) {
- throw new IllegalArgumentException("Invalid cardinality: " + cardinality);
- }
- mProtoBuilder.setCardinality(cardinalityProto);
- return this;
- }
-
- /**
- * Configures how this property should be indexed.
- *
- * If this is not supplied, the property will not be indexed at all.
- */
- @NonNull
- public PropertyConfig.Builder setIndexingConfig(
- @NonNull IndexingConfig indexingConfig) {
- mProtoBuilder.setIndexingConfig(indexingConfig.mProto);
- return this;
- }
-
- /**
- * Constructs a new {@link PropertyConfig} from the contents of this builder.
- *
- * After calling this method, the builder must no longer be used.
- *
- * @throws IllegalSchemaException If the property is not correctly populated (e.g.
- * missing {@code dataType}).
- */
- @NonNull
- public PropertyConfig build() {
- if (mProtoBuilder.getDataType() == PropertyConfigProto.DataType.Code.UNKNOWN) {
- throw new IllegalSchemaException("Missing field: dataType");
- }
- if (mProtoBuilder.getSchemaType().isEmpty()
- && mProtoBuilder.getDataType()
- == PropertyConfigProto.DataType.Code.DOCUMENT) {
- throw new IllegalSchemaException(
- "Missing field: schemaType (required for configs with "
- + "dataType = DOCUMENT)");
- }
- if (mProtoBuilder.getCardinality()
- == PropertyConfigProto.Cardinality.Code.UNKNOWN) {
- throw new IllegalSchemaException("Missing field: cardinality");
- }
- return new PropertyConfig(mProtoBuilder.build());
- }
- }
- }
-
- /** Configures how a property should be indexed so that it can be retrieved by queries. */
- public static final class IndexingConfig {
/** Encapsulates the configurations on how AppSearch should query/index these terms. */
- // NOTE: The integer values of these constants must match the proto enum constants in
- // com.google.android.icing.proto.TermMatchType.Code.
- @IntDef(prefix = {"TERM_MATCH_TYPE_"}, value = {
- TERM_MATCH_TYPE_UNKNOWN,
- TERM_MATCH_TYPE_EXACT_ONLY,
- TERM_MATCH_TYPE_PREFIX,
+ @IntDef(prefix = {"INDEXING_TYPE_"}, value = {
+ INDEXING_TYPE_NONE,
+ INDEXING_TYPE_EXACT_TERMS,
+ INDEXING_TYPE_PREFIXES,
})
@Retention(RetentionPolicy.SOURCE)
- public @interface TermMatchType {}
+ public @interface IndexingType {}
/**
* Content in this property will not be tokenized or indexed.
@@ -328,9 +179,9 @@ public final class AppSearchSchema {
* Useful if the data type is not made up of terms (e.g.
* {@link PropertyConfig#DATA_TYPE_DOCUMENT} or {@link PropertyConfig#DATA_TYPE_BYTES}
* type). All the properties inside the nested property won't be indexed regardless of the
- * value of {@code termMatchType} for the nested properties.
+ * value of {@code indexingType} for the nested properties.
*/
- public static final int TERM_MATCH_TYPE_UNKNOWN = 0;
+ public static final int INDEXING_TYPE_NONE = 0;
/**
* Content in this property should only be returned for queries matching the exact tokens
@@ -338,7 +189,7 @@ public final class AppSearchSchema {
*
* Ex. A property with "fool" should NOT match a query for "foo".
*/
- public static final int TERM_MATCH_TYPE_EXACT_ONLY = 1;
+ public static final int INDEXING_TYPE_EXACT_TERMS = 1;
/**
* Content in this property should be returned for queries that are either exact matches or
@@ -346,7 +197,7 @@ public final class AppSearchSchema {
*
* Ex. A property with "fool" should match a query for "foo".
*/
- public static final int TERM_MATCH_TYPE_PREFIX = 2;
+ public static final int INDEXING_TYPE_PREFIXES = 2;
/** Configures how tokens should be extracted from this property. */
// NOTE: The integer values of these constants must match the proto enum constants in
@@ -367,59 +218,151 @@ public final class AppSearchSchema {
/** Tokenization for plain text. */
public static final int TOKENIZER_TYPE_PLAIN = 1;
- private final com.google.android.icing.proto.IndexingConfig mProto;
+ private final PropertyConfigProto mProto;
- private IndexingConfig(com.google.android.icing.proto.IndexingConfig proto) {
+ private PropertyConfig(PropertyConfigProto proto) {
mProto = proto;
}
+ @Override
+ public String toString() {
+ return mProto.toString();
+ }
+
/**
- * Builder for {@link IndexingConfig} objects.
+ * Builder for {@link PropertyConfig}.
*
- * You may skip adding an {@link IndexingConfig} for a property, which is equivalent to
- * an {@link IndexingConfig} having {@code termMatchType} equal to
- * {@link #TERM_MATCH_TYPE_UNKNOWN}. In this case the property will not be indexed.
+ * The following properties must be set, or {@link PropertyConfig} construction will
+ * fail:
+ * In addition, if {@code schemaType} is {@link #DATA_TYPE_DOCUMENT}, {@code schemaType}
+ * is also required.
*/
public static final class Builder {
- private final com.google.android.icing.proto.IndexingConfig.Builder mProtoBuilder =
- com.google.android.icing.proto.IndexingConfig.newBuilder();
+ private final PropertyConfigProto.Builder mPropertyConfigProto =
+ PropertyConfigProto.newBuilder();
+ private final com.google.android.icing.proto.IndexingConfig.Builder
+ mIndexingConfigProto =
+ com.google.android.icing.proto.IndexingConfig.newBuilder();
- private Builder() {}
+ private Builder(String propertyName) {
+ mPropertyConfigProto.setPropertyName(propertyName);
+ }
- /** Configures how the content of this property should be matched in the index. */
+ /**
+ * Type of data the property contains (e.g. string, int, bytes, etc).
+ *
+ * This property must be set.
+ */
@NonNull
- public IndexingConfig.Builder setTermMatchType(@TermMatchType int termMatchType) {
- com.google.android.icing.proto.TermMatchType.Code termMatchTypeProto =
- com.google.android.icing.proto.TermMatchType.Code.forNumber(termMatchType);
- if (termMatchTypeProto == null) {
- throw new IllegalArgumentException("Invalid termMatchType: " + termMatchType);
+ public PropertyConfig.Builder setDataType(@DataType int dataType) {
+ PropertyConfigProto.DataType.Code dataTypeProto =
+ PropertyConfigProto.DataType.Code.forNumber(dataType);
+ if (dataTypeProto == null) {
+ throw new IllegalArgumentException("Invalid dataType: " + dataType);
}
- mProtoBuilder.setTermMatchType(termMatchTypeProto);
+ mPropertyConfigProto.setDataType(dataTypeProto);
+ return this;
+ }
+
+ /**
+ * The logical schema-type of the contents of this property.
+ *
+ * Only required when {@link #setDataType(int)} is set to
+ * {@link #DATA_TYPE_DOCUMENT}. Otherwise, it is ignored.
+ */
+ @NonNull
+ public PropertyConfig.Builder setSchemaType(@NonNull String schemaType) {
+ mPropertyConfigProto.setSchemaType(schemaType);
+ return this;
+ }
+
+ /**
+ * The cardinality of the property (whether it is optional, required or repeated).
+ *
+ * This property must be set.
+ */
+ @NonNull
+ public PropertyConfig.Builder setCardinality(@Cardinality int cardinality) {
+ PropertyConfigProto.Cardinality.Code cardinalityProto =
+ PropertyConfigProto.Cardinality.Code.forNumber(cardinality);
+ if (cardinalityProto == null) {
+ throw new IllegalArgumentException("Invalid cardinality: " + cardinality);
+ }
+ mPropertyConfigProto.setCardinality(cardinalityProto);
+ return this;
+ }
+
+ /**
+ * Configures how a property should be indexed so that it can be retrieved by queries.
+ */
+ @NonNull
+ public PropertyConfig.Builder setIndexingType(@IndexingType int indexingType) {
+ TermMatchType.Code termMatchTypeProto;
+ switch (indexingType) {
+ case INDEXING_TYPE_NONE:
+ termMatchTypeProto = TermMatchType.Code.UNKNOWN;
+ break;
+ case INDEXING_TYPE_EXACT_TERMS:
+ termMatchTypeProto = TermMatchType.Code.EXACT_ONLY;
+ break;
+ case INDEXING_TYPE_PREFIXES:
+ termMatchTypeProto = TermMatchType.Code.PREFIX;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid indexingType: " + indexingType);
+ }
+ mIndexingConfigProto.setTermMatchType(termMatchTypeProto);
return this;
}
/** Configures how this property should be tokenized (split into words). */
@NonNull
- public IndexingConfig.Builder setTokenizerType(@TokenizerType int tokenizerType) {
+ public PropertyConfig.Builder setTokenizerType(@TokenizerType int tokenizerType) {
com.google.android.icing.proto.IndexingConfig.TokenizerType.Code
tokenizerTypeProto =
com.google.android.icing.proto.IndexingConfig
- .TokenizerType.Code.forNumber(tokenizerType);
+ .TokenizerType.Code.forNumber(tokenizerType);
if (tokenizerTypeProto == null) {
throw new IllegalArgumentException("Invalid tokenizerType: " + tokenizerType);
}
- mProtoBuilder.setTokenizerType(tokenizerTypeProto);
+ mIndexingConfigProto.setTokenizerType(tokenizerTypeProto);
return this;
}
/**
- * Constructs a new {@link IndexingConfig} from the contents of this builder.
+ * Constructs a new {@link PropertyConfig} from the contents of this builder.
*
* After calling this method, the builder must no longer be used.
+ *
+ * @throws IllegalSchemaException If the property is not correctly populated (e.g.
+ * missing {@code dataType}).
*/
@NonNull
- public IndexingConfig build() {
- return new IndexingConfig(mProtoBuilder.build());
+ public PropertyConfig build() {
+ mPropertyConfigProto.setIndexingConfig(mIndexingConfigProto);
+ // TODO(b/147692920): Send the schema to Icing Lib for official validation, instead
+ // of partially reimplementing some of the validation Icing does here.
+ if (mPropertyConfigProto.getDataType()
+ == PropertyConfigProto.DataType.Code.UNKNOWN) {
+ throw new IllegalSchemaException("Missing field: dataType");
+ }
+ if (mPropertyConfigProto.getSchemaType().isEmpty()
+ && mPropertyConfigProto.getDataType()
+ == PropertyConfigProto.DataType.Code.DOCUMENT) {
+ throw new IllegalSchemaException(
+ "Missing field: schemaType (required for configs with "
+ + "dataType = DOCUMENT)");
+ }
+ if (mPropertyConfigProto.getCardinality()
+ == PropertyConfigProto.Cardinality.Code.UNKNOWN) {
+ throw new IllegalSchemaException("Missing field: cardinality");
+ }
+ return new PropertyConfig(mPropertyConfigProto.build());
}
}
}
diff --git a/core/tests/coretests/src/android/app/appsearch/AppSearchSchemaTest.java b/core/tests/coretests/src/android/app/appsearch/AppSearchSchemaTest.java
index 0be52c1803385..08ec2d0b10674 100644
--- a/core/tests/coretests/src/android/app/appsearch/AppSearchSchemaTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/AppSearchSchemaTest.java
@@ -21,14 +21,12 @@ import static com.google.common.truth.Truth.assertThat;
import static org.testng.Assert.assertThrows;
import static org.testng.Assert.expectThrows;
-import android.app.appsearch.AppSearchSchema.IndexingConfig;
import android.app.appsearch.AppSearchSchema.PropertyConfig;
import androidx.test.filters.SmallTest;
import com.google.android.icing.proto.IndexingConfig.TokenizerType;
import com.google.android.icing.proto.PropertyConfigProto;
-import com.google.android.icing.proto.SchemaProto;
import com.google.android.icing.proto.SchemaTypeConfigProto;
import com.google.android.icing.proto.TermMatchType;
@@ -37,94 +35,87 @@ import org.junit.Test;
@SmallTest
public class AppSearchSchemaTest {
@Test
- public void testSuccess() {
- AppSearchSchema schema = AppSearchSchema.newBuilder()
- .addType(AppSearchSchema.newSchemaTypeBuilder("Email")
- .addProperty(AppSearchSchema.newPropertyBuilder("subject")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingConfig(AppSearchSchema.newIndexingConfigBuilder()
- .setTokenizerType(IndexingConfig.TOKENIZER_TYPE_PLAIN)
- .setTermMatchType(IndexingConfig.TERM_MATCH_TYPE_PREFIX)
- .build()
- ).build()
- ).addProperty(AppSearchSchema.newPropertyBuilder("body")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingConfig(AppSearchSchema.newIndexingConfigBuilder()
- .setTokenizerType(IndexingConfig.TOKENIZER_TYPE_PLAIN)
- .setTermMatchType(IndexingConfig.TERM_MATCH_TYPE_PREFIX)
- .build()
- ).build()
- ).build()
-
- ).addType(AppSearchSchema.newSchemaTypeBuilder("MusicRecording")
- .addProperty(AppSearchSchema.newPropertyBuilder("artist")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
- .setIndexingConfig(AppSearchSchema.newIndexingConfigBuilder()
- .setTokenizerType(IndexingConfig.TOKENIZER_TYPE_PLAIN)
- .setTermMatchType(IndexingConfig.TERM_MATCH_TYPE_PREFIX)
- .build()
- ).build()
- ).addProperty(AppSearchSchema.newPropertyBuilder("pubDate")
- .setDataType(PropertyConfig.DATA_TYPE_INT64)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingConfig(AppSearchSchema.newIndexingConfigBuilder()
- .setTokenizerType(IndexingConfig.TOKENIZER_TYPE_NONE)
- .setTermMatchType(IndexingConfig.TERM_MATCH_TYPE_UNKNOWN)
- .build()
- ).build()
- ).build()
+ public void testGetProto_Email() {
+ AppSearchSchema emailSchema = AppSearchSchema.newBuilder("Email")
+ .addProperty(AppSearchSchema.newPropertyBuilder("subject")
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build()
+ ).addProperty(AppSearchSchema.newPropertyBuilder("body")
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build()
).build();
- SchemaProto expectedProto = SchemaProto.newBuilder()
- .addTypes(SchemaTypeConfigProto.newBuilder()
- .setSchemaType("Email")
- .addProperties(PropertyConfigProto.newBuilder()
- .setPropertyName("subject")
- .setDataType(PropertyConfigProto.DataType.Code.STRING)
- .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
- .setIndexingConfig(
- com.google.android.icing.proto.IndexingConfig.newBuilder()
- .setTokenizerType(TokenizerType.Code.PLAIN)
- .setTermMatchType(TermMatchType.Code.PREFIX)
- )
- ).addProperties(PropertyConfigProto.newBuilder()
- .setPropertyName("body")
- .setDataType(PropertyConfigProto.DataType.Code.STRING)
- .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
- .setIndexingConfig(
- com.google.android.icing.proto.IndexingConfig.newBuilder()
- .setTokenizerType(TokenizerType.Code.PLAIN)
- .setTermMatchType(TermMatchType.Code.PREFIX)
- )
+ SchemaTypeConfigProto expectedEmailProto = SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("Email")
+ .addProperties(PropertyConfigProto.newBuilder()
+ .setPropertyName("subject")
+ .setDataType(PropertyConfigProto.DataType.Code.STRING)
+ .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
+ .setIndexingConfig(
+ com.google.android.icing.proto.IndexingConfig.newBuilder()
+ .setTokenizerType(TokenizerType.Code.PLAIN)
+ .setTermMatchType(TermMatchType.Code.PREFIX)
)
-
- ).addTypes(SchemaTypeConfigProto.newBuilder()
- .setSchemaType("MusicRecording")
- .addProperties(PropertyConfigProto.newBuilder()
- .setPropertyName("artist")
- .setDataType(PropertyConfigProto.DataType.Code.STRING)
- .setCardinality(PropertyConfigProto.Cardinality.Code.REPEATED)
- .setIndexingConfig(
- com.google.android.icing.proto.IndexingConfig.newBuilder()
- .setTokenizerType(TokenizerType.Code.PLAIN)
- .setTermMatchType(TermMatchType.Code.PREFIX)
- )
- ).addProperties(PropertyConfigProto.newBuilder()
- .setPropertyName("pubDate")
- .setDataType(PropertyConfigProto.DataType.Code.INT64)
- .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
- .setIndexingConfig(
- com.google.android.icing.proto.IndexingConfig.newBuilder()
- .setTokenizerType(TokenizerType.Code.NONE)
- .setTermMatchType(TermMatchType.Code.UNKNOWN)
- )
+ ).addProperties(PropertyConfigProto.newBuilder()
+ .setPropertyName("body")
+ .setDataType(PropertyConfigProto.DataType.Code.STRING)
+ .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
+ .setIndexingConfig(
+ com.google.android.icing.proto.IndexingConfig.newBuilder()
+ .setTokenizerType(TokenizerType.Code.PLAIN)
+ .setTermMatchType(TermMatchType.Code.PREFIX)
)
).build();
- assertThat(schema.getProto()).isEqualTo(expectedProto);
+ assertThat(emailSchema.getProto()).isEqualTo(expectedEmailProto);
+ }
+
+ @Test
+ public void testGetProto_MusicRecording() {
+ AppSearchSchema musicRecordingSchema = AppSearchSchema.newBuilder("MusicRecording")
+ .addProperty(AppSearchSchema.newPropertyBuilder("artist")
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_REPEATED)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build()
+ ).addProperty(AppSearchSchema.newPropertyBuilder("pubDate")
+ .setDataType(PropertyConfig.DATA_TYPE_INT64)
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_NONE)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_NONE)
+ .build()
+ ).build();
+
+ SchemaTypeConfigProto expectedMusicRecordingProto = SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("MusicRecording")
+ .addProperties(PropertyConfigProto.newBuilder()
+ .setPropertyName("artist")
+ .setDataType(PropertyConfigProto.DataType.Code.STRING)
+ .setCardinality(PropertyConfigProto.Cardinality.Code.REPEATED)
+ .setIndexingConfig(
+ com.google.android.icing.proto.IndexingConfig.newBuilder()
+ .setTokenizerType(TokenizerType.Code.PLAIN)
+ .setTermMatchType(TermMatchType.Code.PREFIX)
+ )
+ ).addProperties(PropertyConfigProto.newBuilder()
+ .setPropertyName("pubDate")
+ .setDataType(PropertyConfigProto.DataType.Code.INT64)
+ .setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
+ .setIndexingConfig(
+ com.google.android.icing.proto.IndexingConfig.newBuilder()
+ .setTokenizerType(TokenizerType.Code.NONE)
+ .setTermMatchType(TermMatchType.Code.UNKNOWN)
+ )
+ ).build();
+
+ assertThat(musicRecordingSchema.getProto()).isEqualTo(expectedMusicRecordingProto);
}
@Test
@@ -151,4 +142,25 @@ public class AppSearchSchemaTest {
builder.setCardinality(PropertyConfig.CARDINALITY_REPEATED);
builder.build();
}
+
+ @Test
+ public void testDuplicateProperties() {
+ AppSearchSchema.Builder builder = AppSearchSchema.newBuilder("Email")
+ .addProperty(AppSearchSchema.newPropertyBuilder("subject")
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build()
+ ).addProperty(AppSearchSchema.newPropertyBuilder("subject")
+ .setDataType(PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
+ .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
+ .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
+ .build()
+ );
+
+ Exception e = expectThrows(IllegalSchemaException.class, builder::build);
+ assertThat(e).hasMessageThat().contains("Property defined more than once: subject");
+ }
}
- *
- *
- *
+ *
+ *
+ *