Skip to content

Commit 1d33611

Browse files
committed
Support Arazzo, check reference exists
1 parent d3576be commit 1d33611

File tree

4 files changed

+66
-47
lines changed

4 files changed

+66
-47
lines changed

src/main/java/com/apiflows/model/SourceDescription.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ public boolean isOpenApi() {
3939
return "openapi".equals(this.type);
4040
}
4141

42-
public boolean isWorkflowsSpec() {
43-
return "workflowsSpec".equals(this.type);
42+
public boolean isArazzo() {
43+
return "arazzo".equals(this.type);
4444
}
4545

4646
public SourceDescription name(String name) {

src/main/java/com/apiflows/parser/OpenAPIWorkflowValidator.java

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ public class OpenAPIWorkflowValidator {
1313
Set<String> workflowIds = new HashSet<>();
1414
Map<String, Set<String>> stepIds = new HashMap<>();
1515
Set<String> operationIds = new HashSet<>();
16-
Set<Schema> components = new HashSet<>();
16+
Set<String> componentIds = new HashSet<>();
17+
Components components = null;
1718

1819
OpenAPIWorkflowValidator() {
1920
}
@@ -31,11 +32,12 @@ public OpenAPIWorkflowValidatorResult validate() {
3132
loadWorkflowIds(this.openAPIWorkflow);
3233
loadStepIds(this.openAPIWorkflow.getWorkflows());
3334
loadOperationIds(this.openAPIWorkflow);
35+
loadComponents(this.openAPIWorkflow.getComponents());
3436

3537
OpenAPIWorkflowValidatorResult result = new OpenAPIWorkflowValidatorResult();
3638

3739
if (openAPIWorkflow.getArazzo() == null || openAPIWorkflow.getArazzo().isEmpty()) {
38-
result.addError("'workflowsSpec' is undefined");
40+
result.addError("'arazzo' is undefined");
3941
}
4042

4143
// Info
@@ -85,7 +87,7 @@ List<String> validateInfo(Info info) {
8587
}
8688

8789
List<String> validateSourceDescriptions(List<SourceDescription> sourceDescriptions) {
88-
List<String> SUPPORTED_TYPES = Arrays.asList("openapi", "workflowsSpec");
90+
List<String> SUPPORTED_TYPES = Arrays.asList("openapi", "arazzo");
8991

9092
List<String> errors = new ArrayList<>();
9193

@@ -171,15 +173,18 @@ List<String> validateStep(Step step, String workflowId ) {
171173

172174
if(step.getParameters() != null) {
173175
for(Parameter parameter : step.getParameters()) {
174-
if(isRuntimeExpression(parameter.getName())) {
176+
if(isRuntimeExpression(parameter.getReference())) {
177+
// reference a reusable object
175178
errors.addAll(validateReusableParameter(parameter, workflowId, null));
176179
} else {
180+
// parameter
177181
errors.addAll(validateParameter(parameter, workflowId, null));
178-
}
179-
if(step.getWorkflowId() == null) {
180-
// when the step in context is NOT a workflowId the parameter IN must be defined
181-
if(!isRuntimeExpression(parameter.getName()) && parameter.getIn() == null) {
182-
errors.add("'Workflow[" + workflowId + "]' parameter IN must be defined");
182+
183+
if(step.getWorkflowId() == null) {
184+
// when the step in context is NOT a workflowId the parameter IN must be defined
185+
if(!isRuntimeExpression(parameter.getName()) && parameter.getIn() == null) {
186+
errors.add("'Workflow[" + workflowId + "]' parameter IN must be defined");
187+
}
183188
}
184189
}
185190
}
@@ -212,7 +217,7 @@ List<String> validateStep(Step step, String workflowId ) {
212217
}
213218

214219
List<String> validateParameter(Parameter parameter, String workflowId, String componentName) {
215-
List<String> SUPPORTED_VALUES = Arrays.asList("path", "query", "header", "cookie", "body", "workflow");
220+
List<String> SUPPORTED_VALUES = Arrays.asList("path", "query", "header", "cookie", "body");
216221

217222
String source;
218223

@@ -264,19 +269,18 @@ List<String> validateReusableParameter(Parameter parameter, String workflowId, S
264269
source = "Component[" + componentName + "]";
265270
}
266271

267-
List<String> errors = new ArrayList<>();
268-
269-
if(isRuntimeExpression(parameter.getName())) {
270-
// Reusable Parameter object
271-
String name = parameter.getName();
272-
273-
if(parameter.getIn() != null) {
274-
errors.add(source + "parameter " + name + " in (" + parameter.getIn() + ") should not be provided for a Reusable Parameter Object");
275-
}
272+
// reference to reusable object
273+
String reference = parameter.getReference();
274+
// normalize reference
275+
String key = reference.replace("$components.parameters.", "");
276276

277-
// TODO: check reusable parameter exists in Components
277+
List<String> errors = new ArrayList<>();
278278

279+
// check reusable parameter exists in Components
280+
if(!this.components.getParameters().containsKey(key)) {
281+
errors.add(source + " parameter '" + reference + "' not found");
279282
}
283+
280284
return errors;
281285
}
282286

@@ -447,14 +451,13 @@ String getOutputsKeyRegularExpression() {
447451
List<String> loadWorkflowIds(OpenAPIWorkflow openAPIWorkflow) {
448452
List<String> errors = new ArrayList<>();
449453

450-
boolean multipleWorkflowsSpec = getNumWorkflowsSpecSourceDescriptions(openAPIWorkflow.getSourceDescriptions()) > 1 ? true : false;
451-
454+
boolean multipleSpecs = getNumArazzoTypeSourceDescriptions(openAPIWorkflow.getSourceDescriptions()) > 1 ? true : false;
452455

453456
if(openAPIWorkflow.getWorkflows() != null) {
454457
validateWorkflowIdsUniqueness(openAPIWorkflow.getWorkflows());
455458

456459
for (Workflow workflow : openAPIWorkflow.getWorkflows()) {
457-
errors.addAll(validateStepsWorkflowIds(workflow.getSteps(), multipleWorkflowsSpec));
460+
errors.addAll(validateStepsWorkflowIds(workflow.getSteps(), multipleSpecs));
458461
}
459462

460463
for (Workflow workflow : openAPIWorkflow.getWorkflows()) {
@@ -508,6 +511,10 @@ List<String> loadOperationIds(OpenAPIWorkflow openAPIWorkflow) {
508511
return errors;
509512
}
510513

514+
void loadComponents(Components components) {
515+
this.components = components;
516+
}
517+
511518
public List<String> validateStepsOperationIds(List<Step> steps, boolean multipleOpenApiFiles) {
512519
List<String> errors = new ArrayList<>();
513520

@@ -528,9 +535,9 @@ int getNumOpenApiSourceDescriptions(List<SourceDescription> sourceDescriptions)
528535
return (int) sourceDescriptions.stream().filter(p -> p.isOpenApi()).count();
529536
}
530537

531-
// num of SourceDescriptions with type 'workflowsSpec'
532-
int getNumWorkflowsSpecSourceDescriptions(List<SourceDescription> sourceDescriptions) {
533-
return (int) sourceDescriptions.stream().filter(p -> p.isWorkflowsSpec()).count();
538+
// num of SourceDescriptions with type 'arazzo'
539+
int getNumArazzoTypeSourceDescriptions(List<SourceDescription> sourceDescriptions) {
540+
return (int) sourceDescriptions.stream().filter(p -> p.isArazzo()).count();
534541
}
535542

536543
boolean stepExists(String workflowId, String stepId) {
@@ -554,11 +561,11 @@ List<String> validateWorkflowIdsUniqueness(List<Workflow> workflows) {
554561
return errors;
555562
}
556563

557-
List<String> validateStepsWorkflowIds(List<Step> steps, boolean multipleWorkflowsSpecFiles) {
564+
List<String> validateStepsWorkflowIds(List<Step> steps, boolean multipleArazzoTypeFiles) {
558565
List<String> errors = new ArrayList<>();
559566

560567
for(Step step : steps) {
561-
if(multipleWorkflowsSpecFiles) {
568+
if(multipleArazzoTypeFiles) {
562569
// must use runtime expression to map applicable SourceDescription
563570
if(step.getWorkflowId() != null && !step.getWorkflowId().startsWith("$sourceDescriptions.")) {
564571
errors.add("Operation " + step.getWorkflowId() + " must be specified using a runtime expression (e.g., $sourceDescriptions.<name>.<workflowId>)");

src/test/java/com/apiflows/parser/OpenAPIWorkflowParserTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public void isYaml() {
8686
@Test
8787
public void getJsonFormat() {
8888
final String CONTENT = "{" +
89-
"\"workflowsSpec\" : \"1.0.0\"" +
89+
"\"arazzo\" : \"1.0.0\"" +
9090
"}";
9191

9292
OpenAPIWorkflowParserResult.Format format = parser.getFormat(CONTENT);
@@ -96,7 +96,7 @@ public void getJsonFormat() {
9696
@Test
9797
public void getYamlFormat() {
9898
final String CONTENT = "" +
99-
"workflowsSpec : 1.0.0" +
99+
"arazzo : 1.0.0" +
100100
"info:" +
101101
" title: simple\n";
102102

src/test/java/com/apiflows/parser/OpenAPIWorkflowValidatorTest.java

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.apiflows.parser;
22

33
import com.apiflows.model.*;
4+
import org.checkerframework.checker.units.qual.C;
45
import org.junit.jupiter.api.Test;
56

67
import java.util.*;
@@ -18,7 +19,7 @@ void validate() {
1819

1920
assertFalse(result.isValid());
2021
assertFalse(result.getErrors().isEmpty());
21-
assertEquals("'workflowsSpec' is undefined", result.getErrors().get(0));
22+
assertEquals("'arazzo' is undefined", result.getErrors().get(0));
2223
}
2324

2425
@Test
@@ -201,22 +202,33 @@ void validateStepWithoutInAttribute() {
201202
@Test
202203
void validateReusableParameter() {
203204
Parameter parameter = new Parameter()
204-
.name("$components.parameters.page")
205+
.reference("$components.parameters.pageSize")
205206
.value("1");
206207
String worklowId = "q1";
207208

209+
Components components = new Components()
210+
.parameter("pageSize", parameter);
211+
212+
validator.loadComponents(components);
213+
208214
assertEquals(0, validator.validateReusableParameter(parameter, worklowId, null).size());
209215
}
210216

211217
@Test
212-
void validateReusableParameterWithInAttribute() {
218+
void validateReusableParameterNotFound() {
213219
Parameter parameter = new Parameter()
214-
.name("$components.parameters.page")
215-
.value("1")
216-
.in("query");
220+
.reference("$components.parameters.pageSize")
221+
.value("1");
222+
Parameter anotherParameter = new Parameter()
223+
.reference("$components.parameters.pageCounter")
224+
.value("1");
217225
String worklowId = "q1";
218226

219-
// error: must not define IN attribute
227+
Components components = new Components()
228+
.parameter("anotherParameter", anotherParameter);
229+
230+
validator.loadComponents(components);
231+
220232
assertEquals(1, validator.validateReusableParameter(parameter, worklowId, null).size());
221233
}
222234

@@ -570,14 +582,14 @@ public void getNumOpenApiSourceDescriptions() {
570582
.type("openapi"),
571583
new SourceDescription()
572584
.name("workflowspec-1")
573-
.type("workflowsSpec")
585+
.type("arazzo")
574586
);
575587

576588
assertEquals(2, new OpenAPIWorkflowValidator().getNumOpenApiSourceDescriptions(sourceDescriptions));
577589
}
578590

579591
@Test
580-
public void getNumWorkflowsSpecSourceDescriptions() {
592+
public void getNumArazzoTypeSourceDescriptions() {
581593
List<SourceDescription> sourceDescriptions = List.of(
582594
new SourceDescription()
583595
.name("openapifile-1")
@@ -587,10 +599,10 @@ public void getNumWorkflowsSpecSourceDescriptions() {
587599
.type("openapi"),
588600
new SourceDescription()
589601
.name("workflowspec-1")
590-
.type("workflowsSpec")
602+
.type("arazzo")
591603
);
592604

593-
assertEquals(1, new OpenAPIWorkflowValidator().getNumWorkflowsSpecSourceDescriptions(sourceDescriptions));
605+
assertEquals(1, new OpenAPIWorkflowValidator().getNumArazzoTypeSourceDescriptions(sourceDescriptions));
594606
}
595607

596608
@Test
@@ -621,28 +633,28 @@ public void validateStepsOperationIdsWithoutRuntimeExpression() {
621633

622634
@Test
623635
public void validateStepsWorkflowIds() {
624-
boolean multipleWorkflowsSpecFiles = true;
636+
boolean multipleArazzoTypeFiles = true;
625637

626638
List<Step> steps = List.of(
627639
new Step()
628640
.stepId("step-one")
629641
.workflowId("w2")
630642
);
631643

632-
assertEquals(1, new OpenAPIWorkflowValidator().validateStepsWorkflowIds(steps, multipleWorkflowsSpecFiles).size());
644+
assertEquals(1, new OpenAPIWorkflowValidator().validateStepsWorkflowIds(steps, multipleArazzoTypeFiles).size());
633645
}
634646

635647
@Test
636648
public void validateStepsWorkflowIdsWithoutRuntimeExpression() {
637-
boolean multipleWorkflowsSpecFiles = false;
649+
boolean multipleArazzoTypeFiles = false;
638650

639651
List<Step> steps = List.of(
640652
new Step()
641653
.stepId("step-one")
642654
.workflowId("w2")
643655
);
644656

645-
assertEquals(0, new OpenAPIWorkflowValidator().validateStepsWorkflowIds(steps, multipleWorkflowsSpecFiles).size());
657+
assertEquals(0, new OpenAPIWorkflowValidator().validateStepsWorkflowIds(steps, multipleArazzoTypeFiles).size());
646658
}
647659

648660
@Test

0 commit comments

Comments
 (0)