@@ -12,6 +12,7 @@ public class OpenAPIWorkflowValidator {
12
12
private OpenAPIWorkflow openAPIWorkflow = null ;
13
13
Set <String > workflowIds = new HashSet <>();
14
14
Map <String , Set <String >> stepIds = new HashMap <>();
15
+ Set <String > operationIds = new HashSet <>();
15
16
Set <Schema > components = new HashSet <>();
16
17
17
18
OpenAPIWorkflowValidator () {
@@ -27,8 +28,9 @@ public OpenAPIWorkflowValidatorResult validate() {
27
28
throw new RuntimeException ("OpenAPIWorkflow is not provided" );
28
29
}
29
30
30
- loadWorkflowIds (this .openAPIWorkflow . getWorkflows () );
31
+ loadWorkflowIds (this .openAPIWorkflow );
31
32
loadStepIds (this .openAPIWorkflow .getWorkflows ());
33
+ loadOperationIds (this .openAPIWorkflow );
32
34
33
35
OpenAPIWorkflowValidatorResult result = new OpenAPIWorkflowValidatorResult ();
34
36
@@ -346,8 +348,8 @@ List<String> validateComponents(Components components) {
346
348
if (components .getParameters () != null ) {
347
349
348
350
for (String key : components .getParameters ().keySet ()) {
349
- if (isValidComponentKey (key )) {
350
- errors .add ("'Component parameter " + key + " is invalid (should match regex " + getComponentKeyRegularExpression () + ")" );
351
+ if (! isValidComponentKey (key )) {
352
+ errors .add ("'Component parameter name " + key + " is invalid (should match regex " + getComponentKeyRegularExpression () + ")" );
351
353
}
352
354
}
353
355
@@ -356,13 +358,11 @@ List<String> validateComponents(Components components) {
356
358
}
357
359
}
358
360
if (components .getInputs () != null ) {
359
-
360
361
for (String key : components .getInputs ().keySet ()) {
361
- if (isValidComponentKey (key )) {
362
+ if (! isValidComponentKey (key )) {
362
363
errors .add ("'Component input " + key + " is invalid (should match regex " + getComponentKeyRegularExpression () + ")" );
363
364
}
364
365
}
365
-
366
366
}
367
367
}
368
368
@@ -400,18 +400,24 @@ String getOutputsKeyRegularExpression() {
400
400
return "^[a-zA-Z0-9\\ .\\ -_]+$" ;
401
401
}
402
402
403
- List <String > loadWorkflowIds (List < Workflow > workflows ) {
403
+ List <String > loadWorkflowIds (OpenAPIWorkflow openAPIWorkflow ) {
404
404
List <String > errors = new ArrayList <>();
405
405
406
- if (workflows != null ) {
407
- for (Workflow workflow : workflows ) {
408
- if (!this .workflowIds .add (workflow .getWorkflowId ())) {
409
- // id already exists
410
- errors .add ("WorkflowId is not unique: " + workflow .getWorkflowId ());
411
- }
406
+ boolean multipleWorkflowsSpec = getNumWorkflowsSpecSourceDescriptions (openAPIWorkflow .getSourceDescriptions ()) > 1 ? true : false ;
407
+
408
+
409
+ if (openAPIWorkflow .getWorkflows () != null ) {
410
+ validateWorkflowIdsUniqueness (openAPIWorkflow .getWorkflows ());
411
+
412
+ for (Workflow workflow : openAPIWorkflow .getWorkflows ()) {
413
+ errors .addAll (validateStepsWorkflowIds (workflow .getSteps (), multipleWorkflowsSpec ));
412
414
}
413
- }
414
415
416
+ for (Workflow workflow : openAPIWorkflow .getWorkflows ()) {
417
+ this .workflowIds .add (workflow .getWorkflowId ());
418
+ }
419
+
420
+ }
415
421
return errors ;
416
422
}
417
423
@@ -440,10 +446,82 @@ List<String> loadStepIds(List<Workflow> workflows) {
440
446
return errors ;
441
447
}
442
448
449
+ List <String > loadOperationIds (OpenAPIWorkflow openAPIWorkflow ) {
450
+ List <String > errors = new ArrayList <>();
451
+
452
+ boolean multipleOpenApiFiles = getNumOpenApiSourceDescriptions (openAPIWorkflow .getSourceDescriptions ()) > 1 ? true : false ;
453
+
454
+ for (Workflow workflow : openAPIWorkflow .getWorkflows ()) {
455
+ errors .addAll (validateStepsOperationIds (workflow .getSteps (), multipleOpenApiFiles ));
456
+
457
+ for (Step step : workflow .getSteps ()) {
458
+ if (step .getOperationId () != null ) {
459
+ this .operationIds .add (step .getOperationId ());
460
+ }
461
+ }
462
+ }
463
+
464
+ return errors ;
465
+ }
466
+
467
+ public List <String > validateStepsOperationIds (List <Step > steps , boolean multipleOpenApiFiles ) {
468
+ List <String > errors = new ArrayList <>();
469
+
470
+ for (Step step : steps ) {
471
+ if (multipleOpenApiFiles ) {
472
+ // must use runtime expression to map applicable SourceDescription
473
+ if (step .getOperationId () != null && !step .getOperationId ().startsWith ("$sourceDescriptions." )) {
474
+ errors .add ("Operation " + step .getOperationId () + " must be specified using a runtime expression (e.g., $sourceDescriptions.<name>.<operationId>)" );
475
+ }
476
+ }
477
+ }
478
+
479
+ return errors ;
480
+ }
481
+
482
+ // num of SourceDescriptions with type 'openapi'
483
+ int getNumOpenApiSourceDescriptions (List <SourceDescription > sourceDescriptions ) {
484
+ return (int ) sourceDescriptions .stream ().filter (p -> p .isOpenApi ()).count ();
485
+ }
486
+
487
+ // num of SourceDescriptions with type 'workflowsSpec'
488
+ int getNumWorkflowsSpecSourceDescriptions (List <SourceDescription > sourceDescriptions ) {
489
+ return (int ) sourceDescriptions .stream ().filter (p -> p .isWorkflowsSpec ()).count ();
490
+ }
491
+
443
492
boolean stepExists (String workflowId , String stepId ) {
444
493
return this .stepIds .get (workflowId ) != null && this .stepIds .get (workflowId ).contains (stepId );
445
494
}
446
495
496
+ List <String > validateWorkflowIdsUniqueness (List <Workflow > workflows ) {
497
+ List <String > errors = new ArrayList <>();
498
+
499
+ Set <String > ids = new HashSet <>();
500
+ for (Workflow workflow : workflows ) {
501
+ if (!ids .add (workflow .getWorkflowId ())) {
502
+ // id already exists
503
+ errors .add ("WorkflowId is not unique: " + workflow .getWorkflowId ());
504
+ }
505
+ }
506
+ return errors ;
507
+ }
508
+
509
+ List <String > validateStepsWorkflowIds (List <Step > steps , boolean multipleWorkflowsSpecFiles ) {
510
+ List <String > errors = new ArrayList <>();
511
+
512
+ for (Step step : steps ) {
513
+ if (multipleWorkflowsSpecFiles ) {
514
+ // must use runtime expression to map applicable SourceDescription
515
+ if (step .getWorkflowId () != null && !step .getWorkflowId ().startsWith ("$sourceDescriptions." )) {
516
+ errors .add ("Operation " + step .getWorkflowId () + " must be specified using a runtime expression (e.g., $sourceDescriptions.<name>.<workflowId>)" );
517
+ }
518
+ }
519
+ }
520
+
521
+ return errors ;
522
+ }
523
+
524
+
447
525
public boolean isValidJsonPointer (String jsonPointerString ) {
448
526
449
527
boolean ret ;
0 commit comments