From 7f1322bd0212770bb2104d9f5e683aaf4c58c653 Mon Sep 17 00:00:00 2001 From: Fritz Lumnitz Date: Thu, 17 Jan 2019 20:29:14 +0100 Subject: [PATCH] Implemented retrieving of schemaPath --- .../v2/api/model/v08/api/GlobalSchema.java | 4 +++ .../v2/api/model/v08/bodies/BodyLike.java | 5 +++ .../internal/impl/commons/model/BodyLike.java | 36 +++++++++++++++++++ .../impl/commons/model/GlobalSchema.java | 8 +++++ .../ExternalSchemaTypeExpressionNode.java | 2 +- .../v2/api/SpecInterfacesV08TestCase.java | 28 +++++++++++++-- .../v2/dataprovider/TestDataProvider.java | 2 +- .../raml/v2/api/v08/full/external.schema.json | 12 +++++++ .../org/raml/v2/api/v08/full/input.raml | 4 +++ .../org/raml/v2/api/v08/full/model.json | 26 ++++++++++++++ .../raml/yagi/framework/nodes/BaseNode.java | 9 +++++ .../framework/nodes/KeyValueNodeImpl.java | 11 ++++++ .../org/raml/yagi/framework/nodes/Node.java | 5 +++ 13 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 raml-parser-2/src/test/resources/org/raml/v2/api/v08/full/external.schema.json diff --git a/raml-parser-2/src/main/java/org/raml/v2/api/model/v08/api/GlobalSchema.java b/raml-parser-2/src/main/java/org/raml/v2/api/model/v08/api/GlobalSchema.java index 33a4f020..f41d1695 100755 --- a/raml-parser-2/src/main/java/org/raml/v2/api/model/v08/api/GlobalSchema.java +++ b/raml-parser-2/src/main/java/org/raml/v2/api/model/v08/api/GlobalSchema.java @@ -32,4 +32,8 @@ public interface GlobalSchema **/ SchemaString value(); + /** + * The path of the schema. If the schema is inlined returns the path inside the raml document. If the schema is included returns the complete path of the included schema. + */ + String path(); } \ No newline at end of file diff --git a/raml-parser-2/src/main/java/org/raml/v2/api/model/v08/bodies/BodyLike.java b/raml-parser-2/src/main/java/org/raml/v2/api/model/v08/bodies/BodyLike.java index 1bc06322..bbfd3449 100755 --- a/raml-parser-2/src/main/java/org/raml/v2/api/model/v08/bodies/BodyLike.java +++ b/raml-parser-2/src/main/java/org/raml/v2/api/model/v08/bodies/BodyLike.java @@ -54,4 +54,9 @@ public interface BodyLike extends RAMLLanguageElement **/ String schemaContent(); + /** + * Returns the path to the schema returned by {@link #schemaContent()}. If the schema is inlined, the path inside the RAML document is returned. If the schema is included, the original path of the schema is returned. If the schema is a reference, the path of the referenced schema is returned. + */ + String schemaPath(); + } \ No newline at end of file diff --git a/raml-parser-2/src/main/java/org/raml/v2/internal/impl/commons/model/BodyLike.java b/raml-parser-2/src/main/java/org/raml/v2/internal/impl/commons/model/BodyLike.java index a1dd36fd..35475c68 100644 --- a/raml-parser-2/src/main/java/org/raml/v2/internal/impl/commons/model/BodyLike.java +++ b/raml-parser-2/src/main/java/org/raml/v2/internal/impl/commons/model/BodyLike.java @@ -15,9 +15,13 @@ */ package org.raml.v2.internal.impl.commons.model; +import org.raml.v2.internal.impl.commons.nodes.ExternalSchemaTypeExpressionNode; +import org.raml.v2.internal.impl.commons.nodes.TypeExpressionNode; import org.raml.yagi.framework.model.AbstractNodeModel; import org.raml.yagi.framework.nodes.KeyValueNode; import org.raml.yagi.framework.nodes.Node; +import org.raml.yagi.framework.nodes.NullNode; +import org.raml.yagi.framework.nodes.SimpleTypeNode; import org.raml.yagi.framework.nodes.StringNode; import org.raml.yagi.framework.model.NodeModel; import org.raml.yagi.framework.util.NodeSelector; @@ -60,4 +64,36 @@ public String schemaContent() return null; } + public String schemaPath() + { + final Node schemaNode = NodeSelector.selectFrom("schema/*", getNode()); + final String schema; + if (schemaNode == null) + { + return null; // Not a Json or XML schema + } + else if (schemaNode instanceof TypeExpressionNode) + { + schema = ((TypeExpressionNode) schemaNode).getTypeExpressionText(); + } + else + schema = null; + // For an inline schema + if (schema == null || schema.startsWith("{") || schema.startsWith("<")) + { + return schemaNode.getPath(); + } + + // For an schema reference, + Node rootRamlSchema = NodeSelector.selectFrom("/schemas/" + schema, getNode()); + if (rootRamlSchema instanceof ExternalSchemaTypeExpressionNode) + { + return ((ExternalSchemaTypeExpressionNode) rootRamlSchema).getSchemaPath(); + } + else + { + return rootRamlSchema.getPath(); + } + + } } diff --git a/raml-parser-2/src/main/java/org/raml/v2/internal/impl/commons/model/GlobalSchema.java b/raml-parser-2/src/main/java/org/raml/v2/internal/impl/commons/model/GlobalSchema.java index a747d837..42501e27 100644 --- a/raml-parser-2/src/main/java/org/raml/v2/internal/impl/commons/model/GlobalSchema.java +++ b/raml-parser-2/src/main/java/org/raml/v2/internal/impl/commons/model/GlobalSchema.java @@ -15,6 +15,7 @@ */ package org.raml.v2.internal.impl.commons.model; +import org.raml.v2.internal.impl.commons.nodes.ExternalSchemaTypeExpressionNode; import org.raml.yagi.framework.model.AbstractNodeModel; import org.raml.yagi.framework.nodes.KeyValueNode; import org.raml.yagi.framework.nodes.Node; @@ -43,4 +44,11 @@ public StringType value() { return new StringType((SimpleTypeNode) node.getValue()); } + + public String path() + { + if (node.getValue() instanceof ExternalSchemaTypeExpressionNode) + return ((ExternalSchemaTypeExpressionNode) node.getValue()).getSchemaPath(); + return node.getPath(); + } } diff --git a/raml-parser-2/src/main/java/org/raml/v2/internal/impl/commons/nodes/ExternalSchemaTypeExpressionNode.java b/raml-parser-2/src/main/java/org/raml/v2/internal/impl/commons/nodes/ExternalSchemaTypeExpressionNode.java index 29b42d2c..69782a4b 100644 --- a/raml-parser-2/src/main/java/org/raml/v2/internal/impl/commons/nodes/ExternalSchemaTypeExpressionNode.java +++ b/raml-parser-2/src/main/java/org/raml/v2/internal/impl/commons/nodes/ExternalSchemaTypeExpressionNode.java @@ -51,7 +51,7 @@ public String getSchemaPath() { return this.getStartPosition().getIncludedResourceUri(); } - return this.getStartPosition().getPath(); + return this.getPath(); } @Nullable diff --git a/raml-parser-2/src/test/java/org/raml/v2/api/SpecInterfacesV08TestCase.java b/raml-parser-2/src/test/java/org/raml/v2/api/SpecInterfacesV08TestCase.java index cd76894f..59da9dac 100644 --- a/raml-parser-2/src/test/java/org/raml/v2/api/SpecInterfacesV08TestCase.java +++ b/raml-parser-2/src/test/java/org/raml/v2/api/SpecInterfacesV08TestCase.java @@ -17,11 +17,14 @@ import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.anyOf; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.junit.Assert.*; import java.io.File; import java.io.IOException; +import java.net.URI; import java.util.List; import org.junit.Test; @@ -39,11 +42,16 @@ public class SpecInterfacesV08TestCase { + private URI externalSchemaUri; + @Test public void full() throws IOException { File input = new File("src/test/resources/org/raml/v2/api/v08/full/input.raml"); assertTrue(input.isFile()); + File externalSchema = new File(input.getParentFile(), "external.schema.json"); + assertTrue(externalSchema.isFile()); + externalSchemaUri = externalSchema.toURI().normalize(); RamlModelResult ramlModelResult = new RamlModelBuilder().buildApi(input); assertFalse(ramlModelResult.hasErrors()); Api api = ramlModelResult.getApiV08(); @@ -60,10 +68,14 @@ private void assertApi(Api api) assertThat(api.protocols().get(0), is("HTTP")); assertThat(api.protocols().get(1), is("HTTPS")); - assertThat(api.schemas().size(), is(2)); + assertThat(api.schemas().size(), is(3)); assertThat(api.schemas().get(0).key(), is("UserJson")); + assertThat(api.schemas().get(0).path(), is("schemas/UserJson")); assertThat(api.schemas().get(0).value().value(), containsString("\"firstname\": { \"type\": \"string\" }")); assertThat(api.schemas().get(1).key(), is("UserXml")); + assertThat(api.schemas().get(1).path(), is("schemas/UserXml")); + assertThat(api.schemas().get(2).key(), is("External")); + assertThat(URI.create(api.schemas().get(2).path()).normalize(), equalTo(externalSchemaUri)); assertDocumentation(api.documentation()); assertTraits(api.traits()); @@ -123,6 +135,7 @@ private void assertResources(List resources) assertThat(childrenBody.name(), is("application/json")); assertThat(childrenBody.schemaContent(), containsString("\"firstname\": { \"type\": \"string\" }")); assertThat(childrenBody.schema().value(), is("UserJson")); + assertThat(childrenBody.schemaPath(), is("schemas/UserJson")); Resource childId = child.resources().get(0); assertThat(childId.uriParameters(), hasSize(1)); @@ -190,18 +203,20 @@ private void assertResponses(List responses) private void assertBody(List body) { - assertThat(body.size(), is(4)); + assertThat(body.size(), is(5)); BodyLike appJson = body.get(0); assertThat(appJson.name(), is("application/json")); assertThat(appJson.example().value(), containsString("\"firstname\": \"tato\"")); assertThat(appJson.schema().value(), is("UserJson")); assertThat(appJson.schemaContent(), containsString("\"firstname\": { \"type\": \"string\" }")); + assertThat(appJson.schemaPath(), is("schemas/UserJson")); BodyLike xml = body.get(1); assertThat(xml.name(), is("application/xml")); assertThat(xml.schema().value(), is("UserXml")); assertThat(xml.schemaContent(), containsString("")); + assertThat(xml.schemaPath(), is("schemas/UserXml")); BodyLike multipart = body.get(2); assertThat(multipart.formParameters().size(), is(2)); @@ -211,5 +226,14 @@ private void assertBody(List body) assertThat(vndJson.name(), is("application/vnd.inline+json")); assertThat(vndJson.schema().value(), containsString("\"input\": {")); assertThat(vndJson.schemaContent(), containsString("\"input\": {")); + assertThat(vndJson.schemaPath(), anyOf( + is("\\/top/post/body/application\\/vnd.inline+json/schema"), // for the direct body in the request + is("\\/top/post/responses/200/body/application\\/vnd.inline+json/schema"))); // the anchor body in the response + + BodyLike vndExternalJson = body.get(4); + assertThat(vndExternalJson.name(), is("application/vnd.external+json")); + assertThat(vndExternalJson.schema().value(), is("External")); + assertThat(vndExternalJson.schemaContent(), containsString("\"stringProperty\": {")); + assertThat(URI.create(vndExternalJson.schemaPath()).normalize(), equalTo(externalSchemaUri)); } } diff --git a/raml-parser-2/src/test/java/org/raml/v2/dataprovider/TestDataProvider.java b/raml-parser-2/src/test/java/org/raml/v2/dataprovider/TestDataProvider.java index f97e191b..28ce4d62 100644 --- a/raml-parser-2/src/test/java/org/raml/v2/dataprovider/TestDataProvider.java +++ b/raml-parser-2/src/test/java/org/raml/v2/dataprovider/TestDataProvider.java @@ -172,7 +172,7 @@ private JsonNode filterNodes(JsonNode jsonNode) protected String[] getKeysToFilter() { - return new String[] {"schemaPath"}; + return new String[] {"schemaPath", "path"}; } } diff --git a/raml-parser-2/src/test/resources/org/raml/v2/api/v08/full/external.schema.json b/raml-parser-2/src/test/resources/org/raml/v2/api/v08/full/external.schema.json new file mode 100644 index 00000000..c651c151 --- /dev/null +++ b/raml-parser-2/src/test/resources/org/raml/v2/api/v08/full/external.schema.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "type": "object", + "properties": { + "stringProperty": { + "type": "string" + } + }, + "required": [ + "stringProperty" + ] +} \ No newline at end of file diff --git a/raml-parser-2/src/test/resources/org/raml/v2/api/v08/full/input.raml b/raml-parser-2/src/test/resources/org/raml/v2/api/v08/full/input.raml index ffffeae8..83cc455e 100644 --- a/raml-parser-2/src/test/resources/org/raml/v2/api/v08/full/input.raml +++ b/raml-parser-2/src/test/resources/org/raml/v2/api/v08/full/input.raml @@ -46,6 +46,8 @@ schemas: + + - External: !include external.schema.json traits: one: description: method description from trait one @@ -107,6 +109,8 @@ resourceTypes: "required": false, "type": "object" } + application/vnd.external+json: + schema: External responses: 200: body: *bodyPost diff --git a/raml-parser-2/src/test/resources/org/raml/v2/api/v08/full/model.json b/raml-parser-2/src/test/resources/org/raml/v2/api/v08/full/model.json index 8bfc25c3..b78996aa 100644 --- a/raml-parser-2/src/test/resources/org/raml/v2/api/v08/full/model.json +++ b/raml-parser-2/src/test/resources/org/raml/v2/api/v08/full/model.json @@ -191,6 +191,16 @@ "value": "{\n \"$schema\": \"http://json-schema.org/draft-03/schema\",\n \"properties\": {\n \"input\": {\n \"required\": false,\n \"type\": \"string\"\n }\n },\n \"required\": false,\n \"type\": \"object\"\n}\n" }, "schemaContent": "{\n \"$schema\": \"http://json-schema.org/draft-03/schema\",\n \"properties\": {\n \"input\": {\n \"required\": false,\n \"type\": \"string\"\n }\n },\n \"required\": false,\n \"type\": \"object\"\n}\n" + }, + { + "description": null, + "example": null, + "formParameters": [], + "name": "application/vnd.external+json", + "schema": { + "value": "External" + }, + "schemaContent": "{\n\t\"$schema\": \"http://json-schema.org/draft-04/schema\",\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"stringProperty\": {\n\t\t\t\"type\": \"string\"\n\t\t}\n\t},\n\t\"required\": [\n\t\t\"stringProperty\"\n\t]\n}" } ], "description": { @@ -268,6 +278,16 @@ "value": "{\n \"$schema\": \"http://json-schema.org/draft-03/schema\",\n \"properties\": {\n \"input\": {\n \"required\": false,\n \"type\": \"string\"\n }\n },\n \"required\": false,\n \"type\": \"object\"\n}\n" }, "schemaContent": "{\n \"$schema\": \"http://json-schema.org/draft-03/schema\",\n \"properties\": {\n \"input\": {\n \"required\": false,\n \"type\": \"string\"\n }\n },\n \"required\": false,\n \"type\": \"object\"\n}\n" + }, + { + "description": null, + "example": null, + "formParameters": [], + "name": "application/vnd.external+json", + "schema": { + "value": "External" + }, + "schemaContent": "{\n\t\"$schema\": \"http://json-schema.org/draft-04/schema\",\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"stringProperty\": {\n\t\t\t\"type\": \"string\"\n\t\t}\n\t},\n\t\"required\": [\n\t\t\"stringProperty\"\n\t]\n}" } ], "code": { @@ -399,6 +419,12 @@ "value": { "value": "\n \n \n \n \n \n \n \n\n" } + }, + { + "key": "External", + "value": { + "value": "{\n\t\"$schema\": \"http://json-schema.org/draft-04/schema\",\n\t\"type\": \"object\",\n\t\"properties\": {\n\t\t\"stringProperty\": {\n\t\t\t\"type\": \"string\"\n\t\t}\n\t},\n\t\"required\": [\n\t\t\"stringProperty\"\n\t]\n}" + } } ], "securedBy": [], diff --git a/yagi/src/main/java/org/raml/yagi/framework/nodes/BaseNode.java b/yagi/src/main/java/org/raml/yagi/framework/nodes/BaseNode.java index 35d8e359..a4867110 100644 --- a/yagi/src/main/java/org/raml/yagi/framework/nodes/BaseNode.java +++ b/yagi/src/main/java/org/raml/yagi/framework/nodes/BaseNode.java @@ -226,4 +226,13 @@ public void setContextNode(Node node) { this.contextNode = node; } + + @Override + public String getPath() + { + final Node parent = getParent(); + if (parent == null) + return ""; + return parent.getPath(); + } } diff --git a/yagi/src/main/java/org/raml/yagi/framework/nodes/KeyValueNodeImpl.java b/yagi/src/main/java/org/raml/yagi/framework/nodes/KeyValueNodeImpl.java index 78f0bb47..6c427a26 100644 --- a/yagi/src/main/java/org/raml/yagi/framework/nodes/KeyValueNodeImpl.java +++ b/yagi/src/main/java/org/raml/yagi/framework/nodes/KeyValueNodeImpl.java @@ -144,4 +144,15 @@ public NodeType getType() { return NodeType.KeyValue; } + + @Override + public String getPath() + { + final String delimiter; + if (getRootNode() == getParent()) + delimiter = ""; + else + delimiter = "/"; + return super.getPath() + delimiter + String.valueOf(getKey()).replace("/", "\\/"); + } } diff --git a/yagi/src/main/java/org/raml/yagi/framework/nodes/Node.java b/yagi/src/main/java/org/raml/yagi/framework/nodes/Node.java index c86751b3..92af3596 100644 --- a/yagi/src/main/java/org/raml/yagi/framework/nodes/Node.java +++ b/yagi/src/main/java/org/raml/yagi/framework/nodes/Node.java @@ -179,4 +179,9 @@ public interface Node void setContextNode(Node node); Node getContextNode(); + + /** + * Get the path within the raml document. + */ + String getPath(); }