• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 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 android.app.appsearch.ast.operators;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.IntDef;
21 import android.app.appsearch.PropertyPath;
22 import android.app.appsearch.ast.Node;
23 
24 import com.android.appsearch.flags.Flags;
25 import com.android.internal.util.Preconditions;
26 
27 import org.jspecify.annotations.NonNull;
28 
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 import java.util.Objects;
32 
33 /**
34  * {@link Node} that represents a numeric search expression between a property and a numeric value.
35  *
36  * <p>All numeric search expressions are represented by this {@link Node} by passing in a {@link
37  * Comparator} that represent one of the comparator operators available in the query language, a
38  * {@link PropertyPath} representing the property, and a numeric value to compare the property
39  * against.
40  *
41  * <p>This node represents comparators as defined in the <a
42  * href="https://google.aip.dev/assets/misc/ebnf-filtering.txt">Google AIP EBNF Filtering
43  * Definition</a>.
44  */
45 @FlaggedApi(Flags.FLAG_ENABLE_ABSTRACT_SYNTAX_TREES)
46 public final class ComparatorNode implements Node {
47     /**
48      * Enums representing different comparators for numeric search expressions in the query
49      * language.
50      *
51      * @hide
52      */
53     @Retention(RetentionPolicy.SOURCE)
54     @IntDef(
55             value = {
56                 EQUALS,
57                 LESS_THAN,
58                 LESS_EQUALS,
59                 GREATER_THAN,
60                 GREATER_EQUALS,
61             })
62     public @interface Comparator {}
63 
64     public static final int EQUALS = 0;
65     public static final int LESS_THAN = 1;
66     public static final int LESS_EQUALS = 2;
67     public static final int GREATER_THAN = 3;
68     public static final int GREATER_EQUALS = 4;
69 
70     private static final int MAX_COMPARATOR_VALUE = GREATER_EQUALS;
71 
72     private @Comparator int mComparator;
73     private PropertyPath mPropertyPath;
74     private long mValue;
75 
76     /**
77      * Construct a {@link Node} representing a numeric search expression between a property and a
78      * numeric value.
79      *
80      * @param comparator An {@code IntDef} representing what comparison is being made.
81      * @param propertyPath A {@link PropertyPath} that is property being compared i.e. the left hand
82      *     side of the comparison.
83      * @param value The numeric value being compared i.e. the right hand side of the comparison.
84      */
ComparatorNode( @omparator int comparator, @NonNull PropertyPath propertyPath, long value)85     public ComparatorNode(
86             @Comparator int comparator, @NonNull PropertyPath propertyPath, long value) {
87         Preconditions.checkArgumentInRange(
88                 comparator, EQUALS, MAX_COMPARATOR_VALUE, "Comparator intDef");
89         mComparator = comparator;
90         mPropertyPath = Objects.requireNonNull(propertyPath);
91         mValue = value;
92     }
93 
94     /** Get the {@code @Comparator} used in the comparison. */
95     @Comparator
getComparator()96     public int getComparator() {
97         return mComparator;
98     }
99 
100     /**
101      * Get the {@code PropertyPath} being compared.
102      *
103      * <p>I.e. left hand side of the comparison represented by this node.
104      */
getPropertyPath()105     public @NonNull PropertyPath getPropertyPath() {
106         return mPropertyPath;
107     }
108 
109     /**
110      * Get the numeric value being compared.
111      *
112      * <p>I.e. the right hand side of the comparison represented by this node.
113      */
getValue()114     public long getValue() {
115         return mValue;
116     }
117 
118     /** Set the {@code @Comparator} being used to compare the {@code PropertyPath} and value. */
setComparator(@omparator int comparator)119     public void setComparator(@Comparator int comparator) {
120         Preconditions.checkArgumentInRange(
121                 comparator, EQUALS, MAX_COMPARATOR_VALUE, "Comparator intDef");
122         mComparator = comparator;
123     }
124 
125     /** Set the {@code PropertyPath} being compared, i.e. the left side of the comparison. */
setPropertyPath(@onNull PropertyPath propertyPath)126     public void setPropertyPath(@NonNull PropertyPath propertyPath) {
127         mPropertyPath = Objects.requireNonNull(propertyPath);
128     }
129 
130     /** Set the numeric value being compared, i.e. the right side of the comparison. */
setValue(long value)131     public void setValue(long value) {
132         mValue = value;
133     }
134 
135     /**
136      * Get the query string representation of {@link ComparatorNode}.
137      *
138      * <p>The string representation is the string representation of the property path joined from
139      * the left to the value being compared with the string representation of the {@link
140      * Comparator}.
141      */
142     @Override
toString()143     public @NonNull String toString() {
144         String comparatorString = "";
145         switch (mComparator) {
146             case ComparatorNode.EQUALS:
147                 comparatorString = "==";
148                 break;
149             case ComparatorNode.LESS_THAN:
150                 comparatorString = "<";
151                 break;
152             case ComparatorNode.LESS_EQUALS:
153                 comparatorString = "<=";
154                 break;
155             case ComparatorNode.GREATER_THAN:
156                 comparatorString = ">";
157                 break;
158             case ComparatorNode.GREATER_EQUALS:
159                 comparatorString = ">=";
160         }
161         // Equivalent in behavior but more efficient than
162         // String.format("(%s %s %s)", mPropertyPath, comparatorString, mValue);
163         return "(" + mPropertyPath + " " + comparatorString + " " + mValue + ")";
164     }
165 
166     @Override
equals(Object o)167     public boolean equals(Object o) {
168         if (this == o) return true;
169         if (!(o instanceof ComparatorNode)) return false;
170         ComparatorNode that = (ComparatorNode) o;
171         return mComparator == that.mComparator
172                 && mValue == that.mValue
173                 && Objects.equals(mPropertyPath, that.mPropertyPath);
174     }
175 
176     @Override
hashCode()177     public int hashCode() {
178         return Objects.hash(mComparator, mPropertyPath, mValue);
179     }
180 }
181