2323import com .google .common .collect .ImmutableMap ;
2424import com .google .firebase .internal .NonNull ;
2525import com .google .firebase .internal .Nullable ;
26-
2726import java .math .BigInteger ;
2827import java .nio .charset .StandardCharsets ;
2928import java .security .MessageDigest ;
3635import java .util .regex .Pattern ;
3736import java .util .regex .PatternSyntaxException ;
3837import java .util .stream .Collectors ;
39-
4038import org .slf4j .Logger ;
4139import org .slf4j .LoggerFactory ;
4240
@@ -47,34 +45,36 @@ final class ConditionEvaluator {
4745
4846 /**
4947 * Evaluates server conditions and assigns a boolean value to each condition.
50- *
48+ *
5149 * @param conditions List of conditions which are to be evaluated.
52- * @param context A map with additional metadata used during evaluation.
50+ * @param context A map with additional metadata used during evaluation.
5351 * @return A map of condition to evaluated value.
5452 */
5553 @ NonNull
5654 Map <String , Boolean > evaluateConditions (
57- @ NonNull List <ServerCondition > conditions ,
58- @ Nullable KeysAndValues context ) {
55+ @ NonNull List <ServerCondition > conditions , @ Nullable KeysAndValues context ) {
5956 checkNotNull (conditions , "List of conditions must not be null." );
6057 checkArgument (!conditions .isEmpty (), "List of conditions must not be empty." );
6158 if (context == null || conditions .isEmpty ()) {
6259 return ImmutableMap .of ();
6360 }
64- KeysAndValues evaluationContext = context != null
65- ? context
66- : new KeysAndValues .Builder ().build ();
67-
68- Map <String , Boolean > evaluatedConditions = conditions .stream ()
69- .collect (ImmutableMap .toImmutableMap (
70- ServerCondition ::getName ,
71- condition -> evaluateCondition (condition .getCondition (), evaluationContext , /* nestingLevel= */ 0 )));
61+ KeysAndValues evaluationContext =
62+ context != null ? context : new KeysAndValues .Builder ().build ();
63+
64+ Map <String , Boolean > evaluatedConditions =
65+ conditions .stream ()
66+ .collect (
67+ ImmutableMap .toImmutableMap (
68+ ServerCondition ::getName ,
69+ condition ->
70+ evaluateCondition (
71+ condition .getCondition (), evaluationContext , /* nestingLevel= */ 0 )));
7272
7373 return evaluatedConditions ;
7474 }
7575
76- private boolean evaluateCondition (OneOfCondition condition , KeysAndValues context ,
77- int nestingLevel ) {
76+ private boolean evaluateCondition (
77+ OneOfCondition condition , KeysAndValues context , int nestingLevel ) {
7878 if (nestingLevel > MAX_CONDITION_RECURSION_DEPTH ) {
7979 logger .warn ("Maximum condition recursion depth exceeded." );
8080 return false ;
@@ -97,29 +97,30 @@ private boolean evaluateCondition(OneOfCondition condition, KeysAndValues contex
9797 return false ;
9898 }
9999
100- private boolean evaluateOrCondition (OrCondition condition , KeysAndValues context ,
101- int nestingLevel ) {
100+ private boolean evaluateOrCondition (
101+ OrCondition condition , KeysAndValues context , int nestingLevel ) {
102102 return condition .getConditions ().stream ()
103103 .anyMatch (subCondition -> evaluateCondition (subCondition , context , nestingLevel + 1 ));
104104 }
105105
106- private boolean evaluateAndCondition (AndCondition condition , KeysAndValues context ,
107- int nestingLevel ) {
106+ private boolean evaluateAndCondition (
107+ AndCondition condition , KeysAndValues context , int nestingLevel ) {
108108 return condition .getConditions ().stream ()
109109 .allMatch (subCondition -> evaluateCondition (subCondition , context , nestingLevel + 1 ));
110110 }
111111
112- private boolean evaluateCustomSignalCondition (CustomSignalCondition condition ,
113- KeysAndValues context ) {
112+ private boolean evaluateCustomSignalCondition (
113+ CustomSignalCondition condition , KeysAndValues context ) {
114114 CustomSignalOperator customSignalOperator = condition .getCustomSignalOperator ();
115115 String customSignalKey = condition .getCustomSignalKey ();
116- ImmutableList <String > targetCustomSignalValues = ImmutableList . copyOf (
117- condition .getTargetCustomSignalValues ());
116+ ImmutableList <String > targetCustomSignalValues =
117+ ImmutableList . copyOf ( condition .getTargetCustomSignalValues ());
118118
119119 if (targetCustomSignalValues .isEmpty ()) {
120- logger .warn (String .format (
121- "Values must be assigned to all custom signal fields. Operator:%s, Key:%s, Values:%s" ,
122- customSignalOperator , customSignalKey , targetCustomSignalValues ));
120+ logger .warn (
121+ String .format (
122+ "Values must be assigned to all custom signal fields. Operator:%s, Key:%s, Values:%s" ,
123+ customSignalOperator , customSignalKey , targetCustomSignalValues ));
123124 return false ;
124125 }
125126
@@ -131,64 +132,65 @@ private boolean evaluateCustomSignalCondition(CustomSignalCondition condition,
131132 switch (customSignalOperator ) {
132133 // String operations.
133134 case STRING_CONTAINS :
134- return compareStrings (targetCustomSignalValues , customSignalValue ,
135+ return compareStrings (
136+ targetCustomSignalValues ,
137+ customSignalValue ,
135138 (customSignal , targetSignal ) -> customSignal .contains (targetSignal ));
136139 case STRING_DOES_NOT_CONTAIN :
137- return !compareStrings (targetCustomSignalValues , customSignalValue ,
140+ return !compareStrings (
141+ targetCustomSignalValues ,
142+ customSignalValue ,
138143 (customSignal , targetSignal ) -> customSignal .contains (targetSignal ));
139144 case STRING_EXACTLY_MATCHES :
140- return compareStrings (targetCustomSignalValues , customSignalValue ,
145+ return compareStrings (
146+ targetCustomSignalValues ,
147+ customSignalValue ,
141148 (customSignal , targetSignal ) -> customSignal .equals (targetSignal ));
142149 case STRING_CONTAINS_REGEX :
143- return compareStrings (targetCustomSignalValues , customSignalValue ,
150+ return compareStrings (
151+ targetCustomSignalValues ,
152+ customSignalValue ,
144153 (customSignal , targetSignal ) -> compareStringRegex (customSignal , targetSignal ));
145154
146155 // Numeric operations.
147156 case NUMERIC_LESS_THAN :
148- return compareNumbers (targetCustomSignalValues , customSignalValue ,
149- (result ) -> result < 0 );
157+ return compareNumbers (targetCustomSignalValues , customSignalValue , (result ) -> result < 0 );
150158 case NUMERIC_LESS_EQUAL :
151- return compareNumbers (targetCustomSignalValues , customSignalValue ,
152- (result ) -> result <= 0 );
159+ return compareNumbers (targetCustomSignalValues , customSignalValue , (result ) -> result <= 0 );
153160 case NUMERIC_EQUAL :
154- return compareNumbers (targetCustomSignalValues , customSignalValue ,
155- (result ) -> result == 0 );
161+ return compareNumbers (targetCustomSignalValues , customSignalValue , (result ) -> result == 0 );
156162 case NUMERIC_NOT_EQUAL :
157- return compareNumbers (targetCustomSignalValues , customSignalValue ,
158- (result ) -> result != 0 );
163+ return compareNumbers (targetCustomSignalValues , customSignalValue , (result ) -> result != 0 );
159164 case NUMERIC_GREATER_THAN :
160- return compareNumbers (targetCustomSignalValues , customSignalValue ,
161- (result ) -> result > 0 );
165+ return compareNumbers (targetCustomSignalValues , customSignalValue , (result ) -> result > 0 );
162166 case NUMERIC_GREATER_EQUAL :
163- return compareNumbers (targetCustomSignalValues , customSignalValue ,
164- (result ) -> result >= 0 );
167+ return compareNumbers (targetCustomSignalValues , customSignalValue , (result ) -> result >= 0 );
165168
166169 // Semantic operations.
167170 case SEMANTIC_VERSION_EQUAL :
168- return compareSemanticVersions (targetCustomSignalValues , customSignalValue ,
169- (result ) -> result == 0 );
171+ return compareSemanticVersions (
172+ targetCustomSignalValues , customSignalValue , (result ) -> result == 0 );
170173 case SEMANTIC_VERSION_GREATER_EQUAL :
171- return compareSemanticVersions (targetCustomSignalValues , customSignalValue ,
172- (result ) -> result >= 0 );
174+ return compareSemanticVersions (
175+ targetCustomSignalValues , customSignalValue , (result ) -> result >= 0 );
173176 case SEMANTIC_VERSION_GREATER_THAN :
174- return compareSemanticVersions (targetCustomSignalValues , customSignalValue ,
175- (result ) -> result > 0 );
177+ return compareSemanticVersions (
178+ targetCustomSignalValues , customSignalValue , (result ) -> result > 0 );
176179 case SEMANTIC_VERSION_LESS_EQUAL :
177- return compareSemanticVersions (targetCustomSignalValues , customSignalValue ,
178- (result ) -> result <= 0 );
180+ return compareSemanticVersions (
181+ targetCustomSignalValues , customSignalValue , (result ) -> result <= 0 );
179182 case SEMANTIC_VERSION_LESS_THAN :
180- return compareSemanticVersions (targetCustomSignalValues , customSignalValue ,
181- (result ) -> result < 0 );
183+ return compareSemanticVersions (
184+ targetCustomSignalValues , customSignalValue , (result ) -> result < 0 );
182185 case SEMANTIC_VERSION_NOT_EQUAL :
183- return compareSemanticVersions (targetCustomSignalValues , customSignalValue ,
184- (result ) -> result != 0 );
186+ return compareSemanticVersions (
187+ targetCustomSignalValues , customSignalValue , (result ) -> result != 0 );
185188 default :
186189 return false ;
187190 }
188191 }
189192
190- private boolean evaluatePercentCondition (PercentCondition condition ,
191- KeysAndValues context ) {
193+ private boolean evaluatePercentCondition (PercentCondition condition , KeysAndValues context ) {
192194 if (!context .containsKey ("randomizationId" )) {
193195 logger .warn ("Percentage operation must not be performed without randomizationId" );
194196 return false ;
@@ -198,18 +200,16 @@ private boolean evaluatePercentCondition(PercentCondition condition,
198200
199201 // The micro-percent interval to be used with the BETWEEN operator.
200202 MicroPercentRange microPercentRange = condition .getMicroPercentRange ();
201- int microPercentUpperBound = microPercentRange != null
202- ? microPercentRange .getMicroPercentUpperBound ()
203- : 0 ;
204- int microPercentLowerBound = microPercentRange != null
205- ? microPercentRange .getMicroPercentLowerBound ()
206- : 0 ;
203+ int microPercentUpperBound =
204+ microPercentRange != null ? microPercentRange .getMicroPercentUpperBound () : 0 ;
205+ int microPercentLowerBound =
206+ microPercentRange != null ? microPercentRange .getMicroPercentLowerBound () : 0 ;
207207 // The limit of percentiles to target in micro-percents when using the
208208 // LESS_OR_EQUAL and GREATER_THAN operators. The value must be in the range [0
209209 // and 100000000].
210210 int microPercent = condition .getMicroPercent ();
211- BigInteger microPercentile = getMicroPercentile ( condition . getSeed (),
212- context .get ("randomizationId" ));
211+ BigInteger microPercentile =
212+ getMicroPercentile ( condition . getSeed (), context .get ("randomizationId" ));
213213 switch (operator ) {
214214 case LESS_OR_EQUAL :
215215 return microPercentile .compareTo (BigInteger .valueOf (microPercent )) <= 0 ;
@@ -247,9 +247,12 @@ private BigInteger hashSeededRandomizationId(String seededRandomizationId) {
247247 }
248248 }
249249
250- private boolean compareStrings (ImmutableList <String > targetValues , String customSignal ,
250+ private boolean compareStrings (
251+ ImmutableList <String > targetValues ,
252+ String customSignal ,
251253 BiPredicate <String , String > compareFunction ) {
252- return targetValues .stream ().anyMatch (targetValue -> compareFunction .test (customSignal , targetValue ));
254+ return targetValues .stream ()
255+ .anyMatch (targetValue -> compareFunction .test (customSignal , targetValue ));
253256 }
254257
255258 private boolean compareStringRegex (String customSignal , String targetSignal ) {
@@ -260,12 +263,13 @@ private boolean compareStringRegex(String customSignal, String targetSignal) {
260263 }
261264 }
262265
263- private boolean compareNumbers (ImmutableList < String > targetValues , String customSignal ,
264- IntPredicate compareFunction ) {
266+ private boolean compareNumbers (
267+ ImmutableList < String > targetValues , String customSignal , IntPredicate compareFunction ) {
265268 if (targetValues .size () != 1 ) {
266- logger .warn (String .format (
267- "Target values must contain 1 element for numeric operations. Target Value: %s" ,
268- targetValues ));
269+ logger .warn (
270+ String .format (
271+ "Target values must contain 1 element for numeric operations. Target Value: %s" ,
272+ targetValues ));
269273 return false ;
270274 }
271275
@@ -275,23 +279,22 @@ private boolean compareNumbers(ImmutableList<String> targetValues, String custom
275279 int comparisonResult = Double .compare (customSignalDouble , targetValue );
276280 return compareFunction .test (comparisonResult );
277281 } catch (NumberFormatException e ) {
278- logger .warn ("Error parsing numeric values: customSignal=%s, targetValue=%s" ,
282+ logger .warn (
283+ "Error parsing numeric values: customSignal=%s, targetValue=%s" ,
279284 customSignal , targetValues .get (0 ), e );
280285 return false ;
281286 }
282287 }
283288
284- private boolean compareSemanticVersions (ImmutableList <String > targetValues ,
285- String customSignal ,
286- IntPredicate compareFunction ) {
289+ private boolean compareSemanticVersions (
290+ ImmutableList <String > targetValues , String customSignal , IntPredicate compareFunction ) {
287291 if (targetValues .size () != 1 ) {
288292 logger .warn (String .format ("Target values must contain 1 element for semantic operation." ));
289293 return false ;
290294 }
291295
292296 String targetValueString = targetValues .get (0 );
293- if (!validateSemanticVersion (targetValueString )
294- || !validateSemanticVersion (customSignal )) {
297+ if (!validateSemanticVersion (targetValueString ) || !validateSemanticVersion (customSignal )) {
295298 return false ;
296299 }
297300
@@ -300,7 +303,8 @@ private boolean compareSemanticVersions(ImmutableList<String> targetValues,
300303
301304 int maxLength = 5 ;
302305 if (targetVersion .size () > maxLength || customSignalVersion .size () > maxLength ) {
303- logger .warn ("Semantic version max length(%s) exceeded. Target: %s, Custom Signal: %s" ,
306+ logger .warn (
307+ "Semantic version max length(%s) exceeded. Target: %s, Custom Signal: %s" ,
304308 maxLength , targetValueString , customSignal );
305309 return false ;
306310 }
0 commit comments