4242import java .util .Map ;
4343import java .util .Objects ;
4444import java .util .Set ;
45+ import java .util .stream .Collectors ;
46+ import java .util .stream .Stream ;
4547import org .jspecify .annotations .Nullable ;
4648
4749/** A build-through cache of message evaluators keyed off the provided descriptor. */
@@ -50,6 +52,10 @@ final class EvaluatorBuilder {
5052 FieldPathUtils .fieldPathElement (
5153 FieldRules .getDescriptor ().findFieldByNumber (FieldRules .CEL_FIELD_NUMBER ));
5254
55+ private static final FieldPathElement CEL_EXPRESSION_FIELD_PATH_ELEMENT =
56+ FieldPathUtils .fieldPathElement (
57+ FieldRules .getDescriptor ().findFieldByNumber (FieldRules .CEL_EXPRESSION_FIELD_NUMBER ));
58+
5359 private volatile Map <Descriptor , MessageEvaluator > evaluatorCache = Collections .emptyMap ();
5460
5561 private final Cel cel ;
@@ -187,7 +193,11 @@ private void buildMessage(Descriptor desc, MessageEvaluator msgEval)
187193 private void processMessageExpressions (
188194 Descriptor desc , MessageRules msgRules , MessageEvaluator msgEval , DynamicMessage message )
189195 throws CompilationException {
190- List <Rule > celList = msgRules .getCelList ();
196+ List <Rule > celList =
197+ Stream .concat (
198+ expressionsToRules (msgRules .getCelExpressionList ()).stream (),
199+ msgRules .getCelList ().stream ())
200+ .collect (Collectors .toList ());
191201 if (celList .isEmpty ()) {
192202 return ;
193203 }
@@ -196,7 +206,7 @@ private void processMessageExpressions(
196206 .addMessageTypes (message .getDescriptorForType ())
197207 .addVar (Variable .THIS_NAME , StructTypeReference .create (desc .getFullName ()))
198208 .build ();
199- List <CompiledProgram > compiledPrograms = compileRules (celList , finalCel , false );
209+ List <CompiledProgram > compiledPrograms = compileRules (celList , finalCel , null );
200210 if (compiledPrograms .isEmpty ()) {
201211 throw new CompilationException ("compile returned null" );
202212 }
@@ -354,7 +364,8 @@ private void processFieldExpressions(
354364 FieldDescriptor fieldDescriptor , FieldRules fieldRules , ValueEvaluator valueEvaluatorEval )
355365 throws CompilationException {
356366 List <Rule > rulesCelList = fieldRules .getCelList ();
357- if (rulesCelList .isEmpty ()) {
367+ List <String > exprList = fieldRules .getCelExpressionList ();
368+ if (rulesCelList .isEmpty () && exprList .isEmpty ()) {
358369 return ;
359370 }
360371 CelBuilder builder = cel .toCelBuilder ();
@@ -367,7 +378,16 @@ private void processFieldExpressions(
367378 builder = builder .addMessageTypes (fieldDescriptor .getMessageType ());
368379 }
369380 Cel finalCel = builder .build ();
370- List <CompiledProgram > compiledPrograms = compileRules (rulesCelList , finalCel , true );
381+ List <CompiledProgram > compiledPrograms = new ArrayList <>();
382+ if (!rulesCelList .isEmpty ()) {
383+ compiledPrograms .addAll (compileRules (rulesCelList , finalCel , CEL_FIELD_PATH_ELEMENT ));
384+ }
385+ if (!exprList .isEmpty ()) {
386+ compiledPrograms .addAll (
387+ compileRules (
388+ expressionsToRules (exprList ), finalCel , CEL_EXPRESSION_FIELD_PATH_ELEMENT ));
389+ }
390+
371391 if (!compiledPrograms .isEmpty ()) {
372392 valueEvaluatorEval .append (new CelPrograms (valueEvaluatorEval , compiledPrograms ));
373393 }
@@ -510,19 +530,18 @@ private void processRepeatedRules(
510530 valueEvaluatorEval .append (listEval );
511531 }
512532
513- private static List <CompiledProgram > compileRules (List <Rule > rules , Cel cel , boolean isField )
533+ private static List <CompiledProgram > compileRules (
534+ List <Rule > rules , Cel cel , @ Nullable FieldPathElement fieldPathElement )
514535 throws CompilationException {
515536 List <Expression > expressions = Expression .fromRules (rules );
516537 List <CompiledProgram > compiledPrograms = new ArrayList <>();
517538 for (int i = 0 ; i < expressions .size (); i ++) {
518539 Expression expression = expressions .get (i );
519540 AstExpression astExpression = AstExpression .newAstExpression (cel , expression );
520541 @ Nullable FieldPath rulePath = null ;
521- if (isField ) {
542+ if (fieldPathElement != null ) {
522543 rulePath =
523- FieldPath .newBuilder ()
524- .addElements (CEL_FIELD_PATH_ELEMENT .toBuilder ().setIndex (i ))
525- .build ();
544+ FieldPath .newBuilder ().addElements (fieldPathElement .toBuilder ().setIndex (i )).build ();
526545 }
527546 try {
528547 compiledPrograms .add (
@@ -538,5 +557,11 @@ private static List<CompiledProgram> compileRules(List<Rule> rules, Cel cel, boo
538557 }
539558 return compiledPrograms ;
540559 }
560+
561+ private static List <Rule > expressionsToRules (List <String > expressions ) {
562+ return expressions .stream ()
563+ .map (expr -> Rule .newBuilder ().setExpression (expr ).build ())
564+ .collect (Collectors .toList ());
565+ }
541566 }
542567}
0 commit comments