1 /*
2  * Copyright 2025 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.appfunctions
18 
19 import androidx.appfunctions.metadata.AppFunctionMetadataDocument
20 
21 /**
22  * Defines the specifications for filtering and searching app function snapshots.
23  *
24  * @constructor Creates a new instance of [AppFunctionSearchSpec].
25  * @property packageNames A set of package names to filter functions by. Only functions belonging to
26  *   these packages will be considered. Defaults to null, which means this field is ignored when
27  *   filtering.
28  *
29  *   The calling app can only search metadata for functions in packages that it is allowed to query
30  *   via [android.content.pm.PackageManager.canPackageQuery]. If a package is not queryable by the
31  *   calling app, its functions' metadata will not be visible.
32  *
33  * @property schemaCategory The category of the function's schema. Defaults to null, which means
34  *   this field is ignored when filtering.
35  * @property schemaName The name of the function's schema. Defaults to null, which means this field
36  *   is ignored when filtering.
37  * @property minSchemaVersion The minimum version of the function's schema. Functions with a schema
38  *   version equal to or greater than this value will be included when filtering. Defaults to 0,
39  *   which means this field is ignored when filtering. This value cannot be negative.
40  */
41 public class AppFunctionSearchSpec
42 @JvmOverloads
43 constructor(
44     @get:Suppress(
45         // Null value is used to specify that the value was not set by the caller to be consistent
46         // with other string fields.
47         "NullableCollection"
48     )
49     public val packageNames: Set<String>? = null,
50     public val schemaCategory: String? = null,
51     public val schemaName: String? = null,
52     public val minSchemaVersion: Int = 0
53 ) {
54     init {
<lambda>null55         require(minSchemaVersion >= 0) {
56             "The minimum schema version must be a non-negative integer."
57         }
58     }
59 
60     /** Creates a search query for searching [AppFunctionMetadataDocument] from App Search. */
toStaticMetadataAppSearchQuerynull61     internal fun toStaticMetadataAppSearchQuery(): String =
62         buildList<String> {
63                 if (packageNames != null) {
64                     check(packageNames.isNotEmpty()) {
65                         "Cannot filter by empty set of package names."
66                     }
67                     add("packageName:(${getOrQueryExpression(packageNames)})")
68                 }
69 
70                 if (schemaName != null) {
71                     add("schemaName:\"${schemaName}\"")
72                 }
73 
74                 if (schemaCategory != null) {
75                     add("schemaCategory:\"${schemaCategory}\"")
76                 }
77 
78                 if (minSchemaVersion > 0) {
79                     add("schemaVersion>=${minSchemaVersion}")
80                 }
81             }
82             .joinToString(" ")
83 
getOrQueryExpressionnull84     private fun getOrQueryExpression(elements: Set<String>) =
85         elements.joinToString(" OR ") { "\"$it\"" }
86 }
87