1 /*
2  * Copyright 2023 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 package androidx.appsearch.compiler.annotationwrapper
17 
18 import androidx.appsearch.compiler.IntrospectionHelper
19 import androidx.appsearch.compiler.ProcessingException
20 import com.squareup.javapoet.ClassName
21 import javax.lang.model.element.AnnotationMirror
22 
23 /**
24  * An instance of an annotation for a data property e.g. `@Document.StringProperty`.
25  *
26  * Is one of:
27  * * [StringPropertyAnnotation]
28  * * [DocumentPropertyAnnotation]
29  * * [LongPropertyAnnotation]
30  * * [DoublePropertyAnnotation]
31  * * [BooleanPropertyAnnotation]
32  * * [BytesPropertyAnnotation]
33  * * [EmbeddingPropertyAnnotation]
34  * * [BlobHandlePropertyAnnotation]
35  */
36 abstract class DataPropertyAnnotation
37 protected constructor(
38     override val className: ClassName,
39 
40     /**
41      * The class used to configure data properties of this kind.
42      *
43      * For example, [androidx.appsearch.app.AppSearchSchema.StringPropertyConfig] for
44      * [StringPropertyAnnotation].
45      */
46     val configClassName: ClassName,
47     override val genericDocGetterName: String,
48 
49     /**
50      * The corresponding getter within [androidx.appsearch.app.GenericDocument] that returns an
51      * array.
52      *
53      * For example, `getPropertyStringArray` for a [StringPropertyAnnotation].
54      */
55     val genericDocArrayGetterName: String,
56     override val genericDocSetterName: String,
57 ) : PropertyAnnotation {
58     enum class Kind {
59         STRING_PROPERTY,
60         DOCUMENT_PROPERTY,
61         LONG_PROPERTY,
62         DOUBLE_PROPERTY,
63         BOOLEAN_PROPERTY,
64         BYTES_PROPERTY,
65         EMBEDDING_PROPERTY,
66         BLOB_HANDLE_PROPERTY
67     }
68 
69     companion object {
70         /**
71          * Attempts to parse an [AnnotationMirror] into a [DataPropertyAnnotation], or null.
72          *
73          * @param defaultName The name to use for the annotated property in case the annotation
74          *   params do not mention an explicit name.
75          * @throws ProcessingException If the [AnnotationMirror] is a valid [DataPropertyAnnotation]
76          *   but its params are malformed e.g. point to an illegal serializer class etc.
77          */
78         @Throws(ProcessingException::class)
79         @JvmStatic
tryParsenull80         fun tryParse(
81             annotation: AnnotationMirror,
82             defaultName: String,
83             helper: IntrospectionHelper
84         ): DataPropertyAnnotation? {
85             val annotationParams = helper.getAnnotationParams(annotation)
86             val qualifiedClassName = annotation.annotationType.toString()
87             return when (qualifiedClassName) {
88                 BooleanPropertyAnnotation.CLASS_NAME.canonicalName() ->
89                     BooleanPropertyAnnotation.parse(annotationParams, defaultName)
90                 BytesPropertyAnnotation.CLASS_NAME.canonicalName() ->
91                     BytesPropertyAnnotation.parse(annotationParams, defaultName)
92                 DocumentPropertyAnnotation.CLASS_NAME.canonicalName() ->
93                     DocumentPropertyAnnotation.parse(annotationParams, defaultName)
94                 DoublePropertyAnnotation.CLASS_NAME.canonicalName() ->
95                     DoublePropertyAnnotation.parse(annotationParams, defaultName)
96                 LongPropertyAnnotation.CLASS_NAME.canonicalName() ->
97                     LongPropertyAnnotation.parse(annotationParams, defaultName)
98                 StringPropertyAnnotation.CLASS_NAME.canonicalName() ->
99                     StringPropertyAnnotation.parse(annotationParams, defaultName)
100                 EmbeddingPropertyAnnotation.CLASS_NAME.canonicalName() ->
101                     EmbeddingPropertyAnnotation.parse(annotationParams, defaultName)
102                 BlobHandlePropertyAnnotation.CLASS_NAME.canonicalName() ->
103                     BlobHandlePropertyAnnotation.parse(annotationParams, defaultName)
104                 else -> return null
105             }
106         }
107     }
108 
109     /** The serialized name for the property in the database. */
110     abstract val name: String
111 
112     /** Denotes whether this property must be specified for the document to be valid. */
113     abstract val isRequired: Boolean
114 
115     /** The [Kind] of [DataPropertyAnnotation]. */
116     abstract val dataPropertyKind: Kind
117 
118     override val propertyKind
119         get() = PropertyAnnotation.Kind.DATA_PROPERTY
120 }
121