1717
1818import  com .fasterxml .jackson .databind .JsonNode ;
1919import  com .fasterxml .jackson .databind .node .ArrayNode ;
20- import  io .serverlessworkflow .impl .ContextAware ;
2120import  io .serverlessworkflow .impl .TaskContext ;
2221import  io .serverlessworkflow .impl .WorkflowContext ;
2322import  io .serverlessworkflow .impl .json .JsonUtils ;
24- import  java .lang .reflect .Field ;
25- import  java .util .ArrayList ;
26- import  java .util .Collection ;
27- import  java .util .HashSet ;
28- import  java .util .Map ;
29- import  java .util .Optional ;
30- import  java .util .concurrent .ConcurrentHashMap ;
3123import  java .util .function .Supplier ;
3224import  net .thisptr .jackson .jq .Output ;
3325import  net .thisptr .jackson .jq .Scope ;
3426import  net .thisptr .jackson .jq .Version ;
3527import  net .thisptr .jackson .jq .exception .JsonQueryException ;
3628import  net .thisptr .jackson .jq .internal .javacc .ExpressionParser ;
37- import  net .thisptr .jackson .jq .internal .tree .FunctionCall ;
38- import  net .thisptr .jackson .jq .internal .tree .StringInterpolation ;
39- import  net .thisptr .jackson .jq .internal .tree .binaryop .BinaryOperatorExpression ;
40- import  org .slf4j .Logger ;
41- import  org .slf4j .LoggerFactory ;
4229
4330public  class  JQExpression  implements  Expression  {
4431
45-   private  static  final  Logger  logger  = LoggerFactory .getLogger (JQExpression .class );
46-   private  final  Map <Class <? extends  net .thisptr .jackson .jq .Expression >, Collection <Field >>
47-       declaredFieldsMap  = new  ConcurrentHashMap <>();
48-   private  final  Map <Class <? extends  net .thisptr .jackson .jq .Expression >, Collection <Field >>
49-       allFieldsMap  = new  ConcurrentHashMap <>();
50- 
5132  private  final  Supplier <Scope > scope ;
5233  private  final  String  expr ;
5334
5435  private  net .thisptr .jackson .jq .Expression  internalExpr ;
55-   private  static  Field  rhsField ;
56- 
57-   static  {
58-     try  {
59-       rhsField  = BinaryOperatorExpression .class .getDeclaredField ("rhs" );
60-       rhsField .setAccessible (true );
61-     } catch  (ReflectiveOperationException  e ) {
62-       logger .warn ("Unexpected exception while resolving rhs field" , e );
63-     }
64-   }
6536
6637  public  JQExpression (Supplier <Scope > scope , String  expr , Version  version )
6738      throws  JsonQueryException  {
6839    this .expr  = expr ;
6940    this .scope  = scope ;
7041    this .internalExpr  = compile (version );
71-     checkFunctionCall (internalExpr );
7242  }
7343
7444  private  net .thisptr .jackson .jq .Expression  compile (Version  version ) throws  JsonQueryException  {
75-     net .thisptr .jackson .jq .Expression  expression ;
76-     try  {
77-       expression  = ExpressionParser .compile (expr , version );
78-     } catch  (JsonQueryException  ex ) {
79-       expression  = handleStringInterpolation (version ).orElseThrow (() -> ex );
80-     }
81-     checkFunctionCall (expression );
82-     return  expression ;
83-   }
84- 
85-   private  Optional <net .thisptr .jackson .jq .Expression > handleStringInterpolation (Version  version ) {
86-     if  (!expr .startsWith ("\" " )) {
87-       try  {
88-         net .thisptr .jackson .jq .Expression  expression  =
89-             ExpressionParser .compile ("\" "  + expr  + "\" " , version );
90-         if  (expression  instanceof  StringInterpolation ) {
91-           return  Optional .of (expression );
92-         }
93-       } catch  (JsonQueryException  ex ) {
94-         // ignoring it 
95-       }
96-     }
97-     return  Optional .empty ();
45+     return  ExpressionParser .compile (expr , version );
9846  }
9947
10048  private  interface  TypedOutput <T > extends  Output  {
10149    T  getResult ();
10250  }
10351
104-   @ SuppressWarnings ("unchecked" )
105-   private  <T > TypedOutput <T > output (Class <T > returnClass ) {
106-     TypedOutput <T > out ;
107-     if  (String .class .isAssignableFrom (returnClass )) {
108-       out  = (TypedOutput <T >) new  StringOutput ();
109-     } else  if  (Collection .class .isAssignableFrom (returnClass )) {
110-       out  = (TypedOutput <T >) new  CollectionOutput ();
111-     } else  {
112-       out  = (TypedOutput <T >) new  JsonNodeOutput ();
113-     }
114-     return  out ;
115-   }
116- 
117-   private  static  class  StringOutput  implements  TypedOutput <String > {
118-     StringBuilder  sb  = new  StringBuilder ();
119- 
120-     @ Override 
121-     public  void  emit (JsonNode  out ) throws  JsonQueryException  {
122-       if  (sb .length () > 0 ) {
123-         sb .append (' ' );
124-       }
125-       if  (!out .isNull () && out .asText () != null ) {
126-         sb .append (out .asText ());
127-       }
128-     }
129- 
130-     @ Override 
131-     public  String  getResult () {
132-       return  sb .toString ();
133-     }
134-   }
135- 
136-   private  static  class  CollectionOutput  implements  TypedOutput <Collection <Object >> {
137-     Collection <Object > result  = new  ArrayList <>();
138- 
139-     @ SuppressWarnings ("unchecked" )
140-     @ Override 
141-     public  void  emit (JsonNode  out ) throws  JsonQueryException  {
142-       Object  obj  = JsonUtils .toJavaValue (out );
143-       if  (obj  instanceof  Collection ) result .addAll ((Collection <Object >) obj );
144-       else  {
145-         result .add (obj );
146-       }
147-     }
148- 
149-     @ Override 
150-     public  Collection <Object > getResult () {
151-       return  result ;
152-     }
153-   }
154- 
15552  private  static  class  JsonNodeOutput  implements  TypedOutput <JsonNode > {
15653
15754    private  JsonNode  result ;
@@ -179,7 +76,7 @@ public JsonNode getResult() {
17976
18077  @ Override 
18178  public  JsonNode  eval (WorkflowContext  workflow , TaskContext <?> task , JsonNode  node ) {
182-     TypedOutput <JsonNode > output  = output ( JsonNode . class );
79+     TypedOutput <JsonNode > output  = new   JsonNodeOutput ( );
18380    try  {
18481      internalExpr .apply (createScope (workflow , task ), node , output );
18582      return  output .getResult ();
@@ -190,74 +87,8 @@ public JsonNode eval(WorkflowContext workflow, TaskContext<?> task, JsonNode nod
19087  }
19188
19289  private  Scope  createScope (WorkflowContext  workflow , TaskContext <?> task ) {
193-     return  createScope (scope .get (), task );
194-   }
195- 
196-   private  Scope  createScope (Scope  parentScope , ContextAware  context ) {
197-     Scope  childScope  = Scope .newChildScope (parentScope );
198-     context .variables ().forEach ((k , v ) -> childScope .setValue (k , JsonUtils .fromValue (v )));
90+     Scope  childScope  = Scope .newChildScope (scope .get ());
91+     task .variables ().forEach ((k , v ) -> childScope .setValue (k , JsonUtils .fromValue (v )));
19992    return  childScope ;
20093  }
201- 
202-   private  void  checkFunctionCall (net .thisptr .jackson .jq .Expression  toCheck )
203-       throws  JsonQueryException  {
204-     if  (toCheck  instanceof  FunctionCall ) {
205-       toCheck .apply (scope .get (), JsonUtils .mapper ().createObjectNode (), out  -> {});
206-     } else  if  (toCheck  instanceof  BinaryOperatorExpression ) {
207-       if  (rhsField  != null ) {
208-         try  {
209-           checkFunctionCall ((net .thisptr .jackson .jq .Expression ) rhsField .get (toCheck ));
210-         } catch  (ReflectiveOperationException  e ) {
211-           logger .warn (
212-               "Ignoring unexpected error {} while accesing field {} for class{} and expression {}" ,
213-               e .getMessage (),
214-               rhsField .getName (),
215-               toCheck .getClass (),
216-               expr );
217-         }
218-       }
219-     } else  if  (toCheck  != null ) {
220-       for  (Field  f  : getAllExprFields (toCheck ))
221-         try  {
222-           checkFunctionCall ((net .thisptr .jackson .jq .Expression ) f .get (toCheck ));
223-         } catch  (ReflectiveOperationException  e ) {
224-           logger .warn (
225-               "Ignoring unexpected error {} while accesing field {} for class{} and expression {}" ,
226-               e .getMessage (),
227-               f .getName (),
228-               toCheck .getClass (),
229-               expr );
230-         }
231-     }
232-   }
233- 
234-   private  Collection <Field > getAllExprFields (net .thisptr .jackson .jq .Expression  toCheck ) {
235-     return  allFieldsMap .computeIfAbsent (toCheck .getClass (), this ::getAllExprFields );
236-   }
237- 
238-   private  Collection <Field > getAllExprFields (
239-       Class <? extends  net .thisptr .jackson .jq .Expression > clazz ) {
240-     Collection <Field > fields  = new  HashSet <>();
241-     Class <?> currentClass  = clazz ;
242-     do  {
243-       fields .addAll (
244-           declaredFieldsMap .computeIfAbsent (
245-               currentClass .asSubclass (net .thisptr .jackson .jq .Expression .class ),
246-               this ::getDeclaredExprFields ));
247-       currentClass  = currentClass .getSuperclass ();
248-     } while  (net .thisptr .jackson .jq .Expression .class .isAssignableFrom (currentClass ));
249-     return  fields ;
250-   }
251- 
252-   private  Collection <Field > getDeclaredExprFields (
253-       Class <? extends  net .thisptr .jackson .jq .Expression > clazz ) {
254-     Collection <Field > fields  = new  HashSet <>();
255-     for  (Field  f  : clazz .getDeclaredFields ()) {
256-       if  (net .thisptr .jackson .jq .Expression .class .isAssignableFrom (f .getType ())) {
257-         f .setAccessible (true );
258-         fields .add (f );
259-       }
260-     }
261-     return  fields ;
262-   }
26394}
0 commit comments