1 /* 2 * Copyright 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.appsearch.localstorage.converter; 18 19 import android.util.Log; 20 21 import androidx.annotation.OptIn; 22 import androidx.annotation.RestrictTo; 23 import androidx.appsearch.app.AppSearchSchema; 24 import androidx.appsearch.app.ExperimentalAppSearchApi; 25 import androidx.core.util.Preconditions; 26 27 import com.google.android.icing.proto.DocumentIndexingConfig; 28 import com.google.android.icing.proto.EmbeddingIndexingConfig; 29 import com.google.android.icing.proto.IntegerIndexingConfig; 30 import com.google.android.icing.proto.JoinableConfig; 31 import com.google.android.icing.proto.PropertyConfigProto; 32 import com.google.android.icing.proto.SchemaTypeConfigProto; 33 import com.google.android.icing.proto.SchemaTypeConfigProtoOrBuilder; 34 import com.google.android.icing.proto.StringIndexingConfig; 35 import com.google.android.icing.proto.TermMatchType; 36 37 import org.jspecify.annotations.NonNull; 38 39 import java.util.List; 40 41 /** 42 * Translates an {@link AppSearchSchema} into a {@link SchemaTypeConfigProto}. 43 * @exportToFramework:hide 44 */ 45 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 46 public final class SchemaToProtoConverter { 47 private static final String TAG = "AppSearchSchemaToProtoC"; 48 SchemaToProtoConverter()49 private SchemaToProtoConverter() {} 50 51 /** 52 * Converts an {@link androidx.appsearch.app.AppSearchSchema} into a 53 * {@link SchemaTypeConfigProto}. 54 */ 55 // TODO(b/284356266): Consider handling addition of schema name prefixes in this function. 56 @OptIn(markerClass = ExperimentalAppSearchApi.class) toSchemaTypeConfigProto( @onNull AppSearchSchema schema, int version)57 public static @NonNull SchemaTypeConfigProto toSchemaTypeConfigProto( 58 @NonNull AppSearchSchema schema, int version) { 59 Preconditions.checkNotNull(schema); 60 SchemaTypeConfigProto.Builder protoBuilder = SchemaTypeConfigProto.newBuilder() 61 .setSchemaType(schema.getSchemaType()) 62 .setDescription(schema.getDescription()) 63 .setVersion(version); 64 List<AppSearchSchema.PropertyConfig> properties = schema.getProperties(); 65 for (int i = 0; i < properties.size(); i++) { 66 PropertyConfigProto propertyProto = toPropertyConfigProto(properties.get(i)); 67 protoBuilder.addProperties(propertyProto); 68 } 69 protoBuilder.addAllParentTypes(schema.getParentTypes()); 70 return protoBuilder.build(); 71 } 72 73 @OptIn(markerClass = ExperimentalAppSearchApi.class) toPropertyConfigProto( AppSearchSchema.@onNull PropertyConfig property)74 private static @NonNull PropertyConfigProto toPropertyConfigProto( 75 AppSearchSchema.@NonNull PropertyConfig property) { 76 Preconditions.checkNotNull(property); 77 PropertyConfigProto.Builder builder = PropertyConfigProto.newBuilder() 78 .setPropertyName(property.getName()) 79 .setDescription(property.getDescription()); 80 81 // Set dataType 82 @AppSearchSchema.PropertyConfig.DataType int dataType = property.getDataType(); 83 PropertyConfigProto.DataType.Code dataTypeProto = 84 PropertyConfigProto.DataType.Code.forNumber(dataType); 85 if (dataTypeProto == null) { 86 throw new IllegalArgumentException("Invalid dataType: " + dataType); 87 } 88 builder.setDataType(dataTypeProto); 89 90 // Set cardinality 91 @AppSearchSchema.PropertyConfig.Cardinality int cardinality = property.getCardinality(); 92 PropertyConfigProto.Cardinality.Code cardinalityProto = 93 PropertyConfigProto.Cardinality.Code.forNumber(cardinality); 94 if (cardinalityProto == null) { 95 throw new IllegalArgumentException("Invalid cardinality: " + dataType); 96 } 97 builder.setCardinality(cardinalityProto); 98 99 if (property instanceof AppSearchSchema.StringPropertyConfig) { 100 AppSearchSchema.StringPropertyConfig stringProperty = 101 (AppSearchSchema.StringPropertyConfig) property; 102 // No need to check against delete propagation type vs joinable value type here, because 103 // the builder has already enforced the restriction. 104 105 // Set JoinableConfig only if it is joinable (i.e. joinableValueType is not NONE). 106 if (stringProperty.getJoinableValueType() 107 != AppSearchSchema.StringPropertyConfig.JOINABLE_VALUE_TYPE_NONE) { 108 JoinableConfig joinableConfig = JoinableConfig.newBuilder() 109 .setValueType( 110 convertJoinableValueTypeToProto( 111 stringProperty.getJoinableValueType())) 112 .setDeletePropagationType( 113 convertDeletePropagationTypeToProto( 114 stringProperty.getDeletePropagationType())) 115 .build(); 116 builder.setJoinableConfig(joinableConfig); 117 } 118 StringIndexingConfig stringIndexingConfig = StringIndexingConfig.newBuilder() 119 .setTermMatchType(convertTermMatchTypeToProto(stringProperty.getIndexingType())) 120 .setTokenizerType( 121 convertTokenizerTypeToProto(stringProperty.getTokenizerType())) 122 .build(); 123 builder.setStringIndexingConfig(stringIndexingConfig); 124 } else if (property instanceof AppSearchSchema.DocumentPropertyConfig) { 125 AppSearchSchema.DocumentPropertyConfig documentProperty = 126 (AppSearchSchema.DocumentPropertyConfig) property; 127 builder 128 .setSchemaType(documentProperty.getSchemaType()) 129 .setDocumentIndexingConfig( 130 DocumentIndexingConfig.newBuilder() 131 .setIndexNestedProperties( 132 documentProperty.shouldIndexNestedProperties()) 133 .addAllIndexableNestedPropertiesList( 134 documentProperty.getIndexableNestedProperties())); 135 } else if (property instanceof AppSearchSchema.LongPropertyConfig) { 136 AppSearchSchema.LongPropertyConfig longProperty = 137 (AppSearchSchema.LongPropertyConfig) property; 138 // Set integer indexing config only if it is indexable (i.e. not INDEXING_TYPE_NONE). 139 if (longProperty.getIndexingType() 140 != AppSearchSchema.LongPropertyConfig.INDEXING_TYPE_NONE) { 141 IntegerIndexingConfig integerIndexingConfig = IntegerIndexingConfig.newBuilder() 142 .setNumericMatchType( 143 convertNumericMatchTypeToProto(longProperty.getIndexingType())) 144 .build(); 145 builder.setIntegerIndexingConfig(integerIndexingConfig); 146 } 147 builder.setScorableType(toScorableTypeCode(longProperty.isScoringEnabled())); 148 } else if (property instanceof AppSearchSchema.EmbeddingPropertyConfig) { 149 AppSearchSchema.EmbeddingPropertyConfig embeddingProperty = 150 (AppSearchSchema.EmbeddingPropertyConfig) property; 151 // Set embedding indexing config only if it is indexable (i.e. not INDEXING_TYPE_NONE). 152 // Non-indexable embedding property only requires to builder.setDataType, without the 153 // need to set an EmbeddingIndexingConfig. 154 if (embeddingProperty.getIndexingType() 155 != AppSearchSchema.EmbeddingPropertyConfig.INDEXING_TYPE_NONE) { 156 EmbeddingIndexingConfig embeddingIndexingConfig = 157 EmbeddingIndexingConfig.newBuilder() 158 .setEmbeddingIndexingType( 159 convertEmbeddingIndexingTypeToProto( 160 embeddingProperty.getIndexingType())) 161 .setQuantizationType( 162 convertEmbeddingQuantizationTypeToProto( 163 embeddingProperty.getQuantizationType())) 164 .build(); 165 builder.setEmbeddingIndexingConfig(embeddingIndexingConfig); 166 } 167 } else if (property instanceof AppSearchSchema.DoublePropertyConfig) { 168 AppSearchSchema.DoublePropertyConfig doubleProperty = 169 (AppSearchSchema.DoublePropertyConfig) property; 170 builder.setScorableType(toScorableTypeCode(doubleProperty.isScoringEnabled())); 171 } else if (property instanceof AppSearchSchema.BooleanPropertyConfig) { 172 AppSearchSchema.BooleanPropertyConfig booleanProperty = 173 (AppSearchSchema.BooleanPropertyConfig) property; 174 builder.setScorableType(toScorableTypeCode(booleanProperty.isScoringEnabled())); 175 } 176 return builder.build(); 177 } 178 179 /** 180 * Converts a {@link SchemaTypeConfigProto} into an 181 * {@link androidx.appsearch.app.AppSearchSchema}. 182 */ 183 // TODO(b/284356266): Consider handling removal of schema name prefixes in this function. 184 @OptIn(markerClass = ExperimentalAppSearchApi.class) toAppSearchSchema( @onNull SchemaTypeConfigProtoOrBuilder proto)185 public static @NonNull AppSearchSchema toAppSearchSchema( 186 @NonNull SchemaTypeConfigProtoOrBuilder proto) { 187 Preconditions.checkNotNull(proto); 188 AppSearchSchema.Builder builder = 189 new AppSearchSchema.Builder(proto.getSchemaType()); 190 builder.setDescription(proto.getDescription()); 191 List<PropertyConfigProto> properties = proto.getPropertiesList(); 192 for (int i = 0; i < properties.size(); i++) { 193 AppSearchSchema.PropertyConfig propertyConfig = toPropertyConfig(properties.get(i)); 194 builder.addProperty(propertyConfig); 195 } 196 List<String> parentTypes = proto.getParentTypesList(); 197 for (int i = 0; i < parentTypes.size(); i++) { 198 builder.addParentType(parentTypes.get(i)); 199 } 200 return builder.build(); 201 } 202 203 @OptIn(markerClass = ExperimentalAppSearchApi.class) toPropertyConfig( @onNull PropertyConfigProto proto)204 private static AppSearchSchema.@NonNull PropertyConfig toPropertyConfig( 205 @NonNull PropertyConfigProto proto) { 206 Preconditions.checkNotNull(proto); 207 switch (proto.getDataType()) { 208 case STRING: 209 return toStringPropertyConfig(proto); 210 case INT64: 211 return toLongPropertyConfig(proto); 212 case DOUBLE: 213 return new AppSearchSchema.DoublePropertyConfig.Builder(proto.getPropertyName()) 214 .setDescription(proto.getDescription()) 215 .setCardinality(proto.getCardinality().getNumber()) 216 .setScoringEnabled( 217 proto.getScorableType() == 218 PropertyConfigProto.ScorableType.Code.ENABLED) 219 .build(); 220 case BOOLEAN: 221 return new AppSearchSchema.BooleanPropertyConfig.Builder(proto.getPropertyName()) 222 .setDescription(proto.getDescription()) 223 .setCardinality(proto.getCardinality().getNumber()) 224 .setScoringEnabled( 225 proto.getScorableType() == 226 PropertyConfigProto.ScorableType.Code.ENABLED) 227 .build(); 228 case BYTES: 229 return new AppSearchSchema.BytesPropertyConfig.Builder(proto.getPropertyName()) 230 .setDescription(proto.getDescription()) 231 .setCardinality(proto.getCardinality().getNumber()) 232 .build(); 233 case DOCUMENT: 234 return toDocumentPropertyConfig(proto); 235 case VECTOR: 236 return toEmbeddingPropertyConfig(proto); 237 case BLOB_HANDLE: 238 return new AppSearchSchema.BlobHandlePropertyConfig.Builder(proto.getPropertyName()) 239 .setDescription(proto.getDescription()) 240 .setCardinality(proto.getCardinality().getNumber()) 241 .build(); 242 default: 243 throw new IllegalArgumentException( 244 "Invalid dataType code: " + proto.getDataType().getNumber()); 245 } 246 } 247 248 @OptIn(markerClass = ExperimentalAppSearchApi.class) toStringPropertyConfig( @onNull PropertyConfigProto proto)249 private static AppSearchSchema.@NonNull StringPropertyConfig toStringPropertyConfig( 250 @NonNull PropertyConfigProto proto) { 251 AppSearchSchema.StringPropertyConfig.Builder builder = 252 new AppSearchSchema.StringPropertyConfig.Builder(proto.getPropertyName()) 253 .setDescription(proto.getDescription()) 254 .setCardinality(proto.getCardinality().getNumber()) 255 .setJoinableValueType( 256 convertJoinableValueTypeFromProto( 257 proto.getJoinableConfig().getValueType())) 258 .setDeletePropagationType( 259 convertDeletePropagationTypeFromProto( 260 proto.getJoinableConfig().getDeletePropagationType())) 261 .setTokenizerType( 262 proto.getStringIndexingConfig().getTokenizerType().getNumber()); 263 264 // Set indexingType 265 TermMatchType.Code termMatchTypeProto = proto.getStringIndexingConfig().getTermMatchType(); 266 builder.setIndexingType(convertTermMatchTypeFromProto(termMatchTypeProto)); 267 268 return builder.build(); 269 } 270 271 @OptIn(markerClass = ExperimentalAppSearchApi.class) toDocumentPropertyConfig( @onNull PropertyConfigProto proto)272 private static AppSearchSchema.@NonNull DocumentPropertyConfig toDocumentPropertyConfig( 273 @NonNull PropertyConfigProto proto) { 274 AppSearchSchema.DocumentPropertyConfig.Builder builder = 275 new AppSearchSchema.DocumentPropertyConfig.Builder( 276 proto.getPropertyName(), proto.getSchemaType()) 277 .setDescription(proto.getDescription()) 278 .setCardinality(proto.getCardinality().getNumber()) 279 .setShouldIndexNestedProperties( 280 proto.getDocumentIndexingConfig().getIndexNestedProperties()); 281 builder.addIndexableNestedProperties( 282 proto.getDocumentIndexingConfig().getIndexableNestedPropertiesListList()); 283 return builder.build(); 284 } 285 286 @OptIn(markerClass = ExperimentalAppSearchApi.class) toLongPropertyConfig( @onNull PropertyConfigProto proto)287 private static AppSearchSchema.@NonNull LongPropertyConfig toLongPropertyConfig( 288 @NonNull PropertyConfigProto proto) { 289 AppSearchSchema.LongPropertyConfig.Builder builder = 290 new AppSearchSchema.LongPropertyConfig.Builder(proto.getPropertyName()) 291 .setDescription(proto.getDescription()) 292 .setCardinality(proto.getCardinality().getNumber()) 293 .setScoringEnabled( 294 proto.getScorableType() == 295 PropertyConfigProto.ScorableType.Code.ENABLED); 296 // Set indexingType 297 IntegerIndexingConfig.NumericMatchType.Code numericMatchTypeProto = 298 proto.getIntegerIndexingConfig().getNumericMatchType(); 299 builder.setIndexingType(convertNumericMatchTypeFromProto(numericMatchTypeProto)); 300 301 return builder.build(); 302 } 303 304 @OptIn(markerClass = ExperimentalAppSearchApi.class) toEmbeddingPropertyConfig( @onNull PropertyConfigProto proto)305 private static AppSearchSchema.@NonNull EmbeddingPropertyConfig toEmbeddingPropertyConfig( 306 @NonNull PropertyConfigProto proto) { 307 AppSearchSchema.EmbeddingPropertyConfig.Builder builder = 308 new AppSearchSchema.EmbeddingPropertyConfig.Builder(proto.getPropertyName()) 309 .setDescription(proto.getDescription()) 310 .setCardinality(proto.getCardinality().getNumber()); 311 312 // Set indexingType 313 EmbeddingIndexingConfig.EmbeddingIndexingType.Code embeddingIndexingType = 314 proto.getEmbeddingIndexingConfig().getEmbeddingIndexingType(); 315 builder.setIndexingType(convertEmbeddingIndexingTypeFromProto(embeddingIndexingType)); 316 317 // Set quantizationType 318 if (embeddingIndexingType != EmbeddingIndexingConfig.EmbeddingIndexingType.Code.UNKNOWN) { 319 EmbeddingIndexingConfig.QuantizationType.Code embeddingQuantizationType = 320 proto.getEmbeddingIndexingConfig().getQuantizationType(); 321 builder.setQuantizationType( 322 convertEmbeddingQuantizationTypeTypeFromProto(embeddingQuantizationType)); 323 } 324 325 return builder.build(); 326 } 327 convertJoinableValueTypeToProto( @ppSearchSchema.StringPropertyConfig.JoinableValueType int joinableValueType)328 private static JoinableConfig.ValueType.@NonNull Code convertJoinableValueTypeToProto( 329 @AppSearchSchema.StringPropertyConfig.JoinableValueType int joinableValueType) { 330 switch (joinableValueType) { 331 case AppSearchSchema.StringPropertyConfig.JOINABLE_VALUE_TYPE_NONE: 332 return JoinableConfig.ValueType.Code.NONE; 333 case AppSearchSchema.StringPropertyConfig.JOINABLE_VALUE_TYPE_QUALIFIED_ID: 334 return JoinableConfig.ValueType.Code.QUALIFIED_ID; 335 default: 336 throw new IllegalArgumentException( 337 "Invalid joinableValueType: " + joinableValueType); 338 } 339 } 340 341 @AppSearchSchema.StringPropertyConfig.JoinableValueType convertJoinableValueTypeFromProto( JoinableConfig.ValueType.@onNull Code joinableValueType)342 private static int convertJoinableValueTypeFromProto( 343 JoinableConfig.ValueType.@NonNull Code joinableValueType) { 344 switch (joinableValueType) { 345 case NONE: 346 return AppSearchSchema.StringPropertyConfig.JOINABLE_VALUE_TYPE_NONE; 347 case QUALIFIED_ID: 348 return AppSearchSchema.StringPropertyConfig.JOINABLE_VALUE_TYPE_QUALIFIED_ID; 349 } 350 // Avoid crashing in the 'read' path; we should try to interpret the document to the 351 // extent possible. 352 Log.w(TAG, "Invalid joinableValueType: " + joinableValueType.getNumber()); 353 return AppSearchSchema.StringPropertyConfig.JOINABLE_VALUE_TYPE_NONE; 354 } 355 356 @OptIn(markerClass = ExperimentalAppSearchApi.class) 357 private static JoinableConfig.DeletePropagationType.@NonNull Code convertDeletePropagationTypeToProto( @ppSearchSchema.StringPropertyConfig.DeletePropagationType int deletePropagationType)358 convertDeletePropagationTypeToProto( 359 @AppSearchSchema.StringPropertyConfig.DeletePropagationType 360 int deletePropagationType) { 361 switch (deletePropagationType) { 362 case AppSearchSchema.StringPropertyConfig.DELETE_PROPAGATION_TYPE_NONE: 363 return JoinableConfig.DeletePropagationType.Code.NONE; 364 case AppSearchSchema.StringPropertyConfig.DELETE_PROPAGATION_TYPE_PROPAGATE_FROM: 365 return JoinableConfig.DeletePropagationType.Code.PROPAGATE_FROM; 366 default: 367 throw new IllegalArgumentException( 368 "Invalid deletePropagationType: " + deletePropagationType); 369 } 370 } 371 372 @AppSearchSchema.StringPropertyConfig.DeletePropagationType 373 @OptIn(markerClass = ExperimentalAppSearchApi.class) convertDeletePropagationTypeFromProto( JoinableConfig.DeletePropagationType.@onNull Code deletePropagationType)374 private static int convertDeletePropagationTypeFromProto( 375 JoinableConfig.DeletePropagationType.@NonNull Code deletePropagationType) { 376 switch (deletePropagationType) { 377 case NONE: 378 return AppSearchSchema.StringPropertyConfig.DELETE_PROPAGATION_TYPE_NONE; 379 case PROPAGATE_FROM: 380 return AppSearchSchema.StringPropertyConfig.DELETE_PROPAGATION_TYPE_PROPAGATE_FROM; 381 } 382 // Avoid crashing in the 'read' path; we should try to interpret the schema to the 383 // extent possible. 384 Log.w(TAG, "Invalid deletePropagationType: " + deletePropagationType.getNumber()); 385 return AppSearchSchema.StringPropertyConfig.DELETE_PROPAGATION_TYPE_NONE; 386 } 387 convertTermMatchTypeToProto( @ppSearchSchema.StringPropertyConfig.IndexingType int indexingType)388 private static TermMatchType.@NonNull Code convertTermMatchTypeToProto( 389 @AppSearchSchema.StringPropertyConfig.IndexingType int indexingType) { 390 switch (indexingType) { 391 case AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE: 392 return TermMatchType.Code.UNKNOWN; 393 case AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS: 394 return TermMatchType.Code.EXACT_ONLY; 395 case AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES: 396 return TermMatchType.Code.PREFIX; 397 default: 398 throw new IllegalArgumentException("Invalid indexingType: " + indexingType); 399 } 400 } 401 402 @AppSearchSchema.StringPropertyConfig.IndexingType convertTermMatchTypeFromProto(TermMatchType.@onNull Code termMatchType)403 private static int convertTermMatchTypeFromProto(TermMatchType.@NonNull Code termMatchType) { 404 switch (termMatchType) { 405 case UNKNOWN: 406 return AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE; 407 case EXACT_ONLY: 408 return AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_EXACT_TERMS; 409 case PREFIX: 410 return AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_PREFIXES; 411 default: 412 // Avoid crashing in the 'read' path; we should try to interpret the document to the 413 // extent possible. 414 Log.w(TAG, "Invalid indexingType: " + termMatchType.getNumber()); 415 return AppSearchSchema.StringPropertyConfig.INDEXING_TYPE_NONE; 416 } 417 } 418 convertTokenizerTypeToProto( @ppSearchSchema.StringPropertyConfig.TokenizerType int tokenizerType)419 private static StringIndexingConfig.TokenizerType.@NonNull Code convertTokenizerTypeToProto( 420 @AppSearchSchema.StringPropertyConfig.TokenizerType int tokenizerType) { 421 StringIndexingConfig.TokenizerType.Code tokenizerTypeProto = 422 StringIndexingConfig.TokenizerType.Code.forNumber(tokenizerType); 423 if (tokenizerTypeProto == null) { 424 throw new IllegalArgumentException("Invalid tokenizerType: " + tokenizerType); 425 } 426 return tokenizerTypeProto; 427 } 428 429 private static IntegerIndexingConfig.NumericMatchType.@NonNull Code convertNumericMatchTypeToProto( @ppSearchSchema.LongPropertyConfig.IndexingType int indexingType)430 convertNumericMatchTypeToProto( 431 @AppSearchSchema.LongPropertyConfig.IndexingType int indexingType) { 432 switch (indexingType) { 433 case AppSearchSchema.LongPropertyConfig.INDEXING_TYPE_NONE: 434 return IntegerIndexingConfig.NumericMatchType.Code.UNKNOWN; 435 case AppSearchSchema.LongPropertyConfig.INDEXING_TYPE_RANGE: 436 return IntegerIndexingConfig.NumericMatchType.Code.RANGE; 437 default: 438 throw new IllegalArgumentException("Invalid indexingType: " + indexingType); 439 } 440 } 441 442 @AppSearchSchema.LongPropertyConfig.IndexingType convertNumericMatchTypeFromProto( IntegerIndexingConfig.NumericMatchType.@onNull Code numericMatchType)443 private static int convertNumericMatchTypeFromProto( 444 IntegerIndexingConfig.NumericMatchType.@NonNull Code numericMatchType) { 445 switch (numericMatchType) { 446 case UNKNOWN: 447 return AppSearchSchema.LongPropertyConfig.INDEXING_TYPE_NONE; 448 case RANGE: 449 return AppSearchSchema.LongPropertyConfig.INDEXING_TYPE_RANGE; 450 default: 451 // Avoid crashing in the 'read' path; we should try to interpret the document to the 452 // extent possible. 453 Log.w(TAG, "Invalid indexingType: " + numericMatchType.getNumber()); 454 return AppSearchSchema.LongPropertyConfig.INDEXING_TYPE_NONE; 455 } 456 } 457 458 private static EmbeddingIndexingConfig.EmbeddingIndexingType.@NonNull Code convertEmbeddingIndexingTypeToProto( @ppSearchSchema.EmbeddingPropertyConfig.IndexingType int indexingType)459 convertEmbeddingIndexingTypeToProto( 460 @AppSearchSchema.EmbeddingPropertyConfig.IndexingType int indexingType) { 461 switch (indexingType) { 462 case AppSearchSchema.EmbeddingPropertyConfig.INDEXING_TYPE_NONE: 463 return EmbeddingIndexingConfig.EmbeddingIndexingType.Code.UNKNOWN; 464 case AppSearchSchema.EmbeddingPropertyConfig.INDEXING_TYPE_SIMILARITY: 465 return EmbeddingIndexingConfig.EmbeddingIndexingType.Code.LINEAR_SEARCH; 466 default: 467 throw new IllegalArgumentException("Invalid indexingType: " + indexingType); 468 } 469 } 470 471 @AppSearchSchema.EmbeddingPropertyConfig.IndexingType convertEmbeddingIndexingTypeFromProto( EmbeddingIndexingConfig.EmbeddingIndexingType.@onNull Code indexingType)472 private static int convertEmbeddingIndexingTypeFromProto( 473 EmbeddingIndexingConfig.EmbeddingIndexingType.@NonNull Code indexingType) { 474 switch (indexingType) { 475 case UNKNOWN: 476 return AppSearchSchema.EmbeddingPropertyConfig.INDEXING_TYPE_NONE; 477 case LINEAR_SEARCH: 478 return AppSearchSchema.EmbeddingPropertyConfig.INDEXING_TYPE_SIMILARITY; 479 default: 480 // Avoid crashing in the 'read' path; we should try to interpret the document to the 481 // extent possible. 482 Log.w(TAG, "Invalid indexingType: " + indexingType.getNumber()); 483 return AppSearchSchema.EmbeddingPropertyConfig.INDEXING_TYPE_NONE; 484 } 485 } 486 487 @OptIn(markerClass = ExperimentalAppSearchApi.class) 488 private static EmbeddingIndexingConfig.QuantizationType.@NonNull Code convertEmbeddingQuantizationTypeToProto( @ppSearchSchema.EmbeddingPropertyConfig.QuantizationType int quantizationType)489 convertEmbeddingQuantizationTypeToProto( 490 @AppSearchSchema.EmbeddingPropertyConfig.QuantizationType int quantizationType) { 491 switch (quantizationType) { 492 case AppSearchSchema.EmbeddingPropertyConfig.QUANTIZATION_TYPE_NONE: 493 return EmbeddingIndexingConfig.QuantizationType.Code.NONE; 494 case AppSearchSchema.EmbeddingPropertyConfig.QUANTIZATION_TYPE_8_BIT: 495 return EmbeddingIndexingConfig.QuantizationType.Code.QUANTIZE_8_BIT; 496 default: 497 throw new IllegalArgumentException("Invalid quantizationType: " + quantizationType); 498 } 499 } 500 501 @AppSearchSchema.EmbeddingPropertyConfig.QuantizationType 502 @OptIn(markerClass = ExperimentalAppSearchApi.class) convertEmbeddingQuantizationTypeTypeFromProto( EmbeddingIndexingConfig.QuantizationType.@onNull Code quantizationType)503 private static int convertEmbeddingQuantizationTypeTypeFromProto( 504 EmbeddingIndexingConfig.QuantizationType.@NonNull Code quantizationType) { 505 switch (quantizationType) { 506 case NONE: 507 return AppSearchSchema.EmbeddingPropertyConfig.QUANTIZATION_TYPE_NONE; 508 case QUANTIZE_8_BIT: 509 return AppSearchSchema.EmbeddingPropertyConfig.QUANTIZATION_TYPE_8_BIT; 510 default: 511 // Avoid crashing in the 'read' path; we should try to interpret the document to the 512 // extent possible. 513 Log.w(TAG, "Invalid quantizationType: " + quantizationType.getNumber()); 514 return AppSearchSchema.EmbeddingPropertyConfig.QUANTIZATION_TYPE_NONE; 515 } 516 } 517 toScorableTypeCode( boolean isScoringEnabled)518 private static PropertyConfigProto.ScorableType.Code toScorableTypeCode( 519 boolean isScoringEnabled) { 520 if (isScoringEnabled) { 521 return PropertyConfigProto.ScorableType.Code.ENABLED; 522 } else { 523 return PropertyConfigProto.ScorableType.Code.DISABLED; 524 } 525 } 526 } 527