diff --git a/.gitignore b/.gitignore
index eb67759e09..88f6119088 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,6 +114,7 @@ Migrations/
/core-tests/client-java/distance-heuristics/target/
/em.toml
+/core-extra/arazzo-parser/target/
/core-extra/solver/target/
/em.yaml
/core-tests/e2e-tests/spring/spring-rest-openapi-v2/em.yaml
diff --git a/core-extra/arazzo-parser/pom.xml b/core-extra/arazzo-parser/pom.xml
new file mode 100644
index 0000000000..13b6528ee2
--- /dev/null
+++ b/core-extra/arazzo-parser/pom.xml
@@ -0,0 +1,84 @@
+
+
+ 4.0.0
+
+ org.evomaster
+ evomaster-core-extra
+ 5.1.1-SNAPSHOT
+
+
+ arazzo-parser
+
+
+
+ io.swagger.core.v3
+ swagger-models
+ 2.2.34
+ compile
+
+
+ org.mock-server
+ mockserver-client-java-no-dependencies
+ compile
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+
+
+ io.swagger.core.v3
+ swagger-core
+ 2.2.34
+ compile
+
+
+ com.github.tomakehurst
+ wiremock-jre8-standalone
+ compile
+
+
+ junit
+ junit
+ 4.13.1
+ test
+
+
+ io.swagger.parser.v3
+ swagger-parser-v3
+ 2.1.33
+ test
+
+
+ com.graphql-java
+ java-dataloader
+ 2.2.3
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 8
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ @{argLine} -ea -Xms512m -Xmx1536m -Xss2m -Dfile.encoding=UTF-8 -Duser.language=en -Duser.country=GB
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/access/ArazzoAccess.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/access/ArazzoAccess.java
new file mode 100644
index 0000000000..4ee909dd9b
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/access/ArazzoAccess.java
@@ -0,0 +1,39 @@
+package org.evomaster.arazzo.access;
+
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Read Arrazzo documents
+ */
+public class ArazzoAccess {
+ public static String readFromDisk(String arazzoLocation) throws Exception {
+ String fileScheme = "file:";
+
+ Path path;
+ try {
+ if (arazzoLocation.toLowerCase().startsWith(fileScheme)) {
+ path = Paths.get(URI.create(arazzoLocation));
+ } else {
+ path = Paths.get(arazzoLocation);
+ }
+ } catch (Exception e) {
+ throw new Exception("The file path provided for the Arazzo Schema " + arazzoLocation + " ended up with the following error: " + e.getMessage());
+ }
+
+ if ((!Files.exists(path))) {
+ throw new Exception("The provided Arazzo file does not exist: " + arazzoLocation);
+ }
+
+ try {
+ byte[] bytes = Files.readAllBytes(path);
+ return new String(bytes, StandardCharsets.UTF_8);
+ } catch (Exception e) {
+ throw new Exception("Error reading the Arazzo file: " + e.getMessage());
+ }
+
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/AnyExpressionDeserializer.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/AnyExpressionDeserializer.java
new file mode 100644
index 0000000000..53dfef2da1
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/AnyExpressionDeserializer.java
@@ -0,0 +1,30 @@
+package org.evomaster.arazzo.deserializer;
+
+import com.fasterxml.jackson.core.JacksonException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import org.evomaster.arazzo.models.domain.AnyExpression;
+
+import java.io.IOException;
+
+/**
+ * Custom Jackson deserializer for {@link AnyExpression}.
+ * It resolves dynamic JSON payloads by mapping plain text to a {@link AnyExpression.Expression},
+ * and any other complex structure to a generic JSON node.
+ */
+public class AnyExpressionDeserializer extends JsonDeserializer {
+
+ @Override
+ public AnyExpression deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
+ JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+
+ if (node.isTextual()) {
+ return new AnyExpression.Expression(node.asText());
+ }
+ JsonNode any = jsonParser.getCodec().treeToValue(node, JsonNode.class);
+ return new AnyExpression.Any(any);
+ }
+
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/CriterionTypeDeserializer.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/CriterionTypeDeserializer.java
new file mode 100644
index 0000000000..46adea4e67
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/CriterionTypeDeserializer.java
@@ -0,0 +1,35 @@
+package org.evomaster.arazzo.deserializer;
+
+import com.fasterxml.jackson.core.JacksonException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import org.evomaster.arazzo.models.domain.CriterionExpression;
+import org.evomaster.arazzo.models.domain.CriterionType;
+
+import java.io.IOException;
+
+/**
+ * Custom Jackson deserializer for {@link CriterionType}.
+ * It resolves dynamic JSON payloads by mapping plain text to a {@link CriterionType.Simple},
+ * and a JSON object to a {@link CriterionType.Complex}.
+ */
+public class CriterionTypeDeserializer extends JsonDeserializer {
+
+ @Override
+ public CriterionType deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
+ JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+
+ if (node.isTextual()) {
+ return new CriterionType.Simple(node.asText());
+ } else if (node.isObject()) {
+ CriterionExpression complex = jsonParser.getCodec().treeToValue(node, CriterionExpression.class);
+ return new CriterionType.Complex(complex);
+ } else {
+ throw new IllegalArgumentException("Arazzo Parsing Error: Invalid " + node.getNodeType() + ". Expected string or Criterion Expression");
+ }
+
+ }
+
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/FailureReusableDeserializer.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/FailureReusableDeserializer.java
new file mode 100644
index 0000000000..f0443ba9d6
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/FailureReusableDeserializer.java
@@ -0,0 +1,31 @@
+package org.evomaster.arazzo.deserializer;
+
+import com.fasterxml.jackson.core.JacksonException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import org.evomaster.arazzo.models.domain.*;
+
+import java.io.IOException;
+
+/**
+ * Custom Jackson deserializer for {@link FailureReusable}.
+ * It differentiates the incoming JSON payload based on the presence of the "reference" field,
+ * mapping it to a {@link FailureReusable.ReusableObj} if present, or to a {@link FailureReusable.Failure} otherwise.
+ */
+public class FailureReusableDeserializer extends JsonDeserializer {
+
+ @Override
+ public FailureReusable deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
+ JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+
+ if (node.has("reference")) {
+ Reusable reusable = jsonParser.getCodec().treeToValue(node, Reusable.class);
+ return new FailureReusable.ReusableObj(reusable);
+ }
+
+ FailureAction action = jsonParser.getCodec().treeToValue(node, FailureAction.class);
+ return new FailureReusable.Failure(action);
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/ParameterReusableDeserializer.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/ParameterReusableDeserializer.java
new file mode 100644
index 0000000000..ae456f8fd9
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/ParameterReusableDeserializer.java
@@ -0,0 +1,32 @@
+package org.evomaster.arazzo.deserializer;
+
+import com.fasterxml.jackson.core.JacksonException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import org.evomaster.arazzo.models.domain.*;
+
+import java.io.IOException;
+
+/**
+ * Custom Jackson deserializer for {@link ParameterReusable}.
+ * It differentiates the incoming JSON payload based on the presence of the "reference" field,
+ * mapping it to a {@link ParameterReusable.ReusableObj} if present, or to a {@link ParameterReusable.Param} otherwise.
+ */
+public class ParameterReusableDeserializer extends JsonDeserializer {
+
+ @Override
+ public ParameterReusable deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
+ JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+
+ if (node.has("reference")) {
+ Reusable reusable = jsonParser.getCodec().treeToValue(node, Reusable.class);
+ return new ParameterReusable.ReusableObj(reusable);
+ }
+
+ Parameter parameter = jsonParser.getCodec().treeToValue(node, Parameter.class);
+ return new ParameterReusable.Param(parameter);
+ }
+
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/SuccessReusableDeserializer.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/SuccessReusableDeserializer.java
new file mode 100644
index 0000000000..6f72fb3e9a
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/deserializer/SuccessReusableDeserializer.java
@@ -0,0 +1,35 @@
+package org.evomaster.arazzo.deserializer;
+
+import com.fasterxml.jackson.core.JacksonException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import org.evomaster.arazzo.models.domain.ParameterReusable;
+import org.evomaster.arazzo.models.domain.Reusable;
+import org.evomaster.arazzo.models.domain.SuccessAction;
+import org.evomaster.arazzo.models.domain.SuccessReusable;
+
+import java.io.IOException;
+
+/**
+ * Custom Jackson deserializer for {@link SuccessReusable}.
+ * It differentiates the incoming JSON payload based on the presence of the "reference" field,
+ * mapping it to a {@link SuccessReusable.ReusableObj} if present, or to a {@link SuccessReusable.Success} otherwise.
+ */
+public class SuccessReusableDeserializer extends JsonDeserializer {
+
+ @Override
+ public SuccessReusable deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
+ JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+
+ if (node.has("reference")) {
+ Reusable reusable = jsonParser.getCodec().treeToValue(node, Reusable.class);
+ return new SuccessReusable.ReusableObj(reusable);
+ }
+
+ SuccessAction action = jsonParser.getCodec().treeToValue(node, SuccessAction.class);
+ return new SuccessReusable.Success(action);
+ }
+
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/mapper/ArazzoMapper.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/mapper/ArazzoMapper.java
new file mode 100644
index 0000000000..9a10d32bf0
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/mapper/ArazzoMapper.java
@@ -0,0 +1,90 @@
+package org.evomaster.arazzo.mapper;
+
+import org.evomaster.arazzo.models.domain.ArazzoSpecifications;
+import org.evomaster.arazzo.models.domain.Step;
+import org.evomaster.arazzo.models.domain.Workflow;
+import org.evomaster.arazzo.models.dto.ArazzoSpecificationsDTO;
+import org.evomaster.arazzo.models.dto.StepDTO;
+import org.evomaster.arazzo.models.dto.WorkflowDTO;
+import org.evomaster.arazzo.resolver.ArazzoReferenceResolver;
+import io.swagger.v3.oas.models.media.Schema;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Mapper class responsible for converting Arazzo Specification (DTOs)
+ * into their corresponding domain models.
+ */
+public class ArazzoMapper {
+ private ArazzoReferenceResolver resolver;
+
+ public ArazzoMapper(ArazzoReferenceResolver resolver) {
+ this.resolver = resolver;
+ }
+
+ public ArazzoSpecifications toDomain(ArazzoSpecificationsDTO arazzoSpecificationsDTO) {
+ return ArazzoSpecifications.builder()
+ .arazzo(arazzoSpecificationsDTO.getArazzo())
+ .info(arazzoSpecificationsDTO.getInfo())
+ .sourceDescriptions(arazzoSpecificationsDTO.getSourceDescriptions())
+ .workflows(arazzoSpecificationsDTO.getWorkflows().stream()
+ .map(this::toDomain)
+ .collect(Collectors.toList()))
+ .components(arazzoSpecificationsDTO.getComponents())
+ .build();
+ }
+
+ public Workflow toDomain(WorkflowDTO workflowDTO) {
+ return Workflow.builder()
+ .workflowId(workflowDTO.getWorkflowId())
+ .summary(workflowDTO.getSummary())
+ .description(workflowDTO.getDescription())
+ .inputs(this.toDomain(workflowDTO.getInputs()))
+ .dependsOn(workflowDTO.getDependsOn())
+ .steps(workflowDTO.getSteps().stream()
+ .map(this::toDomain)
+ .collect(Collectors.toList()))
+ .successActions(resolver.resolveSuccessReusable(workflowDTO.getSuccessActions()))
+ .failureActions(resolver.resolveFailureReusable(workflowDTO.getFailureActions()))
+ .outputs(workflowDTO.getOutputs())
+ .parameters(resolver.resolveParametersReusable(workflowDTO.getParameters()))
+ .build();
+ }
+
+ public Step toDomain(StepDTO stepDTO) {
+ return Step.builder()
+ .description(stepDTO.getDescription())
+ .stepId(stepDTO.getStepId())
+ .operationId(stepDTO.getOperationId())
+ .operationPath(stepDTO.getOperationPath())
+ .workflowId(stepDTO.getWorkflowId())
+ .parameters(resolver.resolveParametersReusable(stepDTO.getParameters()))
+ .requestBody(stepDTO.getRequestBody())
+ .successCriteria(stepDTO.getSuccessCriteria())
+ .onSuccess(resolver.resolveSuccessReusable(stepDTO.getOnSuccess()))
+ .onFailure(resolver.resolveFailureReusable(stepDTO.getOnFailure()))
+ .outputs(stepDTO.getOutputs())
+ .build();
+ }
+
+ public Schema> toDomain(Schema> schema) {
+ if (schema != null && schema.get$ref() != null && !schema.get$ref().trim().isEmpty()) {
+ Schema> reference = toDomain(resolver.resolveJsonPointer(schema.get$ref()));
+ if (reference != null) {
+ if (reference.getProperties() != null) {
+ Map updatedProperties = reference.getProperties().entrySet().stream()
+ .collect(Collectors.toMap(
+ Map.Entry::getKey, entry -> toDomain(entry.getValue())
+ ));
+
+ reference.setProperties(updatedProperties);
+ }
+
+ return reference;
+ }
+ }
+
+ return schema;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/AnyExpression.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/AnyExpression.java
new file mode 100644
index 0000000000..64054adf4c
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/AnyExpression.java
@@ -0,0 +1,39 @@
+package org.evomaster.arazzo.models.domain;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Representing the model (Any | {expression})
+ * The value to pass in the parameter.
+ * The value can be a constant or a Runtime Expression to be evaluated
+ * and passed to the referenced operation or workflow
+ */
+public abstract class AnyExpression {
+
+ public AnyExpression() {
+ }
+
+ public static class Any extends AnyExpression {
+ private final JsonNode jsonNode;
+
+ public Any(JsonNode jsonNode) {
+ this.jsonNode = jsonNode;
+ }
+
+ public JsonNode getJsonNode() {
+ return jsonNode;
+ }
+ }
+
+ public static class Expression extends AnyExpression {
+ private final String expression;
+
+ public Expression(String expression) {
+ this.expression = expression;
+ }
+
+ public String getExpression() {
+ return expression;
+ }
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/ArazzoSpecifications.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/ArazzoSpecifications.java
new file mode 100644
index 0000000000..b8220f9e20
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/ArazzoSpecifications.java
@@ -0,0 +1,66 @@
+package org.evomaster.arazzo.models.domain;
+
+import java.util.List;
+
+/**
+ * Representing the model Arazzo Specification Object
+ * This is the root object of the Arazzo Description
+ */
+public class ArazzoSpecifications {
+ private String arazzo;
+ private InfoArazzo info;
+ private List sourceDescriptions;
+ private List workflows;
+ private Components components;
+
+ private ArazzoSpecifications(Builder builder) {
+ this.arazzo = builder.arazzo;
+ this.info = builder.info;
+ this.sourceDescriptions = builder.sourceDescriptions;
+ this.workflows = builder.workflows;
+ this.components = builder.components;
+ }
+
+ public String getArazzo() {
+ return arazzo;
+ }
+
+ public InfoArazzo getInfo() {
+ return info;
+ }
+
+ public List getSourceDescriptions() {
+ return sourceDescriptions;
+ }
+
+ public List getWorkflows() {
+ return workflows;
+ }
+
+ public Components getComponents() {
+ return components;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private String arazzo;
+ private InfoArazzo info;
+ private List sourceDescriptions;
+ private List workflows;
+ private Components components;
+
+ public Builder arazzo(String arazzo) { this.arazzo = arazzo; return this; }
+ public Builder info(InfoArazzo info) { this.info = info; return this; }
+ public Builder sourceDescriptions(List sourceDescriptions) { this.sourceDescriptions = sourceDescriptions; return this; }
+ public Builder workflows(List workflows) { this.workflows = workflows; return this; }
+ public Builder components(Components components) { this.components = components; return this; }
+
+ public ArazzoSpecifications build() {
+ return new ArazzoSpecifications(this);
+ }
+
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Components.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Components.java
new file mode 100644
index 0000000000..b422254ac5
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Components.java
@@ -0,0 +1,52 @@
+package org.evomaster.arazzo.models.domain;
+
+import java.util.Map;
+import io.swagger.v3.oas.models.media.Schema;
+
+/**
+ * Representing the model Components Object
+ * Holds a set of reusable objects for different aspects of the Arazzo Specification.
+ * All objects defined within the components object will have no effect on the Arazzo Description
+ * unless they are explicitly referenced from properties outside the components object.
+ */
+public class Components {
+ private Map> inputs;
+ private Map parameters;
+ private Map successAction;
+ private Map failureAction;
+
+ public Components() {
+ }
+
+ public Map> getInputs() {
+ return inputs;
+ }
+
+ public void setInputs(Map> inputs) {
+ this.inputs = inputs;
+ }
+
+ public Map getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(Map parameters) {
+ this.parameters = parameters;
+ }
+
+ public Map getSuccessAction() {
+ return successAction;
+ }
+
+ public void setSuccessAction(Map successAction) {
+ this.successAction = successAction;
+ }
+
+ public Map getFailureAction() {
+ return failureAction;
+ }
+
+ public void setFailureAction(Map failureAction) {
+ this.failureAction = failureAction;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Criterion.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Criterion.java
new file mode 100644
index 0000000000..88ee23d551
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Criterion.java
@@ -0,0 +1,44 @@
+package org.evomaster.arazzo.models.domain;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.evomaster.arazzo.deserializer.CriterionTypeDeserializer;
+
+/**
+ * Representing the model Criterion Object
+ * An object used to specify the context, conditions,
+ * and condition types that can be used to prove or satisfy assertions specified
+ */
+public class Criterion {
+ private String context;
+ private String condition;
+
+ @JsonDeserialize(using = CriterionTypeDeserializer.class)
+ private CriterionType type;
+
+ public Criterion() {
+ }
+
+ public String getContext() {
+ return context;
+ }
+
+ public void setContext(String context) {
+ this.context = context;
+ }
+
+ public String getCondition() {
+ return condition;
+ }
+
+ public void setCondition(String condition) {
+ this.condition = condition;
+ }
+
+ public CriterionType getType() {
+ return type;
+ }
+
+ public void setType(CriterionType type) {
+ this.type = type;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/CriterionExpression.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/CriterionExpression.java
new file mode 100644
index 0000000000..10700f03cf
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/CriterionExpression.java
@@ -0,0 +1,29 @@
+package org.evomaster.arazzo.models.domain;
+
+/**
+ * Representing the model Criterion Expression Type Object
+ * An object used to describe the type and version of an expression used within a Criterion Object
+ */
+public class CriterionExpression {
+ private String type;
+ private String version;
+
+ public CriterionExpression() {
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/CriterionType.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/CriterionType.java
new file mode 100644
index 0000000000..faf268ac6e
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/CriterionType.java
@@ -0,0 +1,34 @@
+package org.evomaster.arazzo.models.domain;
+
+/**
+ * It represents an object that can be a String or a {@link CriterionExpression}.
+ */
+public abstract class CriterionType {
+
+ public CriterionType() {
+ }
+
+ public static class Simple extends CriterionType {
+ private final String value;
+
+ public Simple(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+ }
+
+ public static class Complex extends CriterionType {
+ private final CriterionExpression expression;
+
+ public Complex(CriterionExpression expression) {
+ this.expression = expression;
+ }
+
+ public CriterionExpression getExpression() {
+ return expression;
+ }
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/FailureAction.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/FailureAction.java
new file mode 100644
index 0000000000..614575a4d1
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/FailureAction.java
@@ -0,0 +1,76 @@
+package org.evomaster.arazzo.models.domain;
+
+import java.util.List;
+
+/**
+ * Representing the model Failure Action Object
+ * A single failure action which describes an action to take upon failure of a workflow step
+ */
+public class FailureAction {
+ private String name;
+ private String type;
+ private String workflowId;
+ private String stepId;
+ private Number retryAfter;
+ private Integer retryLimit;
+ private List criteria;
+
+ public FailureAction() {
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getWorkflowId() {
+ return workflowId;
+ }
+
+ public void setWorkflowId(String workflowId) {
+ this.workflowId = workflowId;
+ }
+
+ public Number getRetryAfter() {
+ return retryAfter;
+ }
+
+ public void setRetryAfter(Number retryAfter) {
+ this.retryAfter = retryAfter;
+ }
+
+ public String getStepId() {
+ return stepId;
+ }
+
+ public void setStepId(String stepId) {
+ this.stepId = stepId;
+ }
+
+ public Integer getRetryLimit() {
+ return retryLimit;
+ }
+
+ public void setRetryLimit(Integer retryLimit) {
+ this.retryLimit = retryLimit;
+ }
+
+ public List getCriteria() {
+ return criteria;
+ }
+
+ public void setCriteria(List criteria) {
+ this.criteria = criteria;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/FailureReusable.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/FailureReusable.java
new file mode 100644
index 0000000000..070067251d
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/FailureReusable.java
@@ -0,0 +1,34 @@
+package org.evomaster.arazzo.models.domain;
+
+/**
+ * It represents an object that can be a {@link FailureAction} or a {@link Reusable}.
+ */
+public abstract class FailureReusable {
+
+ public FailureReusable() {
+ }
+
+ public static class Failure extends FailureReusable {
+ private final FailureAction action;
+
+ public Failure(FailureAction action) {
+ this.action = action;
+ }
+
+ public FailureAction getAction() {
+ return action;
+ }
+ }
+
+ public static class ReusableObj extends FailureReusable {
+ private final Reusable reusable;
+
+ public ReusableObj(Reusable reusable) {
+ this.reusable = reusable;
+ }
+
+ public Reusable getReusable() {
+ return reusable;
+ }
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/InfoArazzo.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/InfoArazzo.java
new file mode 100644
index 0000000000..5ad6681989
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/InfoArazzo.java
@@ -0,0 +1,47 @@
+package org.evomaster.arazzo.models.domain;
+
+/**
+ * Representing the model Info Object
+ * This is the root object of the Arazzo Description
+ */
+public class InfoArazzo {
+ private String title;
+ private String summary;
+ private String description;
+ private String version;
+
+ public InfoArazzo() {
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getSummary() {
+ return summary;
+ }
+
+ public void setSummary(String summary) {
+ this.summary = summary;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Parameter.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Parameter.java
new file mode 100644
index 0000000000..f62e88b60d
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Parameter.java
@@ -0,0 +1,43 @@
+package org.evomaster.arazzo.models.domain;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.evomaster.arazzo.deserializer.AnyExpressionDeserializer;
+
+/**
+ * Representing the model Parameter Object
+ * Describes a single step parameter
+ */
+public class Parameter {
+ private String name;
+ private String in;
+
+ @JsonDeserialize(using = AnyExpressionDeserializer.class)
+ private AnyExpression value;
+
+ public Parameter() {
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getIn() {
+ return in;
+ }
+
+ public void setIn(String in) {
+ this.in = in;
+ }
+
+ public AnyExpression getValue() {
+ return value;
+ }
+
+ public void setValue(AnyExpression value) {
+ this.value = value;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/ParameterReusable.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/ParameterReusable.java
new file mode 100644
index 0000000000..38cc80f43f
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/ParameterReusable.java
@@ -0,0 +1,34 @@
+package org.evomaster.arazzo.models.domain;
+
+/**
+ * It represents an object that can be a {@link Parameter} or a {@link Reusable}.
+ */
+public abstract class ParameterReusable {
+
+ public ParameterReusable() {
+ }
+
+ public static class Param extends ParameterReusable {
+ private final Parameter parameter;
+
+ public Param(Parameter parameter) {
+ this.parameter = parameter;
+ }
+
+ public Parameter getParameter() {
+ return parameter;
+ }
+ }
+
+ public static class ReusableObj extends ParameterReusable {
+ private final Reusable reusable;
+
+ public ReusableObj(Reusable reusable) {
+ this.reusable = reusable;
+ }
+
+ public Reusable getReusable() {
+ return reusable;
+ }
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/PayloadReplacement.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/PayloadReplacement.java
new file mode 100644
index 0000000000..ab3dae9f47
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/PayloadReplacement.java
@@ -0,0 +1,34 @@
+package org.evomaster.arazzo.models.domain;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.evomaster.arazzo.deserializer.AnyExpressionDeserializer;
+
+/**
+ * Representing the model Payload Replacement Object
+ * Describes a location within a payload (e.g., a request body) and a value to set within the location.
+ */
+public class PayloadReplacement {
+ private String target;
+
+ @JsonDeserialize(using = AnyExpressionDeserializer.class)
+ private AnyExpression value;
+
+ public PayloadReplacement() {
+ }
+
+ public String getTarget() {
+ return target;
+ }
+
+ public void setTarget(String target) {
+ this.target = target;
+ }
+
+ public AnyExpression getValue() {
+ return value;
+ }
+
+ public void setValue(AnyExpression value) {
+ this.value = value;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/RequestBody.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/RequestBody.java
new file mode 100644
index 0000000000..a2a8a94d1a
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/RequestBody.java
@@ -0,0 +1,42 @@
+package org.evomaster.arazzo.models.domain;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import java.util.List;
+
+/**
+ * Representing the model Request Body Object
+ * A single request body describing the Content-Type and request body content to be passed by a step to an operation.
+ */
+public class RequestBody {
+ private String contentType;
+ private JsonNode payload;
+ private List replacements;
+
+ public RequestBody() {
+ }
+
+ public String getContentType() {
+ return contentType;
+ }
+
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+ public JsonNode getPayload() {
+ return payload;
+ }
+
+ public void setPayload(JsonNode payload) {
+ this.payload = payload;
+ }
+
+ public List getReplacements() {
+ return replacements;
+ }
+
+ public void setReplacements(List replacements) {
+ this.replacements = replacements;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Reusable.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Reusable.java
new file mode 100644
index 0000000000..cded5118e7
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Reusable.java
@@ -0,0 +1,29 @@
+package org.evomaster.arazzo.models.domain;
+
+/**
+ * Representing the model Reusable Object
+ * A simple object to allow referencing of objects contained within the {@link Components}
+ */
+public class Reusable {
+ private String reference;
+ private String value;
+
+ public Reusable() {
+ }
+
+ public String getReference() {
+ return reference;
+ }
+
+ public void setReference(String reference) {
+ this.reference = reference;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/SourceDescription.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/SourceDescription.java
new file mode 100644
index 0000000000..8d8c336652
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/SourceDescription.java
@@ -0,0 +1,39 @@
+package org.evomaster.arazzo.models.domain;
+
+/**
+ * Representing the model Source Description Object
+ * Describes a source description (such as an OpenAPI description)
+ * that will be referenced by one or more workflows described within an Arazzo Description
+ */
+public class SourceDescription {
+ private String name;
+ private String url;
+ private String type;
+
+ public SourceDescription() {
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Step.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Step.java
new file mode 100644
index 0000000000..ac52e8da41
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Step.java
@@ -0,0 +1,119 @@
+package org.evomaster.arazzo.models.domain;
+
+import org.evomaster.arazzo.resolver.ArazzoReferenceResolver;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Representing the model Step Object
+ * Describes a single workflow step which MAY be a call
+ * to an API operation (OpenAPI Operation Object) or another Workflow Object
+ * This model only have SuccessAction, FailureAction and Parameter.
+ * The references are expected to be resolved by {@link ArazzoReferenceResolver}.
+ */
+public class Step {
+ private String description;
+ private String stepId;
+ private String operationId;
+ private String operationPath;
+ private String workflowId;
+ private List parameters;
+ private RequestBody requestBody;
+ private List successCriteria;
+ private List onSuccess;
+ private List onFailure;
+ private Map outputs;
+
+ public Step(Builder builder) {
+ this.description = builder.description;
+ this.stepId = builder.stepId;
+ this.operationId = builder.operationId;
+ this.operationPath = builder.operationPath;
+ this.workflowId = builder.workflowId;
+ this.parameters = builder.parameters;
+ this.requestBody = builder.requestBody;
+ this.successCriteria = builder.successCriteria;
+ this.onSuccess = builder.onSuccess;
+ this.onFailure = builder.onFailure;
+ this.outputs = builder.outputs;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getStepId() {
+ return stepId;
+ }
+
+ public String getOperationId() {
+ return operationId;
+ }
+
+ public String getOperationPath() {
+ return operationPath;
+ }
+
+ public String getWorkflowId() {
+ return workflowId;
+ }
+
+ public List getParameters() {
+ return parameters;
+ }
+
+ public RequestBody getRequestBody() {
+ return requestBody;
+ }
+
+ public List getSuccessCriteria() {
+ return successCriteria;
+ }
+
+ public List getOnSuccess() {
+ return onSuccess;
+ }
+
+ public List getOnFailure() {
+ return onFailure;
+ }
+
+ public Map getOutputs() {
+ return outputs;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private String description;
+ private String stepId;
+ private String operationId;
+ private String operationPath;
+ private String workflowId;
+ private List parameters;
+ private RequestBody requestBody;
+ private List successCriteria;
+ private List onSuccess;
+ private List onFailure;
+ private Map outputs;
+
+ public Builder description(String description) { this.description = description; return this; }
+ public Builder stepId(String stepId) { this.stepId = stepId; return this; }
+ public Builder operationId(String operationId) { this.operationId = operationId; return this; }
+ public Builder operationPath(String operationPath) { this.operationPath = operationPath; return this; }
+ public Builder workflowId(String workflowId) { this.workflowId = workflowId; return this; }
+ public Builder parameters(List parameters) { this.parameters = parameters; return this; }
+ public Builder requestBody(RequestBody requestBody) { this.requestBody = requestBody; return this; }
+ public Builder successCriteria(List successCriteria) { this.successCriteria = successCriteria; return this; }
+ public Builder onSuccess(List onSuccess) { this.onSuccess = onSuccess; return this; }
+ public Builder onFailure(List onFailure) { this.onFailure = onFailure; return this; }
+ public Builder outputs(Map outputs) { this.outputs = outputs; return this; }
+
+ public Step build() {
+ return new Step(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/SuccessAction.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/SuccessAction.java
new file mode 100644
index 0000000000..cd87d77a4f
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/SuccessAction.java
@@ -0,0 +1,58 @@
+package org.evomaster.arazzo.models.domain;
+
+import java.util.List;
+
+/**
+ * Representing the model Success Action Object
+ * A single success action which describes an action to take upon success of a workflow step
+ */
+public class SuccessAction {
+ private String name;
+ private String type;
+ private String workflowId;
+ private String stepId;
+ private List criteria;
+
+ public SuccessAction() {
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getWorkflowId() {
+ return workflowId;
+ }
+
+ public void setWorkflowId(String workflowId) {
+ this.workflowId = workflowId;
+ }
+
+ public String getStepId() {
+ return stepId;
+ }
+
+ public void setStepId(String stepId) {
+ this.stepId = stepId;
+ }
+
+ public List getCriteria() {
+ return criteria;
+ }
+
+ public void setCriteria(List criteria) {
+ this.criteria = criteria;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/SuccessReusable.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/SuccessReusable.java
new file mode 100644
index 0000000000..2e5660eae2
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/SuccessReusable.java
@@ -0,0 +1,34 @@
+package org.evomaster.arazzo.models.domain;
+
+/**
+ * It represents an object that can be a {@link SuccessAction} or a {@link Reusable}.
+ */
+public abstract class SuccessReusable {
+
+ public SuccessReusable() {
+ }
+
+ public static class Success extends SuccessReusable {
+ private final SuccessAction action;
+
+ public Success(SuccessAction action) {
+ this.action = action;
+ }
+
+ public SuccessAction getAction() {
+ return action;
+ }
+ }
+
+ public static class ReusableObj extends SuccessReusable {
+ private final Reusable reusable;
+
+ public ReusableObj(Reusable reusable) {
+ this.reusable = reusable;
+ }
+
+ public Reusable getReusable() {
+ return reusable;
+ }
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Workflow.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Workflow.java
new file mode 100644
index 0000000000..a83755fbfe
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/domain/Workflow.java
@@ -0,0 +1,115 @@
+package org.evomaster.arazzo.models.domain;
+
+import io.swagger.v3.oas.models.media.Schema;
+import org.evomaster.arazzo.resolver.ArazzoReferenceResolver;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Representing the model Workflow Object
+ * Describes the steps to be taken across one or more APIs to achieve an objective.
+ * The workflow object MAY define inputs needed in order to execute workflow steps,
+ * where the defined steps represent a call to an API operation or another workflow,
+ * and a set of outputs.
+ * This model only have SuccessAction, FailureAction and Parameter.
+ * The references are expected to be resolved by {@link ArazzoReferenceResolver}.
+ */
+public class Workflow {
+ private String workflowId;
+ private String summary;
+ private String description;
+ private Schema> inputs;
+ private List dependsOn;
+ private List steps;
+ private List successActions;
+ private List failureActions;
+ private Map outputs;
+ private List parameters;
+
+ private Workflow(Builder builder) {
+ this.workflowId = builder.workflowId;
+ this.summary = builder.summary;
+ this.description = builder.description;
+ this.inputs = builder.inputs;
+ this.dependsOn = builder.dependsOn;
+ this.steps = builder.steps;
+ this.successActions = builder.successActions;
+ this.failureActions = builder.failureActions;
+ this.outputs = builder.outputs;
+ this.parameters = builder.parameters;
+ }
+
+ public String getWorkflowId() {
+ return workflowId;
+ }
+
+ public String getSummary() {
+ return summary;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public Schema> getInputs() {
+ return inputs;
+ }
+
+ public List getDependsOn() {
+ return dependsOn;
+ }
+
+ public List getSteps() {
+ return steps;
+ }
+
+ public List getSuccessActions() {
+ return successActions;
+ }
+
+ public List getFailureActions() {
+ return failureActions;
+ }
+
+ public Map getOutputs() {
+ return outputs;
+ }
+
+ public List getParameters() {
+ return parameters;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private String workflowId;
+ private String summary;
+ private String description;
+ private Schema> inputs;
+ private List dependsOn;
+ private List steps;
+ private List successActions;
+ private List failureActions;
+ private Map outputs;
+ private List parameters;
+
+ public Builder workflowId(String workflowId) { this.workflowId = workflowId; return this; }
+ public Builder summary(String summary) { this.summary = summary; return this; }
+ public Builder description(String description) { this.description = description; return this; }
+ public Builder inputs(Schema> inputs) { this.inputs = inputs; return this; }
+ public Builder dependsOn(List dependsOn) { this.dependsOn = dependsOn; return this; }
+ public Builder steps(List steps) { this.steps = steps; return this; }
+ public Builder successActions(List successActions) { this.successActions = successActions; return this; }
+ public Builder failureActions(List failureActions) { this.failureActions = failureActions; return this; }
+ public Builder outputs(Map outputs) { this.outputs = outputs; return this; }
+ public Builder parameters(List parameters) { this.parameters = parameters; return this; }
+
+ public Workflow build() {
+ return new Workflow(this);
+ }
+ }
+
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/dto/ArazzoSpecificationsDTO.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/dto/ArazzoSpecificationsDTO.java
new file mode 100644
index 0000000000..355a4b278e
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/dto/ArazzoSpecificationsDTO.java
@@ -0,0 +1,62 @@
+package org.evomaster.arazzo.models.dto;
+
+import org.evomaster.arazzo.models.domain.Components;
+import org.evomaster.arazzo.models.domain.InfoArazzo;
+import org.evomaster.arazzo.models.domain.SourceDescription;
+
+import java.util.List;
+
+/**
+ * Representing the ArazzoSpecifications (DTO)
+ * Used for direct document parsing
+ */
+public class ArazzoSpecificationsDTO {
+ private String arazzo;
+ private InfoArazzo info;
+ private List sourceDescriptions;
+ private List workflows;
+ private Components components;
+
+ public ArazzoSpecificationsDTO() {
+ }
+
+ public String getArazzo() {
+ return arazzo;
+ }
+
+ public void setArazzo(String arazzo) {
+ this.arazzo = arazzo;
+ }
+
+ public InfoArazzo getInfo() {
+ return info;
+ }
+
+ public void setInfo(InfoArazzo info) {
+ this.info = info;
+ }
+
+ public List getSourceDescriptions() {
+ return sourceDescriptions;
+ }
+
+ public void setSourceDescriptions(List sourceDescriptions) {
+ this.sourceDescriptions = sourceDescriptions;
+ }
+
+ public List getWorkflows() {
+ return workflows;
+ }
+
+ public void setWorkflows(List workflows) {
+ this.workflows = workflows;
+ }
+
+ public Components getComponents() {
+ return components;
+ }
+
+ public void setComponents(Components components) {
+ this.components = components;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/dto/StepDTO.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/dto/StepDTO.java
new file mode 100644
index 0000000000..9a80d6628d
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/dto/StepDTO.java
@@ -0,0 +1,126 @@
+package org.evomaster.arazzo.models.dto;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.evomaster.arazzo.deserializer.FailureReusableDeserializer;
+import org.evomaster.arazzo.deserializer.ParameterReusableDeserializer;
+import org.evomaster.arazzo.deserializer.SuccessReusableDeserializer;
+import org.evomaster.arazzo.models.domain.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Representing the Step (DTO)
+ * Used for direct document parsing
+ * Use SuccessReusable, FailureReusable and ParameterReusable, for representing (Object | Reusable Object)
+ */
+public class StepDTO {
+ private String description;
+ private String stepId;
+ private String operationId;
+ private String operationPath;
+ private String workflowId;
+ private RequestBody requestBody;
+ private List successCriteria;
+ private Map outputs;
+
+ @JsonDeserialize(contentUsing = ParameterReusableDeserializer.class)
+ private List parameters;
+
+ @JsonDeserialize(contentUsing = SuccessReusableDeserializer.class)
+ private List onSuccess;
+
+ @JsonDeserialize(contentUsing = FailureReusableDeserializer.class)
+ private List onFailure;
+
+ public StepDTO() {
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getStepId() {
+ return stepId;
+ }
+
+ public void setStepId(String stepId) {
+ this.stepId = stepId;
+ }
+
+ public String getOperationId() {
+ return operationId;
+ }
+
+ public void setOperationId(String operationId) {
+ this.operationId = operationId;
+ }
+
+ public String getOperationPath() {
+ return operationPath;
+ }
+
+ public void setOperationPath(String operationPath) {
+ this.operationPath = operationPath;
+ }
+
+ public String getWorkflowId() {
+ return workflowId;
+ }
+
+ public void setWorkflowId(String workflowId) {
+ this.workflowId = workflowId;
+ }
+
+ public RequestBody getRequestBody() {
+ return requestBody;
+ }
+
+ public void setRequestBody(RequestBody requestBody) {
+ this.requestBody = requestBody;
+ }
+
+ public List getSuccessCriteria() {
+ return successCriteria;
+ }
+
+ public void setSuccessCriteria(List successCriteria) {
+ this.successCriteria = successCriteria;
+ }
+
+ public Map getOutputs() {
+ return outputs;
+ }
+
+ public void setOutputs(Map outputs) {
+ this.outputs = outputs;
+ }
+
+ public List getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(List parameters) {
+ this.parameters = parameters;
+ }
+
+ public List getOnSuccess() {
+ return onSuccess;
+ }
+
+ public void setOnSuccess(List onSuccess) {
+ this.onSuccess = onSuccess;
+ }
+
+ public List getOnFailure() {
+ return onFailure;
+ }
+
+ public void setOnFailure(List onFailure) {
+ this.onFailure = onFailure;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/dto/WorkflowDTO.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/dto/WorkflowDTO.java
new file mode 100644
index 0000000000..37898cbc33
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/models/dto/WorkflowDTO.java
@@ -0,0 +1,120 @@
+package org.evomaster.arazzo.models.dto;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.evomaster.arazzo.deserializer.FailureReusableDeserializer;
+import org.evomaster.arazzo.deserializer.ParameterReusableDeserializer;
+import org.evomaster.arazzo.deserializer.SuccessReusableDeserializer;
+import org.evomaster.arazzo.models.domain.FailureReusable;
+import org.evomaster.arazzo.models.domain.ParameterReusable;
+import org.evomaster.arazzo.models.domain.SuccessReusable;
+import io.swagger.v3.oas.models.media.Schema;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Representing the Workflow (DTO)
+ * Used for direct document parsing
+ * Use SuccessReusable, FailureReusable and ParameterReusable, for representing (Object | Reusable Object)
+ */
+public class WorkflowDTO {
+ private String workflowId;
+ private String summary;
+ private String description;
+ private Schema> inputs;
+ private List dependsOn;
+ private List steps;
+ private Map outputs;
+
+ @JsonDeserialize(contentUsing = SuccessReusableDeserializer.class)
+ private List successActions;
+
+ @JsonDeserialize(contentUsing = FailureReusableDeserializer.class)
+ private List failureActions;
+
+ @JsonDeserialize(contentUsing = ParameterReusableDeserializer.class)
+ private List parameters;
+
+ public WorkflowDTO() {
+ }
+
+ public String getWorkflowId() {
+ return workflowId;
+ }
+
+ public void setWorkflowId(String workflowId) {
+ this.workflowId = workflowId;
+ }
+
+ public String getSummary() {
+ return summary;
+ }
+
+ public void setSummary(String summary) {
+ this.summary = summary;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Schema> getInputs() {
+ return inputs;
+ }
+
+ public void setInputs(Schema> inputs) {
+ this.inputs = inputs;
+ }
+
+ public List getDependsOn() {
+ return dependsOn;
+ }
+
+ public void setDependsOn(List dependsOn) {
+ this.dependsOn = dependsOn;
+ }
+
+ public List getSteps() {
+ return steps;
+ }
+
+ public void setSteps(List steps) {
+ this.steps = steps;
+ }
+
+ public Map getOutputs() {
+ return outputs;
+ }
+
+ public void setOutputs(Map outputs) {
+ this.outputs = outputs;
+ }
+
+ public List getSuccessActions() {
+ return successActions;
+ }
+
+ public void setSuccessActions(List successActions) {
+ this.successActions = successActions;
+ }
+
+ public List getFailureActions() {
+ return failureActions;
+ }
+
+ public void setFailureActions(List failureActions) {
+ this.failureActions = failureActions;
+ }
+
+ public List getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(List parameters) {
+ this.parameters = parameters;
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/parser/ArazzoParser.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/parser/ArazzoParser.java
new file mode 100644
index 0000000000..8ef2995054
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/parser/ArazzoParser.java
@@ -0,0 +1,48 @@
+package org.evomaster.arazzo.parser;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import io.swagger.v3.oas.models.OpenAPI;
+import javafx.util.Pair;
+import org.evomaster.arazzo.mapper.ArazzoMapper;
+import org.evomaster.arazzo.models.domain.ArazzoSpecifications;
+import org.evomaster.arazzo.models.dto.ArazzoSpecificationsDTO;
+import org.evomaster.arazzo.resolver.ArazzoReferenceResolver;
+
+/**
+ * Parse a String containing an Arazzo document into a complete model in ArazzoSpecifications
+ */
+public class ArazzoParser {
+
+ private static final ObjectMapper JSON_MAPPER = new ObjectMapper().findAndRegisterModules();
+ private static final ObjectMapper YAML_MAPPER = new ObjectMapper(new YAMLFactory()).findAndRegisterModules();
+
+ public static ArazzoSpecifications parse(String schemaText, OpenAPI openAPI) {
+ Pair parsed = parseSchemaText(schemaText);
+ ArazzoReferenceResolver resolver = new ArazzoReferenceResolver(parsed.getKey().getComponents(), parsed.getValue(), openAPI);
+ ArazzoMapper mapper = new ArazzoMapper(resolver);
+ return mapper.toDomain(parsed.getKey());
+ }
+
+ private static Pair parseSchemaText(String schemaText) {
+ String schemaTextClean = schemaText.replaceAll("^\\s+", "");
+
+ ArazzoSpecificationsDTO arazzoSpecificationsDTO;
+ JsonNode arazzoJsonNode;
+
+ try {
+ if (schemaTextClean.startsWith("{")) {
+ arazzoSpecificationsDTO = JSON_MAPPER.readValue(schemaTextClean, ArazzoSpecificationsDTO.class);
+ arazzoJsonNode = JSON_MAPPER.readTree(schemaTextClean);
+ } else {
+ arazzoSpecificationsDTO = YAML_MAPPER.readValue(schemaTextClean, ArazzoSpecificationsDTO.class);
+ arazzoJsonNode = YAML_MAPPER.readTree(schemaTextClean);
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Problems parsing the Arazzo document", e);
+ }
+
+ return new Pair<>(arazzoSpecificationsDTO, arazzoJsonNode);
+ }
+}
diff --git a/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/resolver/ArazzoReferenceResolver.java b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/resolver/ArazzoReferenceResolver.java
new file mode 100644
index 0000000000..bed05cfd7a
--- /dev/null
+++ b/core-extra/arazzo-parser/src/main/java/org/evomaster/arazzo/resolver/ArazzoReferenceResolver.java
@@ -0,0 +1,185 @@
+package org.evomaster.arazzo.resolver;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import io.swagger.v3.core.util.Json;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.media.Schema;
+import org.evomaster.arazzo.models.domain.*;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Resolver class responsible for resolving Arazzo references.
+ */
+public class ArazzoReferenceResolver {
+ private Components components;
+ private JsonNode arazzoJsonNode;
+ private OpenAPI openApi;
+
+ public ArazzoReferenceResolver(Components components, JsonNode arazzoJsonNode, OpenAPI openAPI) {
+ this.components = components;
+ this.arazzoJsonNode = arazzoJsonNode;
+ this.openApi = openAPI;
+ }
+
+ public void setComponents(Components components) {
+ this.components = components;
+ }
+
+ public void setArazzoJsonNode(JsonNode arazzoJsonNode) {
+ this.arazzoJsonNode = arazzoJsonNode;
+ }
+
+ public void setOpenApi(OpenAPI openApi) {
+ this.openApi = openApi;
+ }
+
+ /**
+ * Resolve the {@link SuccessReusable} references to get a complete list of {@link SuccessAction}
+ */
+ public List resolveSuccessReusable(List items) {
+ if (items == null) {
+ return null;
+ }
+
+ return items.stream().map(item -> {
+ if (item instanceof SuccessReusable.Success) {
+ SuccessReusable.Success action = (SuccessReusable.Success) item;
+ return action.getAction();
+ }
+ SuccessReusable.ReusableObj reusableObj = (SuccessReusable.ReusableObj) item;
+ return (SuccessAction) resolveReusableWithPrefix(reusableObj.getReusable(), "successActions");
+ }).collect(Collectors.toList());
+ }
+
+ /**
+ * Resolve the {@link FailureReusable} references to get a complete list of {@link FailureAction}
+ */
+ public List resolveFailureReusable(List items) {
+ if (items == null) {
+ return null;
+ }
+
+ return items.stream().map(item -> {
+ if (item instanceof FailureReusable.Failure) {
+ FailureReusable.Failure action = (FailureReusable.Failure) item;
+ return action.getAction();
+ }
+ FailureReusable.ReusableObj reusableObj = (FailureReusable.ReusableObj) item;
+ return (FailureAction) resolveReusableWithPrefix(reusableObj.getReusable(), "failureActions");
+ }).collect(Collectors.toList());
+ }
+
+ /**
+ * Resolve the {@link ParameterReusable} references to get a complete list of {@link Parameter}
+ */
+ public List resolveParametersReusable(List items) {
+ if (items == null) {
+ return null;
+ }
+
+ return items.stream().map(item -> {
+ if (item instanceof ParameterReusable.Param) {
+ ParameterReusable.Param param = (ParameterReusable.Param) item;
+ return param.getParameter();
+ }
+ ParameterReusable.ReusableObj reusableObj = (ParameterReusable.ReusableObj) item;
+ return (Parameter) resolveReusableWithPrefix(reusableObj.getReusable(), "parameters");
+ }).collect(Collectors.toList());
+ }
+
+ private Object resolveReusableWithPrefix(Reusable reusable, String expectedPrefix) {
+ if (components == null) {
+ throw new IllegalArgumentException("Arazzo Parsing Error: Can't reference with no Components");
+ }
+
+ String reference = reusable.getReference();
+ if (!reference.startsWith("$components.")) {
+ throw new IllegalArgumentException("Arazzo Parsing Error: Invalid reference (" + reference + "). Expected to point to '$components.'");
+ }
+
+ String referenceWithoutComponents = reference.substring(("$components.").length());
+ if (!referenceWithoutComponents.startsWith(expectedPrefix)) {
+ throw new IllegalArgumentException("Arazzo Parsing Error: Invalid reference (" + referenceWithoutComponents + "). Expected to point to '" + expectedPrefix +"'");
+ }
+
+ String referenceClean = referenceWithoutComponents.substring((expectedPrefix + ".").length());
+ Object resolve;
+ switch (expectedPrefix) {
+ case "successActions":
+ resolve = (components.getSuccessAction() != null) ? components.getSuccessAction().get(referenceClean) : null;
+ break;
+ case "failureActions":
+ resolve = (components.getFailureAction() != null) ? components.getFailureAction().get(referenceClean) : null;
+ break;
+ case "parameters":
+ resolve = (components.getParameters() != null) ? components.getParameters().get(referenceClean) : null;
+ break;
+ default:
+ resolve = null;
+ break;
+ }
+
+ if (resolve == null) {
+ throw new IllegalArgumentException("Arazzo Parsing Error: The " + expectedPrefix + ": '" + referenceClean + "' is not in the components.");
+ }
+
+ return resolve;
+
+ }
+
+ public Schema> resolveJsonPointer(String reference) {
+ if (reference.startsWith("#/")) {
+ return resolveJsonPointerLocal(reference);
+ }
+ return resolveJsonPointerExternal(reference);
+ }
+
+ private Schema> resolveJsonPointerLocal(String reference) {
+ if (arazzoJsonNode == null) {
+ throw new IllegalArgumentException("Arazzo Parsing Error: Can't reference with no Arazzo Document");
+ }
+
+ String jsonPointer = reference.substring(1);
+
+ JsonNode result = arazzoJsonNode.at(jsonPointer);
+
+ if (result.isMissingNode()) {
+ throw new IllegalArgumentException("Arazzo Parsing Error: Can't reference '" + reference + "'");
+ }
+
+ return Json.mapper().convertValue(result, Schema.class);
+ }
+
+ private Schema> resolveJsonPointerExternal(String reference) {
+ if (openApi == null) {
+ throw new IllegalArgumentException("Arazzo Parsing Error: Can't reference with no OpenApi Document");
+ }
+
+ String[] tokens = reference.split("#");
+ if (tokens.length < 2) {
+ throw new IllegalArgumentException("Arazzo Parsing Error: Error reference (" + reference + "). '#' Is mandatory");
+ }
+
+ String jsonPointer = tokens[1];
+ String expectedPrefix = "/components/schemas/";
+
+ if (!jsonPointer.startsWith(expectedPrefix)) {
+ throw new IllegalArgumentException("Arazzo Parsing Error: Error reference (" + reference + "). \"/components/schemas/\" Is mandatory for references to OpenApi");
+ }
+
+ String schemaName = jsonPointer.substring((expectedPrefix).length());
+ Schema> result = null;
+ if (openApi.getComponents() != null && openApi.getComponents().getSchemas() != null) {
+ result = openApi.getComponents().getSchemas().get(schemaName);
+ }
+
+ if (result == null) {
+ throw new IllegalArgumentException("Arazzo Parsing Error: (" + reference + ") reference does not exist in the OpenApi document");
+ }
+
+ return result;
+ }
+
+}
diff --git a/core-extra/arazzo-parser/src/test/java/arazzo/ArazzoParserTest.java b/core-extra/arazzo-parser/src/test/java/arazzo/ArazzoParserTest.java
new file mode 100644
index 0000000000..2798af4d3f
--- /dev/null
+++ b/core-extra/arazzo-parser/src/test/java/arazzo/ArazzoParserTest.java
@@ -0,0 +1,39 @@
+package arazzo;
+
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.parser.OpenAPIV3Parser;
+import org.dataloader.impl.Assertions;
+import org.evomaster.arazzo.access.ArazzoAccess;
+import org.evomaster.arazzo.models.domain.ArazzoSpecifications;
+import org.evomaster.arazzo.parser.ArazzoParser;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ArazzoParserTest {
+
+ private final String BASE_RESOURCE_ARAZZO = "src/test/resources/arazzo";
+ private final String BASE_RESOURCE_OPENAPI = "src/test/resources/openapi";
+
+ @Test
+ public void shouldParseArazzoYamlSuccessfully() throws Exception {
+ String schemaText = ArazzoAccess.readFromDisk(BASE_RESOURCE_ARAZZO + "/arazzo_pet.yaml");
+ OpenAPI openAPI = new OpenAPIV3Parser().read(BASE_RESOURCE_OPENAPI + "/openapi_pet.json");
+
+ ArazzoSpecifications arazzo = ArazzoParser.parse(schemaText, openAPI);
+
+ Assert.assertEquals(3, arazzo.getWorkflows().size());
+ Assert.assertEquals("Petstore - Apply Coupons", arazzo.getInfo().getTitle());
+ }
+
+ @Test
+ public void shouldParseArazzoJsonSuccessfully() throws Exception {
+ String schemaText = ArazzoAccess.readFromDisk(BASE_RESOURCE_ARAZZO + "/arazzo_pet.json");
+ OpenAPI openAPI = new OpenAPIV3Parser().read(BASE_RESOURCE_OPENAPI + "/openapi_pet.json");
+
+ ArazzoSpecifications arazzo = ArazzoParser.parse(schemaText, openAPI);
+
+ Assert.assertEquals(3, arazzo.getWorkflows().size());
+ Assert.assertEquals("Petstore - Apply Coupons", arazzo.getInfo().getTitle());
+ }
+
+}
diff --git a/core-extra/arazzo-parser/src/test/resources/arazzo/arazzo_pet.json b/core-extra/arazzo-parser/src/test/resources/arazzo/arazzo_pet.json
new file mode 100644
index 0000000000..47b817654c
--- /dev/null
+++ b/core-extra/arazzo-parser/src/test/resources/arazzo/arazzo_pet.json
@@ -0,0 +1,248 @@
+{
+ "arazzo": "1.0.0",
+ "info": {
+ "title": "Petstore - Apply Coupons",
+ "version": "1.0.0",
+ "description": "Illustrates a workflow whereby a client a) finds a pet in the petstore, b) finds coupons for that pet, and finally c) orders the pet while applying the coupons from step b."
+ },
+ "sourceDescriptions": [
+ {
+ "name": "pet-coupons",
+ "url": "./pet-coupons.openapi.yaml",
+ "type": "openapi"
+ }
+ ],
+ "workflows": [
+ {
+ "workflowId": "apply-coupon",
+ "summary": "Apply a coupon to a pet order.",
+ "description": "This is how you can find a pet, find an applicable coupon, and apply that coupon in your order. The workflow concludes by outputting the ID of the placed order.",
+ "inputs": {
+ "$ref": "#/components/inputs/apply_coupon_input"
+ },
+ "steps": [
+ {
+ "stepId": "find-pet",
+ "description": "Find a pet based on the provided tags.",
+ "operationId": "findPetsByTags",
+ "parameters": [
+ {
+ "name": "pet_tags",
+ "in": "query",
+ "value": "$inputs.my_pet_tags"
+ }
+ ],
+ "successCriteria": [
+ {
+ "condition": "$statusCode == 200"
+ }
+ ],
+ "outputs": {
+ "my_pet_id": "$response.body#/0/id"
+ }
+ },
+ {
+ "stepId": "find-coupons",
+ "description": "Find a coupon available for the selected pet.",
+ "operationId": "getPetCoupons",
+ "parameters": [
+ {
+ "name": "pet_id",
+ "in": "path",
+ "value": "$steps.find-pet.outputs.my_pet_id"
+ }
+ ],
+ "successCriteria": [
+ {
+ "condition": "$statusCode == 200"
+ }
+ ],
+ "outputs": {
+ "my_coupon_code": "$response.body#/couponCode"
+ }
+ },
+ {
+ "stepId": "place-order",
+ "description": "Place an order for the pet, applying the coupon.",
+ "workflowId": "place-order",
+ "parameters": [
+ {
+ "name": "pet_id",
+ "value": "$steps.find-pet.outputs.my_pet_id"
+ },
+ {
+ "name": "coupon_code",
+ "value": "$steps.find-coupons.outputs.my_coupon_code"
+ }
+ ],
+ "successCriteria": [
+ {
+ "condition": "$statusCode == 200"
+ }
+ ],
+ "outputs": {
+ "my_order_id": "$outputs.workflow_order_id"
+ }
+ }
+ ],
+ "outputs": {
+ "apply_coupon_pet_order_id": "$steps.place-order.outputs.my_order_id"
+ }
+ },
+ {
+ "workflowId": "buy-available-pet",
+ "summary": "Buy an available pet if one is available.",
+ "description": "This workflow demonstrates a workflow very similar to `apply-coupon`, by intention. It's meant to indicate how to reuse a step (`place-order`) as well as a parameter (`page`, `pageSize`).",
+ "inputs": {
+ "$ref": "#/components/inputs/buy_available_pet_input"
+ },
+ "steps": [
+ {
+ "stepId": "find-pet",
+ "description": "Find a pet that is available for purchase.",
+ "operationId": "findPetsByStatus",
+ "parameters": [
+ {
+ "name": "status",
+ "in": "query",
+ "value": "available"
+ },
+ {
+ "reference": "$components.parameters.page",
+ "value": 1
+ },
+ {
+ "reference": "$components.parameters.pageSize",
+ "value": 10
+ }
+ ],
+ "successCriteria": [
+ {
+ "condition": "$statusCode == 200"
+ }
+ ],
+ "outputs": {
+ "my_pet_id": "$response.body#/0/id"
+ }
+ },
+ {
+ "stepId": "place-order",
+ "description": "Place an order for the pet.",
+ "workflowId": "place-order",
+ "parameters": [
+ {
+ "name": "pet_id",
+ "value": "$steps.find-pet.outputs.my_pet_id"
+ }
+ ],
+ "successCriteria": [
+ {
+ "condition": "$statusCode == 200"
+ }
+ ],
+ "outputs": {
+ "my_order_id": "$outputs.workflow_order_id"
+ }
+ }
+ ],
+ "outputs": {
+ "buy_pet_order_id": "$steps.place-order.outputs.my_order_id"
+ }
+ },
+ {
+ "workflowId": "place-order",
+ "summary": "Place an order for a pet.",
+ "description": "This workflow places an order for a pet. It may be reused by other workflows as the \"final step\" in a purchase.",
+ "inputs": {
+ "type": "object",
+ "properties": {
+ "pet_id": {
+ "type": "integer",
+ "format": "int64",
+ "description": "The ID of the pet to place in the order."
+ },
+ "quantity": {
+ "type": "integer",
+ "format": "int32",
+ "description": "The number of pets to place in the order."
+ },
+ "coupon_code": {
+ "type": "string",
+ "description": "The coupon code to apply to the order."
+ }
+ }
+ },
+ "steps": [
+ {
+ "stepId": "place-order",
+ "description": "Place an order for the pet.",
+ "operationId": "placeOrder",
+ "requestBody": {
+ "contentType": "application/json",
+ "payload": {
+ "petId": "$inputs.pet_id",
+ "quantity": "$inputs.quantity",
+ "couponCode": "$inputs.coupon_code",
+ "status": "placed",
+ "complete": false
+ }
+ },
+ "successCriteria": [
+ {
+ "condition": "$statusCode == 200"
+ }
+ ],
+ "outputs": {
+ "step_order_id": "$response.body#/id"
+ }
+ }
+ ],
+ "outputs": {
+ "workflow_order_id": "$steps.place-order.outputs.step_order_id"
+ }
+ }
+ ],
+ "components": {
+ "inputs": {
+ "apply_coupon_input": {
+ "type": "object",
+ "properties": {
+ "my_pet_tags": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Desired tags to use when searching for a pet, in CSV format (e.g. \"puppy, dalmatian\")"
+ },
+ "store_id": {
+ "$ref": "#/components/inputs/store_id"
+ }
+ }
+ },
+ "buy_available_pet_input": {
+ "type": "object",
+ "properties": {
+ "store_id": {
+ "$ref": "#/components/inputs/store_id"
+ }
+ }
+ },
+ "store_id": {
+ "type": "string",
+ "description": "Indicates the domain name of the store where the customer is browsing or buying pets, e.g. \"pets.example.com\" or \"pets.example.co.uk\"."
+ }
+ },
+ "parameters": {
+ "page": {
+ "name": "page",
+ "in": "query",
+ "value": 1
+ },
+ "pageSize": {
+ "name": "pageSize",
+ "in": "query",
+ "value": 100
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/core-extra/arazzo-parser/src/test/resources/arazzo/arazzo_pet.yaml b/core-extra/arazzo-parser/src/test/resources/arazzo/arazzo_pet.yaml
new file mode 100644
index 0000000000..8a573b645e
--- /dev/null
+++ b/core-extra/arazzo-parser/src/test/resources/arazzo/arazzo_pet.yaml
@@ -0,0 +1,160 @@
+arazzo: 1.0.0
+info:
+ title: Petstore - Apply Coupons
+ version: 1.0.0
+ description: >-
+ Illustrates a workflow whereby a client a) finds a pet in the petstore,
+ b) finds coupons for that pet, and finally
+ c) orders the pet while applying the coupons from step b.
+sourceDescriptions:
+ - name: pet-coupons
+ url: ./pet-coupons.openapi.yaml
+ type: openapi
+workflows:
+ - workflowId: apply-coupon
+ summary: Apply a coupon to a pet order.
+ description: >-
+ This is how you can find a pet, find an applicable coupon, and apply that coupon in your order.
+ The workflow concludes by outputting the ID of the placed order.
+ inputs:
+ $ref: "#/components/inputs/apply_coupon_input"
+ steps:
+ - stepId: find-pet
+ description: Find a pet based on the provided tags.
+ operationId: findPetsByTags
+ parameters:
+ - name: pet_tags
+ in: query
+ value: $inputs.my_pet_tags
+ successCriteria:
+ - condition: $statusCode == 200
+ outputs:
+ my_pet_id: $response.body#/0/id
+ # there is some implied selection here - findPetsByTags responds with a list of pets,
+ # but the client only wants to choose one, and that's what will be provided to the next step.
+ # not totally sure how to indicate that.
+ - stepId: find-coupons
+ description: Find a coupon available for the selected pet.
+ operationId: getPetCoupons
+ parameters:
+ - name: pet_id
+ in: path
+ value: $steps.find-pet.outputs.my_pet_id
+ successCriteria:
+ - condition: $statusCode == 200
+ outputs:
+ my_coupon_code: $response.body#/couponCode
+ - stepId: place-order
+ description: Place an order for the pet, applying the coupon.
+ workflowId: place-order
+ parameters:
+ - name: pet_id
+ value: $steps.find-pet.outputs.my_pet_id
+ - name: coupon_code
+ value: $steps.find-coupons.outputs.my_coupon_code
+ successCriteria:
+ - condition: $statusCode == 200
+ outputs:
+ my_order_id: $outputs.workflow_order_id
+ outputs:
+ apply_coupon_pet_order_id: $steps.place-order.outputs.my_order_id
+ - workflowId: buy-available-pet
+ summary: Buy an available pet if one is available.
+ description:
+ This workflow demonstrates a workflow very similar to `apply-coupon`, by intention.
+ It's meant to indicate how to reuse a step (`place-order`) as well as a parameter (`page`, `pageSize`).
+ inputs:
+ $ref: "#/components/inputs/buy_available_pet_input"
+ steps:
+ - stepId: find-pet
+ description: Find a pet that is available for purchase.
+ operationId: findPetsByStatus
+ parameters:
+ - name: status
+ in: query
+ value: "available"
+ - reference: $components.parameters.page
+ value: 1
+ - reference: $components.parameters.pageSize
+ value: 10
+ successCriteria:
+ - condition: $statusCode == 200
+ outputs:
+ my_pet_id: $response.body#/0/id
+ - stepId: place-order
+ description: Place an order for the pet.
+ workflowId: place-order
+ parameters:
+ - name: pet_id
+ value: $steps.find-pet.outputs.my_pet_id
+ successCriteria:
+ - condition: $statusCode == 200
+ outputs:
+ my_order_id: $outputs.workflow_order_id
+ outputs:
+ buy_pet_order_id: $steps.place-order.outputs.my_order_id
+ - workflowId: place-order
+ summary: Place an order for a pet.
+ description:
+ This workflow places an order for a pet. It may be reused by other workflows as the "final step" in a purchase.
+ inputs:
+ type: object
+ properties:
+ pet_id:
+ type: integer
+ format: int64
+ description: The ID of the pet to place in the order.
+ quantity:
+ type: integer
+ format: int32
+ description: The number of pets to place in the order.
+ coupon_code:
+ type: string
+ description: The coupon code to apply to the order.
+ steps:
+ - stepId: place-order
+ description: Place an order for the pet.
+ operationId: placeOrder
+ requestBody:
+ contentType: application/json
+ payload:
+ petId: $inputs.pet_id
+ quantity: $inputs.quantity
+ couponCode: $inputs.coupon_code
+ status: placed
+ complete: false
+ successCriteria:
+ - condition: $statusCode == 200
+ outputs:
+ step_order_id: $response.body#/id
+ outputs:
+ workflow_order_id: $steps.place-order.outputs.step_order_id
+components:
+ inputs:
+ apply_coupon_input:
+ type: object
+ properties:
+ my_pet_tags:
+ type: array
+ items:
+ type: string
+ description: Desired tags to use when searching for a pet, in CSV format (e.g. "puppy, dalmatian")
+ store_id:
+ $ref: "#/components/inputs/store_id"
+ buy_available_pet_input:
+ type: object
+ properties:
+ store_id:
+ $ref: "#/components/inputs/store_id"
+ store_id:
+ type: string
+ description: Indicates the domain name of the store where the customer is browsing or buying pets, e.g. "pets.example.com" or "pets.example.co.uk".
+ parameters:
+ page:
+ name: page
+ in: query
+ value: 1
+ pageSize:
+ name: pageSize
+ in: query
+ value: 100
\ No newline at end of file
diff --git a/core-extra/arazzo-parser/src/test/resources/openapi/openapi_pet.json b/core-extra/arazzo-parser/src/test/resources/openapi/openapi_pet.json
new file mode 100644
index 0000000000..1b546da4a4
--- /dev/null
+++ b/core-extra/arazzo-parser/src/test/resources/openapi/openapi_pet.json
@@ -0,0 +1,1225 @@
+{
+ "openapi": "3.0.2",
+ "info": {
+ "title": "Swagger Petstore - OpenAPI 3.0",
+ "description": "This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about\nSwagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!\nYou can now help us improve the API whether it's by making changes to the definition itself or to the code.\nThat way, with time, we can improve the API in general, and expose some of the new features in OAS3.\n\nSome useful links:\n- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)\n- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)",
+ "termsOfService": "http://swagger.io/terms/",
+ "contact": {
+ "email": "apiteam@swagger.io"
+ },
+ "license": {
+ "name": "Apache 2.0",
+ "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+ },
+ "version": "1.0.17"
+ },
+ "externalDocs": {
+ "description": "Find out more about Swagger",
+ "url": "http://swagger.io"
+ },
+ "servers": [
+ {
+ "url": "/api/v3"
+ }
+ ],
+ "tags": [
+ {
+ "name": "pet",
+ "description": "Everything about your Pets",
+ "externalDocs": {
+ "description": "Find out more",
+ "url": "http://swagger.io"
+ }
+ },
+ {
+ "name": "store",
+ "description": "Access to Petstore orders",
+ "externalDocs": {
+ "description": "Find out more about our store",
+ "url": "http://swagger.io"
+ }
+ },
+ {
+ "name": "user",
+ "description": "Operations about user"
+ }
+ ],
+ "paths": {
+ "/pet": {
+ "put": {
+ "tags": [
+ "pet"
+ ],
+ "summary": "Update an existing pet",
+ "description": "Update an existing pet by Id",
+ "operationId": "updatePet",
+ "requestBody": {
+ "description": "Update an existent pet in the store",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ },
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ },
+ "application/x-www-form-urlencoded": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "200": {
+ "description": "Successful operation",
+ "content": {
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid ID supplied"
+ },
+ "404": {
+ "description": "Pet not found"
+ },
+ "405": {
+ "description": "Validation exception"
+ }
+ },
+ "security": [
+ {
+ "petstore_auth": [
+ "write:pets",
+ "read:pets"
+ ]
+ }
+ ]
+ },
+ "post": {
+ "tags": [
+ "pet"
+ ],
+ "summary": "Add a new pet to the store",
+ "description": "Add a new pet to the store",
+ "operationId": "addPet",
+ "requestBody": {
+ "description": "Create a new pet in the store",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ },
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ },
+ "application/x-www-form-urlencoded": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ },
+ "required": true
+ },
+ "responses": {
+ "200": {
+ "description": "Successful operation",
+ "content": {
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ }
+ },
+ "405": {
+ "description": "Invalid input"
+ }
+ },
+ "security": [
+ {
+ "petstore_auth": [
+ "write:pets",
+ "read:pets"
+ ]
+ }
+ ]
+ }
+ },
+ "/pet/findByStatus": {
+ "get": {
+ "tags": [
+ "pet"
+ ],
+ "summary": "Finds Pets by status",
+ "description": "Multiple status values can be provided with comma separated strings",
+ "operationId": "findPetsByStatus",
+ "parameters": [
+ {
+ "name": "status",
+ "in": "query",
+ "description": "Status values that need to be considered for filter",
+ "required": false,
+ "explode": true,
+ "schema": {
+ "type": "string",
+ "default": "available",
+ "enum": [
+ "available",
+ "pending",
+ "sold"
+ ]
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/xml": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ },
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid status value"
+ }
+ },
+ "security": [
+ {
+ "petstore_auth": [
+ "write:pets",
+ "read:pets"
+ ]
+ }
+ ]
+ }
+ },
+ "/pet/findByTags": {
+ "get": {
+ "tags": [
+ "pet"
+ ],
+ "summary": "Finds Pets by tags",
+ "description": "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.",
+ "operationId": "findPetsByTags",
+ "parameters": [
+ {
+ "name": "tags",
+ "in": "query",
+ "description": "Tags to filter by",
+ "required": false,
+ "explode": true,
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/xml": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ },
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid tag value"
+ }
+ },
+ "security": [
+ {
+ "petstore_auth": [
+ "write:pets",
+ "read:pets"
+ ]
+ }
+ ]
+ }
+ },
+ "/pet/{petId}": {
+ "get": {
+ "tags": [
+ "pet"
+ ],
+ "summary": "Find pet by ID",
+ "description": "Returns a single pet",
+ "operationId": "getPetById",
+ "parameters": [
+ {
+ "name": "petId",
+ "in": "path",
+ "description": "ID of pet to return",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid ID supplied"
+ },
+ "404": {
+ "description": "Pet not found"
+ }
+ },
+ "security": [
+ {
+ "api_key": []
+ },
+ {
+ "petstore_auth": [
+ "write:pets",
+ "read:pets"
+ ]
+ }
+ ]
+ },
+ "post": {
+ "tags": [
+ "pet"
+ ],
+ "summary": "Updates a pet in the store with form data",
+ "description": "",
+ "operationId": "updatePetWithForm",
+ "parameters": [
+ {
+ "name": "petId",
+ "in": "path",
+ "description": "ID of pet that needs to be updated",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "name",
+ "in": "query",
+ "description": "Name of pet that needs to be updated",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "status",
+ "in": "query",
+ "description": "Status of pet that needs to be updated",
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "405": {
+ "description": "Invalid input"
+ }
+ },
+ "security": [
+ {
+ "petstore_auth": [
+ "write:pets",
+ "read:pets"
+ ]
+ }
+ ]
+ },
+ "delete": {
+ "tags": [
+ "pet"
+ ],
+ "summary": "Deletes a pet",
+ "description": "",
+ "operationId": "deletePet",
+ "parameters": [
+ {
+ "name": "api_key",
+ "in": "header",
+ "description": "",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "petId",
+ "in": "path",
+ "description": "Pet id to delete",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ ],
+ "responses": {
+ "400": {
+ "description": "Invalid pet value"
+ }
+ },
+ "security": [
+ {
+ "petstore_auth": [
+ "write:pets",
+ "read:pets"
+ ]
+ }
+ ]
+ }
+ },
+ "/pet/{petId}/uploadImage": {
+ "post": {
+ "tags": [
+ "pet"
+ ],
+ "summary": "uploads an image",
+ "description": "",
+ "operationId": "uploadFile",
+ "parameters": [
+ {
+ "name": "petId",
+ "in": "path",
+ "description": "ID of pet to update",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ },
+ {
+ "name": "additionalMetadata",
+ "in": "query",
+ "description": "Additional Metadata",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "content": {
+ "application/octet-stream": {
+ "schema": {
+ "type": "string",
+ "format": "binary"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ApiResponse"
+ }
+ }
+ }
+ }
+ },
+ "security": [
+ {
+ "petstore_auth": [
+ "write:pets",
+ "read:pets"
+ ]
+ }
+ ]
+ }
+ },
+ "/store/inventory": {
+ "get": {
+ "tags": [
+ "store"
+ ],
+ "summary": "Returns pet inventories by status",
+ "description": "Returns a map of status codes to quantities",
+ "operationId": "getInventory",
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "integer",
+ "format": "int32"
+ }
+ }
+ }
+ }
+ }
+ },
+ "security": [
+ {
+ "api_key": []
+ }
+ ]
+ }
+ },
+ "/store/order": {
+ "post": {
+ "tags": [
+ "store"
+ ],
+ "summary": "Place an order for a pet",
+ "description": "Place a new order in the store",
+ "operationId": "placeOrder",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Order"
+ }
+ },
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/Order"
+ }
+ },
+ "application/x-www-form-urlencoded": {
+ "schema": {
+ "$ref": "#/components/schemas/Order"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Order"
+ }
+ }
+ }
+ },
+ "405": {
+ "description": "Invalid input"
+ }
+ }
+ }
+ },
+ "/store/order/{orderId}": {
+ "get": {
+ "tags": [
+ "store"
+ ],
+ "summary": "Find purchase order by ID",
+ "description": "For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions.",
+ "operationId": "getOrderById",
+ "parameters": [
+ {
+ "name": "orderId",
+ "in": "path",
+ "description": "ID of order that needs to be fetched",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/Order"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Order"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid ID supplied"
+ },
+ "404": {
+ "description": "Order not found"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "store"
+ ],
+ "summary": "Delete purchase order by ID",
+ "description": "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors",
+ "operationId": "deleteOrder",
+ "parameters": [
+ {
+ "name": "orderId",
+ "in": "path",
+ "description": "ID of the order that needs to be deleted",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ ],
+ "responses": {
+ "400": {
+ "description": "Invalid ID supplied"
+ },
+ "404": {
+ "description": "Order not found"
+ }
+ }
+ }
+ },
+ "/user": {
+ "post": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Create user",
+ "description": "This can only be done by the logged in user.",
+ "operationId": "createUser",
+ "requestBody": {
+ "description": "Created user object",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/User"
+ }
+ },
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/User"
+ }
+ },
+ "application/x-www-form-urlencoded": {
+ "schema": {
+ "$ref": "#/components/schemas/User"
+ }
+ }
+ }
+ },
+ "responses": {
+ "default": {
+ "description": "successful operation",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/User"
+ }
+ },
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/User"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/user/createWithList": {
+ "post": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Creates list of users with given input array",
+ "description": "Creates list of users with given input array",
+ "operationId": "createUsersWithListInput",
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/User"
+ }
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Successful operation",
+ "content": {
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/User"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/User"
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "successful operation"
+ }
+ }
+ }
+ },
+ "/user/login": {
+ "get": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Logs user into the system",
+ "description": "",
+ "operationId": "loginUser",
+ "parameters": [
+ {
+ "name": "username",
+ "in": "query",
+ "description": "The user name for login",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "password",
+ "in": "query",
+ "description": "The password for login in clear text",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "headers": {
+ "X-Rate-Limit": {
+ "description": "calls per hour allowed by the user",
+ "schema": {
+ "type": "integer",
+ "format": "int32"
+ }
+ },
+ "X-Expires-After": {
+ "description": "date in UTC when token expires",
+ "schema": {
+ "type": "string",
+ "format": "date-time"
+ }
+ }
+ },
+ "content": {
+ "application/xml": {
+ "schema": {
+ "type": "string"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid username/password supplied"
+ }
+ }
+ }
+ },
+ "/user/logout": {
+ "get": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Logs out current logged in user session",
+ "description": "",
+ "operationId": "logoutUser",
+ "parameters": [],
+ "responses": {
+ "default": {
+ "description": "successful operation"
+ }
+ }
+ }
+ },
+ "/user/{username}": {
+ "get": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Get user by user name",
+ "description": "",
+ "operationId": "getUserByName",
+ "parameters": [
+ {
+ "name": "username",
+ "in": "path",
+ "description": "The name that needs to be fetched. Use user1 for testing. ",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/User"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/User"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid username supplied"
+ },
+ "404": {
+ "description": "User not found"
+ }
+ }
+ },
+ "put": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Update user",
+ "description": "This can only be done by the logged in user.",
+ "operationId": "updateUser",
+ "parameters": [
+ {
+ "name": "username",
+ "in": "path",
+ "description": "name that needs to be updated",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "requestBody": {
+ "description": "Update an existent user in the store",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/User"
+ }
+ },
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/User"
+ }
+ },
+ "application/x-www-form-urlencoded": {
+ "schema": {
+ "$ref": "#/components/schemas/User"
+ }
+ }
+ }
+ },
+ "responses": {
+ "default": {
+ "description": "successful operation"
+ }
+ }
+ },
+ "delete": {
+ "tags": [
+ "user"
+ ],
+ "summary": "Delete user",
+ "description": "This can only be done by the logged in user.",
+ "operationId": "deleteUser",
+ "parameters": [
+ {
+ "name": "username",
+ "in": "path",
+ "description": "The name that needs to be deleted",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "400": {
+ "description": "Invalid username supplied"
+ },
+ "404": {
+ "description": "User not found"
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Order": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "example": 10
+ },
+ "petId": {
+ "type": "integer",
+ "format": "int64",
+ "example": 198772
+ },
+ "quantity": {
+ "type": "integer",
+ "format": "int32",
+ "example": 7
+ },
+ "shipDate": {
+ "type": "string",
+ "format": "date-time"
+ },
+ "status": {
+ "type": "string",
+ "description": "Order Status",
+ "example": "approved",
+ "enum": [
+ "placed",
+ "approved",
+ "delivered"
+ ]
+ },
+ "complete": {
+ "type": "boolean"
+ }
+ },
+ "xml": {
+ "name": "order"
+ }
+ },
+ "Customer": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "example": 100000
+ },
+ "username": {
+ "type": "string",
+ "example": "fehguy"
+ },
+ "address": {
+ "type": "array",
+ "xml": {
+ "name": "addresses",
+ "wrapped": true
+ },
+ "items": {
+ "$ref": "#/components/schemas/Address"
+ }
+ }
+ },
+ "xml": {
+ "name": "customer"
+ }
+ },
+ "Address": {
+ "type": "object",
+ "properties": {
+ "street": {
+ "type": "string",
+ "example": "437 Lytton"
+ },
+ "city": {
+ "type": "string",
+ "example": "Palo Alto"
+ },
+ "state": {
+ "type": "string",
+ "example": "CA"
+ },
+ "zip": {
+ "type": "string",
+ "example": "94301"
+ }
+ },
+ "xml": {
+ "name": "address"
+ }
+ },
+ "Category": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "example": 1
+ },
+ "name": {
+ "type": "string",
+ "example": "Dogs"
+ }
+ },
+ "xml": {
+ "name": "category"
+ }
+ },
+ "User": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "example": 10
+ },
+ "username": {
+ "type": "string",
+ "example": "theUser"
+ },
+ "firstName": {
+ "type": "string",
+ "example": "John"
+ },
+ "lastName": {
+ "type": "string",
+ "example": "James"
+ },
+ "email": {
+ "type": "string",
+ "example": "john@email.com"
+ },
+ "password": {
+ "type": "string",
+ "example": "12345"
+ },
+ "phone": {
+ "type": "string",
+ "example": "12345"
+ },
+ "userStatus": {
+ "type": "integer",
+ "description": "User Status",
+ "format": "int32",
+ "example": 1
+ }
+ },
+ "xml": {
+ "name": "user"
+ }
+ },
+ "Tag": {
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "name": {
+ "type": "string"
+ }
+ },
+ "xml": {
+ "name": "tag"
+ }
+ },
+ "Pet": {
+ "required": [
+ "name",
+ "photoUrls"
+ ],
+ "type": "object",
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "example": 10
+ },
+ "name": {
+ "type": "string",
+ "example": "doggie"
+ },
+ "category": {
+ "$ref": "#/components/schemas/Category"
+ },
+ "photoUrls": {
+ "type": "array",
+ "xml": {
+ "wrapped": true
+ },
+ "items": {
+ "type": "string",
+ "xml": {
+ "name": "photoUrl"
+ }
+ }
+ },
+ "tags": {
+ "type": "array",
+ "xml": {
+ "wrapped": true
+ },
+ "items": {
+ "$ref": "#/components/schemas/Tag"
+ }
+ },
+ "status": {
+ "type": "string",
+ "description": "pet status in the store",
+ "enum": [
+ "available",
+ "pending",
+ "sold"
+ ]
+ }
+ },
+ "xml": {
+ "name": "pet"
+ }
+ },
+ "ApiResponse": {
+ "type": "object",
+ "properties": {
+ "code": {
+ "type": "integer",
+ "format": "int32"
+ },
+ "type": {
+ "type": "string"
+ },
+ "message": {
+ "type": "string"
+ }
+ },
+ "xml": {
+ "name": "##default"
+ }
+ }
+ },
+ "requestBodies": {
+ "Pet": {
+ "description": "Pet object that needs to be added to the store",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ },
+ "application/xml": {
+ "schema": {
+ "$ref": "#/components/schemas/Pet"
+ }
+ }
+ }
+ },
+ "UserArray": {
+ "description": "List of user object",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/User"
+ }
+ }
+ }
+ }
+ }
+ },
+ "securitySchemes": {
+ "petstore_auth": {
+ "type": "oauth2",
+ "flows": {
+ "implicit": {
+ "authorizationUrl": "https://petstore.swagger.io/oauth/authorize",
+ "scopes": {
+ "write:pets": "modify pets in your account",
+ "read:pets": "read your pets"
+ }
+ }
+ }
+ },
+ "api_key": {
+ "type": "apiKey",
+ "name": "api_key",
+ "in": "header"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/core-extra/pom.xml b/core-extra/pom.xml
index a194c5338f..ecbdf8e5ba 100644
--- a/core-extra/pom.xml
+++ b/core-extra/pom.xml
@@ -16,5 +16,6 @@
dbconstraint
solver
+ arazzo-parser
\ No newline at end of file
diff --git a/core/pom.xml b/core/pom.xml
index ffae946f47..c02c021e17 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -354,37 +354,37 @@
maven-compiler-plugin
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+