11
11
12
12
import org .elasticsearch .common .Strings ;
13
13
import org .elasticsearch .core .PathUtils ;
14
+ import org .elasticsearch .license .License ;
14
15
import org .elasticsearch .logging .LogManager ;
15
16
import org .elasticsearch .logging .Logger ;
16
17
import org .elasticsearch .xcontent .XContentBuilder ;
46
47
import java .io .InputStreamReader ;
47
48
import java .lang .annotation .Annotation ;
48
49
import java .lang .reflect .Constructor ;
50
+ import java .lang .reflect .Method ;
49
51
import java .nio .charset .StandardCharsets ;
50
52
import java .nio .file .Files ;
51
53
import java .nio .file .Path ;
@@ -107,7 +109,7 @@ static OperatorsDocsSupport forOperators(String name, Class<?> testClass) {
107
109
return new OperatorsDocsSupport (name , testClass );
108
110
}
109
111
110
- static void renderDocs (String name , Class <?> testClass ) throws IOException {
112
+ static void renderDocs (String name , Class <?> testClass ) throws Exception {
111
113
if (OPERATORS .containsKey (name )) {
112
114
var docs = DocsV3Support .forOperators (name , testClass );
113
115
docs .renderSignature ();
@@ -126,7 +128,7 @@ public static void renderNegatedOperator(
126
128
String name ,
127
129
Function <String , String > description ,
128
130
Class <?> testClass
129
- ) throws IOException {
131
+ ) throws Exception {
130
132
var docs = forOperators ("not " + name .toLowerCase (Locale .ROOT ), testClass );
131
133
docs .renderDocsForNegatedOperators (ctor , description );
132
134
}
@@ -272,12 +274,46 @@ public void writeToTempDir(Path dir, String extension, String str) throws IOExce
272
274
}
273
275
}
274
276
277
+ /**
278
+ * This class is used to check if a license requirement method exists in the test class.
279
+ * This is used to add license requirement information to the generated documentation.
280
+ */
281
+ public static class LicenseRequirementChecker {
282
+ private Method staticMethod ;
283
+ private Function <List <DataType >, License .OperationMode > fallbackLambda ;
284
+
285
+ public LicenseRequirementChecker (Class <?> testClass ) {
286
+ try {
287
+ staticMethod = testClass .getMethod ("licenseRequirement" , List .class );
288
+ if (License .OperationMode .class .equals (staticMethod .getReturnType ()) == false
289
+ || java .lang .reflect .Modifier .isStatic (staticMethod .getModifiers ()) == false ) {
290
+ staticMethod = null ; // Reset if the method doesn't match the signature
291
+ }
292
+ } catch (NoSuchMethodException e ) {
293
+ staticMethod = null ;
294
+ }
295
+
296
+ if (staticMethod == null ) {
297
+ fallbackLambda = fieldTypes -> License .OperationMode .BASIC ;
298
+ }
299
+ }
300
+
301
+ public License .OperationMode invoke (List <DataType > fieldTypes ) throws Exception {
302
+ if (staticMethod != null ) {
303
+ return (License .OperationMode ) staticMethod .invoke (null , fieldTypes );
304
+ } else {
305
+ return fallbackLambda .apply (fieldTypes );
306
+ }
307
+ }
308
+ }
309
+
275
310
protected final String category ;
276
311
protected final String name ;
277
312
protected final FunctionDefinition definition ;
278
313
protected final Logger logger ;
279
314
private final Supplier <Map <List <DataType >, DataType >> signatures ;
280
315
private TempFileWriter tempFileWriter ;
316
+ private final LicenseRequirementChecker licenseChecker ;
281
317
282
318
protected DocsV3Support (String category , String name , Class <?> testClass , Supplier <Map <List <DataType >, DataType >> signatures ) {
283
319
this (category , name , null , testClass , signatures );
@@ -296,6 +332,7 @@ private DocsV3Support(
296
332
this .logger = LogManager .getLogger (testClass );
297
333
this .signatures = signatures ;
298
334
this .tempFileWriter = new DocsFileWriter ();
335
+ this .licenseChecker = new LicenseRequirementChecker (testClass );
299
336
}
300
337
301
338
/** Used in tests to capture output for asserting on the content */
@@ -460,7 +497,7 @@ void writeToTempKibanaDir(String subdir, String extension, String str) throws IO
460
497
461
498
protected abstract void renderSignature () throws IOException ;
462
499
463
- protected abstract void renderDocs () throws IOException ;
500
+ protected abstract void renderDocs () throws Exception ;
464
501
465
502
static class FunctionDocsSupport extends DocsV3Support {
466
503
private FunctionDocsSupport (String name , Class <?> testClass ) {
@@ -488,7 +525,7 @@ protected void renderSignature() throws IOException {
488
525
}
489
526
490
527
@ Override
491
- protected void renderDocs () throws IOException {
528
+ protected void renderDocs () throws Exception {
492
529
if (definition == null ) {
493
530
logger .info ("Skipping rendering docs because the function '{}' isn't registered" , name );
494
531
} else {
@@ -497,7 +534,7 @@ protected void renderDocs() throws IOException {
497
534
}
498
535
}
499
536
500
- private void renderDocs (FunctionDefinition definition ) throws IOException {
537
+ private void renderDocs (FunctionDefinition definition ) throws Exception {
501
538
EsqlFunctionRegistry .FunctionDescription description = EsqlFunctionRegistry .description (definition );
502
539
if (name .equals ("case" )) {
503
540
/*
@@ -711,7 +748,7 @@ public void renderSignature() throws IOException {
711
748
}
712
749
713
750
@ Override
714
- public void renderDocs () throws IOException {
751
+ public void renderDocs () throws Exception {
715
752
Constructor <?> ctor = constructorWithFunctionInfo (op .clazz ());
716
753
if (ctor != null ) {
717
754
FunctionInfo functionInfo = ctor .getAnnotation (FunctionInfo .class );
@@ -722,7 +759,7 @@ public void renderDocs() throws IOException {
722
759
}
723
760
}
724
761
725
- void renderDocsForNegatedOperators (Constructor <?> ctor , Function <String , String > description ) throws IOException {
762
+ void renderDocsForNegatedOperators (Constructor <?> ctor , Function <String , String > description ) throws Exception {
726
763
String baseName = name .toLowerCase (Locale .ROOT ).replace ("not " , "" );
727
764
OperatorConfig op = OPERATORS .get (baseName );
728
765
assert op != null ;
@@ -795,7 +832,7 @@ public Example[] examples() {
795
832
}
796
833
797
834
void renderDocsForOperators (String name , String titleName , Constructor <?> ctor , FunctionInfo info , boolean variadic )
798
- throws IOException {
835
+ throws Exception {
799
836
renderKibanaInlineDocs (name , titleName , info );
800
837
801
838
var params = ctor .getParameters ();
@@ -999,7 +1036,7 @@ void renderKibanaFunctionDefinition(
999
1036
FunctionInfo info ,
1000
1037
List <EsqlFunctionRegistry .ArgSignature > args ,
1001
1038
boolean variadic
1002
- ) throws IOException {
1039
+ ) throws Exception {
1003
1040
1004
1041
try (XContentBuilder builder = JsonXContent .contentBuilder ().prettyPrint ().lfAtEnd ().startObject ()) {
1005
1042
builder .field (
@@ -1019,6 +1056,10 @@ void renderKibanaFunctionDefinition(
1019
1056
});
1020
1057
}
1021
1058
builder .field ("name" , name );
1059
+ License .OperationMode license = licenseChecker .invoke (null );
1060
+ if (license != null && license != License .OperationMode .BASIC ) {
1061
+ builder .field ("license" , license .toString ());
1062
+ }
1022
1063
if (titleName != null && titleName .equals (name ) == false ) {
1023
1064
builder .field ("titleName" , titleName );
1024
1065
}
@@ -1073,6 +1114,10 @@ void renderKibanaFunctionDefinition(
1073
1114
builder .endObject ();
1074
1115
}
1075
1116
builder .endArray ();
1117
+ license = licenseChecker .invoke (sig .getKey ());
1118
+ if (license != null && license != License .OperationMode .BASIC ) {
1119
+ builder .field ("license" , license .toString ());
1120
+ }
1076
1121
builder .field ("variadic" , variadic );
1077
1122
builder .field ("returnType" , sig .getValue ().esNameIfPossible ());
1078
1123
builder .endObject ();
0 commit comments