52
52
import java .security .PrivilegedAction ;
53
53
import java .text .ParseException ;
54
54
import java .util .ArrayList ;
55
+ import java .util .Collections ;
55
56
import java .util .HashMap ;
56
57
import java .util .List ;
57
58
import java .util .Map ;
59
+ import java .util .Set ;
60
+ import java .util .function .Function ;
58
61
59
62
/**
60
63
* Provides the infrastructure for Lucene expressions as a scripting language for Elasticsearch.
@@ -65,6 +68,45 @@ public class ExpressionScriptEngine implements ScriptEngine {
65
68
66
69
public static final String NAME = "expression" ;
67
70
71
+ private static Map <ScriptContext <?>, Function <Expression ,Object >> contexts ;
72
+
73
+ static {
74
+ Map <ScriptContext <?>, Function <Expression ,Object >> contexts = new HashMap <ScriptContext <?>, Function <Expression ,Object >>();
75
+ contexts .put (BucketAggregationScript .CONTEXT ,
76
+ ExpressionScriptEngine ::newBucketAggregationScriptFactory );
77
+
78
+ contexts .put (BucketAggregationSelectorScript .CONTEXT ,
79
+ (Expression expr ) -> {
80
+ BucketAggregationScript .Factory factory = newBucketAggregationScriptFactory (expr );
81
+ BucketAggregationSelectorScript .Factory wrappedFactory = parameters -> new BucketAggregationSelectorScript (parameters ) {
82
+ @ Override
83
+ public boolean execute () {
84
+ return factory .newInstance (getParams ()).execute ().doubleValue () == 1.0 ;
85
+ }
86
+ };
87
+ return wrappedFactory ; });
88
+
89
+ contexts .put (FilterScript .CONTEXT ,
90
+ (Expression expr ) -> (FilterScript .Factory ) (p , lookup ) -> newFilterScript (expr , lookup , p ));
91
+
92
+ contexts .put (ScoreScript .CONTEXT ,
93
+ (Expression expr ) -> (ScoreScript .Factory ) (p , lookup ) -> newScoreScript (expr , lookup , p ));
94
+
95
+ contexts .put (TermsSetQueryScript .CONTEXT ,
96
+ (Expression expr ) -> (TermsSetQueryScript .Factory ) (p , lookup ) -> newTermsSetQueryScript (expr , lookup , p ));
97
+
98
+ contexts .put (AggregationScript .CONTEXT ,
99
+ (Expression expr ) -> (AggregationScript .Factory ) (p , lookup ) -> newAggregationScript (expr , lookup , p ));
100
+
101
+ contexts .put (NumberSortScript .CONTEXT ,
102
+ (Expression expr ) -> (NumberSortScript .Factory ) (p , lookup ) -> newSortScript (expr , lookup , p ));
103
+
104
+ contexts .put (FieldScript .CONTEXT ,
105
+ (Expression expr ) -> (FieldScript .Factory ) (p , lookup ) -> newFieldScript (expr , lookup , p ));
106
+
107
+ ExpressionScriptEngine .contexts = Collections .unmodifiableMap (contexts );
108
+ }
109
+
68
110
@ Override
69
111
public String getType () {
70
112
return NAME ;
@@ -102,37 +144,15 @@ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundE
102
144
}
103
145
}
104
146
});
105
- if (context .instanceClazz .equals (BucketAggregationScript .class )) {
106
- return context .factoryClazz .cast (newBucketAggregationScriptFactory (expr ));
107
- } else if (context .instanceClazz .equals (BucketAggregationSelectorScript .class )) {
108
- BucketAggregationScript .Factory factory = newBucketAggregationScriptFactory (expr );
109
- BucketAggregationSelectorScript .Factory wrappedFactory = parameters -> new BucketAggregationSelectorScript (parameters ) {
110
- @ Override
111
- public boolean execute () {
112
- return factory .newInstance (getParams ()).execute ().doubleValue () == 1.0 ;
113
- }
114
- };
115
- return context .factoryClazz .cast (wrappedFactory );
116
- } else if (context .instanceClazz .equals (FilterScript .class )) {
117
- FilterScript .Factory factory = (p , lookup ) -> newFilterScript (expr , lookup , p );
118
- return context .factoryClazz .cast (factory );
119
- } else if (context .instanceClazz .equals (ScoreScript .class )) {
120
- ScoreScript .Factory factory = (p , lookup ) -> newScoreScript (expr , lookup , p );
121
- return context .factoryClazz .cast (factory );
122
- } else if (context .instanceClazz .equals (TermsSetQueryScript .class )) {
123
- TermsSetQueryScript .Factory factory = (p , lookup ) -> newTermsSetQueryScript (expr , lookup , p );
124
- return context .factoryClazz .cast (factory );
125
- } else if (context .instanceClazz .equals (AggregationScript .class )) {
126
- AggregationScript .Factory factory = (p , lookup ) -> newAggregationScript (expr , lookup , p );
127
- return context .factoryClazz .cast (factory );
128
- } else if (context .instanceClazz .equals (NumberSortScript .class )) {
129
- NumberSortScript .Factory factory = (p , lookup ) -> newSortScript (expr , lookup , p );
130
- return context .factoryClazz .cast (factory );
131
- } else if (context .instanceClazz .equals (FieldScript .class )) {
132
- FieldScript .Factory factory = (p , lookup ) -> newFieldScript (expr , lookup , p );
133
- return context .factoryClazz .cast (factory );
147
+ if (contexts .containsKey (context ) == false ) {
148
+ throw new IllegalArgumentException ("expression engine does not know how to handle script context [" + context .name + "]" );
134
149
}
135
- throw new IllegalArgumentException ("expression engine does not know how to handle script context [" + context .name + "]" );
150
+ return context .factoryClazz .cast (contexts .get (context ).apply (expr ));
151
+ }
152
+
153
+ @ Override
154
+ public Set <ScriptContext <?>> getSupportedContexts () {
155
+ return contexts .keySet ();
136
156
}
137
157
138
158
private static BucketAggregationScript .Factory newBucketAggregationScriptFactory (Expression expr ) {
@@ -166,7 +186,7 @@ public Double execute() {
166
186
};
167
187
}
168
188
169
- private NumberSortScript .LeafFactory newSortScript (Expression expr , SearchLookup lookup , @ Nullable Map <String , Object > vars ) {
189
+ private static NumberSortScript .LeafFactory newSortScript (Expression expr , SearchLookup lookup , @ Nullable Map <String , Object > vars ) {
170
190
// NOTE: if we need to do anything complicated with bindings in the future, we can just extend Bindings,
171
191
// instead of complicating SimpleBindings (which should stay simple)
172
192
SimpleBindings bindings = new SimpleBindings ();
@@ -193,7 +213,7 @@ private NumberSortScript.LeafFactory newSortScript(Expression expr, SearchLookup
193
213
return new ExpressionNumberSortScript (expr , bindings , needsScores );
194
214
}
195
215
196
- private TermsSetQueryScript .LeafFactory newTermsSetQueryScript (Expression expr , SearchLookup lookup ,
216
+ private static TermsSetQueryScript .LeafFactory newTermsSetQueryScript (Expression expr , SearchLookup lookup ,
197
217
@ Nullable Map <String , Object > vars ) {
198
218
// NOTE: if we need to do anything complicated with bindings in the future, we can just extend Bindings,
199
219
// instead of complicating SimpleBindings (which should stay simple)
@@ -216,7 +236,7 @@ private TermsSetQueryScript.LeafFactory newTermsSetQueryScript(Expression expr,
216
236
return new ExpressionTermSetQueryScript (expr , bindings );
217
237
}
218
238
219
- private AggregationScript .LeafFactory newAggregationScript (Expression expr , SearchLookup lookup ,
239
+ private static AggregationScript .LeafFactory newAggregationScript (Expression expr , SearchLookup lookup ,
220
240
@ Nullable Map <String , Object > vars ) {
221
241
// NOTE: if we need to do anything complicated with bindings in the future, we can just extend Bindings,
222
242
// instead of complicating SimpleBindings (which should stay simple)
@@ -252,7 +272,7 @@ private AggregationScript.LeafFactory newAggregationScript(Expression expr, Sear
252
272
return new ExpressionAggregationScript (expr , bindings , needsScores , specialValue );
253
273
}
254
274
255
- private FieldScript .LeafFactory newFieldScript (Expression expr , SearchLookup lookup , @ Nullable Map <String , Object > vars ) {
275
+ private static FieldScript .LeafFactory newFieldScript (Expression expr , SearchLookup lookup , @ Nullable Map <String , Object > vars ) {
256
276
SimpleBindings bindings = new SimpleBindings ();
257
277
for (String variable : expr .variables ) {
258
278
try {
@@ -273,7 +293,7 @@ private FieldScript.LeafFactory newFieldScript(Expression expr, SearchLookup loo
273
293
* This is a hack for filter scripts, which must return booleans instead of doubles as expression do.
274
294
* See https://github.com/elastic/elasticsearch/issues/26429.
275
295
*/
276
- private FilterScript .LeafFactory newFilterScript (Expression expr , SearchLookup lookup , @ Nullable Map <String , Object > vars ) {
296
+ private static FilterScript .LeafFactory newFilterScript (Expression expr , SearchLookup lookup , @ Nullable Map <String , Object > vars ) {
277
297
ScoreScript .LeafFactory searchLeafFactory = newScoreScript (expr , lookup , vars );
278
298
return ctx -> {
279
299
ScoreScript script = searchLeafFactory .newInstance (ctx );
@@ -290,7 +310,7 @@ public void setDocument(int docid) {
290
310
};
291
311
}
292
312
293
- private ScoreScript .LeafFactory newScoreScript (Expression expr , SearchLookup lookup , @ Nullable Map <String , Object > vars ) {
313
+ private static ScoreScript .LeafFactory newScoreScript (Expression expr , SearchLookup lookup , @ Nullable Map <String , Object > vars ) {
294
314
// NOTE: if we need to do anything complicated with bindings in the future, we can just extend Bindings,
295
315
// instead of complicating SimpleBindings (which should stay simple)
296
316
SimpleBindings bindings = new SimpleBindings ();
@@ -327,7 +347,7 @@ private ScoreScript.LeafFactory newScoreScript(Expression expr, SearchLookup loo
327
347
/**
328
348
* converts a ParseException at compile-time or link-time to a ScriptException
329
349
*/
330
- private ScriptException convertToScriptException (String message , String source , String portion , Throwable cause ) {
350
+ private static ScriptException convertToScriptException (String message , String source , String portion , Throwable cause ) {
331
351
List <String > stack = new ArrayList <>();
332
352
stack .add (portion );
333
353
StringBuilder pointer = new StringBuilder ();
0 commit comments