From c4c739f038ef1b0dddb8810afdc7733ff7fac9fc Mon Sep 17 00:00:00 2001 From: Oleksandr Zharov Date: Tue, 8 Aug 2023 12:36:28 +0200 Subject: [PATCH] Do not use TOP schemas in RPC requests Refactored RPC operations in order to stop using TOP schemas for generation of it's request body. JIRA: NETCONF-1057 Change-Id: Ib5bf2a258a8aa9df515a9a466ddcbc5a99a0dea4 Signed-off-by: Oleksandr Zharov --- .../model/builder/OperationBuilder.java | 33 +++++--------- .../restconf/openapi/OperationalDataTest.java | 20 ++++----- .../impl/OpenApiGeneratorRFC8040Test.java | 44 +++++++++---------- 3 files changed, 41 insertions(+), 56 deletions(-) diff --git a/restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/model/builder/OperationBuilder.java b/restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/model/builder/OperationBuilder.java index 558513280c..1184162b03 100644 --- a/restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/model/builder/OperationBuilder.java +++ b/restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/model/builder/OperationBuilder.java @@ -56,12 +56,9 @@ public final class OperationBuilder { final var summary = SUMMARY_TEMPLATE.formatted(HttpMethod.POST, deviceName, moduleName, nodeName); final List tags = List.of(deviceName + " " + moduleName); final List parameters = new ArrayList<>(pathParams); - final ObjectNode ref = JsonNodeFactory.instance.objectNode(); final String cleanDefName = parentName + "_" + nodeName; final String defName = cleanDefName + discriminator; - final String xmlDefName = cleanDefName + discriminator; - ref.put(REF_KEY, COMPONENTS_PREFIX + defName); - final ObjectNode requestBody = createRequestBodyParameter(defName, xmlDefName, nodeName, summary); + final ObjectNode requestBody = createPostDataRequestBodyParameter(defName, nodeName); final ObjectNode responses = JsonNodeFactory.instance.objectNode(); responses.set(String.valueOf(Response.Status.CREATED.getStatusCode()), buildResponse(Response.Status.CREATED.getReasonPhrase())); @@ -91,7 +88,7 @@ public final class OperationBuilder { final boolean isList = node instanceof ListSchemaNode; final ObjectNode response; if (isConfig) { - response = createRequestBodyParameter1(defName, nodeName, isList, summary, + response = createRequestBodyParameter(defName, nodeName, isList, summary, String.valueOf(Response.Status.OK.getStatusCode())); } else { response = JsonNodeFactory.instance.objectNode(); @@ -130,7 +127,7 @@ public final class OperationBuilder { final List parameters = new ArrayList<>(pathParams); final String defName = parentName + "_" + nodeName; final boolean isList = node instanceof ListSchemaNode; - final ObjectNode requestBody = createRequestBodyParameter1(defName, fullName, isList, summary, nodeName); + final ObjectNode requestBody = createRequestBodyParameter(defName, fullName, isList, summary, nodeName); final ObjectNode responses = JsonNodeFactory.instance.objectNode(); responses.set(String.valueOf(Response.Status.CREATED.getStatusCode()), @@ -155,7 +152,7 @@ public final class OperationBuilder { final List parameters = new ArrayList<>(pathParams); final String defName = parentName + "_" + nodeName; final boolean isList = node instanceof ListSchemaNode; - final ObjectNode requestBody = createRequestBodyParameter1(defName, fullName, isList, summary, nodeName); + final ObjectNode requestBody = createRequestBodyParameter(defName, fullName, isList, summary, nodeName); final ObjectNode responses = JsonNodeFactory.instance.objectNode(); responses.set(String.valueOf(Response.Status.OK.getStatusCode()), @@ -207,8 +204,7 @@ public final class OperationBuilder { final String discriminator = definitionNames.getDiscriminator(input); final String clearDefName = parentName + "_" + operationName + INPUT_SUFFIX; final String defName = clearDefName + discriminator; - final String defTopName = clearDefName + TOP + discriminator; - requestBody = createRequestBodyParameter(defTopName, defName, inputName, summary); + requestBody = createRequestBodyParameter(defName, INPUT_KEY, false, summary, inputName); } else { final ObjectNode payload = JsonNodeFactory.instance.objectNode(); final ObjectNode jsonSchema = JsonNodeFactory.instance.objectNode(); @@ -241,7 +237,7 @@ public final class OperationBuilder { if (!output.getChildNodes().isEmpty()) { final ObjectNode schema = JsonNodeFactory.instance.objectNode(); - final String defName = parentName + "_" + operationName + OUTPUT_SUFFIX + TOP + final String defName = parentName + "_" + operationName + OUTPUT_SUFFIX + definitionNames.getDiscriminator(output); schema.put(REF_KEY, COMPONENTS_PREFIX + defName); responses.set(String.valueOf(Response.Status.OK.getStatusCode()), buildResponse(description, schema)); @@ -260,25 +256,18 @@ public final class OperationBuilder { .build(); } - private static ObjectNode createRequestBodyParameter(final String defName, final String xmlDefName, - final String name, final String summary) { + private static ObjectNode createPostDataRequestBodyParameter(final String defName, final String name) { final ObjectNode payload = JsonNodeFactory.instance.objectNode(); final ObjectNode content = JsonNodeFactory.instance.objectNode(); - if (summary != null && summary.contains(HttpMethod.PATCH)) { - content.set("application/yang-data+json", buildMimeTypeValue(defName)); - content.set("application/yang-data+xml", buildMimeTypeValue(xmlDefName)); - } else { - content.set(MediaType.APPLICATION_JSON, buildMimeTypeValue(defName)); - content.set(MediaType.APPLICATION_XML, buildMimeTypeValue(xmlDefName)); - } + final ObjectNode value = buildMimeTypeValue(defName); + content.set(MediaType.APPLICATION_JSON, value); + content.set(MediaType.APPLICATION_XML, value); payload.set(CONTENT_KEY, content); payload.put(DESCRIPTION_KEY, name); return payload; } - // TODO change name after this method will be finished.(for now it's just PUT and PATCH but there might be more - // in next patches) - private static ObjectNode createRequestBodyParameter1(final String defName, final String name, + private static ObjectNode createRequestBodyParameter(final String defName, final String name, final boolean isList, final String summary, final String description) { final ObjectNode payload = JsonNodeFactory.instance.objectNode(); final ObjectNode content = JsonNodeFactory.instance.objectNode(); diff --git a/restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/OperationalDataTest.java b/restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/OperationalDataTest.java index 5fae1d2a70..1c644c0ec9 100644 --- a/restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/OperationalDataTest.java +++ b/restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/OperationalDataTest.java @@ -111,28 +111,27 @@ public class OperationalDataTest { final var content = response.get("content"); // In case of 200 no content and Operational data if (content != null) { - verifyOperationHaveCorrectReference(content.get("application/xml")); - // TODO re-enable it in next patch after refactoring -// verifyOperationHaveCorrectReference(content.get("application/json")); + verifyOperationHaveCorrectXmlReference(content.get("application/xml").get("schema")); + verifyOperationHaveCorrectJsonReference(content.get("application/json").get("schema")); } } if (path.put() != null) { final var responses = path.put().requestBody(); final var content = responses.get("content"); - verifyOperationHaveCorrectReference(content.get("application/xml")); - verifyOperationHaveCorrectJsonReference(content.get("application/json")); + verifyOperationHaveCorrectXmlReference(content.get("application/xml").get("schema")); + verifyOperationHaveCorrectJsonReference(content.get("application/json").get("schema")); } if (path.post() != null) { final var responses = path.post().requestBody(); final var content = responses.get("content"); - verifyOperationHaveCorrectReference(content.get("application/xml")); - verifyOperationHaveCorrectReference(content.get("application/json")); + verifyOperationHaveCorrectXmlReference(content.get("application/xml").get("schema")); + verifyOperationHaveCorrectJsonReference(content.get("application/json").get("schema")); } if (path.patch() != null) { final var responses = path.patch().requestBody(); final var content = responses.get("content"); - verifyOperationHaveCorrectReference(content.get("application/yang-data+xml")); - verifyOperationHaveCorrectJsonReference(content.get("application/yang-data+json")); + verifyOperationHaveCorrectXmlReference(content.get("application/yang-data+xml").get("schema")); + verifyOperationHaveCorrectJsonReference(content.get("application/yang-data+json").get("schema")); } } } @@ -207,8 +206,7 @@ public class OperationalDataTest { assertEquals(Set.of("ca-output"), actualProperties); } - private static void verifyOperationHaveCorrectReference(final JsonNode jsonNode) { - final var schema = jsonNode.get("schema"); + private static void verifyOperationHaveCorrectXmlReference(final JsonNode schema) { final var ref = schema.get("$ref"); // In case of a POST RPC with a direct input body and no reference value if (ref != null) { diff --git a/restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/impl/OpenApiGeneratorRFC8040Test.java b/restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/impl/OpenApiGeneratorRFC8040Test.java index 39350e108a..f387ae4edc 100644 --- a/restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/impl/OpenApiGeneratorRFC8040Test.java +++ b/restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/impl/OpenApiGeneratorRFC8040Test.java @@ -318,10 +318,10 @@ public final class OpenApiGeneratorRFC8040Test { assertEquals(Set.of("/rests/data", "/rests/data/my-yang:data"), doc.paths().keySet()); final var JsonNodeMyYangData = doc.paths().get("/rests/data/my-yang:data"); - verifyRequestRef(JsonNodeMyYangData.post(), "#/components/schemas/my-yang_data", + verifyPostDataRequestRef(JsonNodeMyYangData.post(), "#/components/schemas/my-yang_data", "#/components/schemas/my-yang_data"); - verifyRequestRef1(JsonNodeMyYangData.put(), "#/components/schemas/my-yang_data", CONTAINER); - verifyRequestRef1(JsonNodeMyYangData.get(), "#/components/schemas/my-yang_data", CONTAINER); + verifyRequestRef(JsonNodeMyYangData.put(), "#/components/schemas/my-yang_data", CONTAINER); + verifyRequestRef(JsonNodeMyYangData.get(), "#/components/schemas/my-yang_data", CONTAINER); // Test `components/schemas` objects final var definitions = doc.components().schemas(); @@ -336,42 +336,41 @@ public final class OpenApiGeneratorRFC8040Test { final var doc = generator.getApiDeclaration(TOASTER_2, REVISION_DATE, uriInfo); final var jsonNodeToaster = doc.paths().get("/rests/data/toaster2:toaster"); - verifyRequestRef(jsonNodeToaster.post(), "#/components/schemas/toaster2_toaster", + verifyPostDataRequestRef(jsonNodeToaster.post(), "#/components/schemas/toaster2_toaster", "#/components/schemas/toaster2_toaster"); - verifyRequestRef1(jsonNodeToaster.put(), "#/components/schemas/toaster2_toaster", CONTAINER); - verifyRequestRef1(jsonNodeToaster.get(), "#/components/schemas/toaster2_toaster", CONTAINER); + verifyRequestRef(jsonNodeToaster.put(), "#/components/schemas/toaster2_toaster", CONTAINER); + verifyRequestRef(jsonNodeToaster.get(), "#/components/schemas/toaster2_toaster", CONTAINER); final var jsonNodeToasterSlot = doc.paths().get("/rests/data/toaster2:toaster/toasterSlot={slotId}"); - verifyRequestRef(jsonNodeToasterSlot.post(), "#/components/schemas/toaster2_toaster_toasterSlot", + verifyPostDataRequestRef(jsonNodeToasterSlot.post(), "#/components/schemas/toaster2_toaster_toasterSlot", "#/components/schemas/toaster2_toaster_toasterSlot"); - verifyRequestRef1(jsonNodeToasterSlot.put(), "#/components/schemas/toaster2_toaster_toasterSlot", LIST); - verifyRequestRef1(jsonNodeToasterSlot.get(), "#/components/schemas/toaster2_toaster_toasterSlot", LIST); + verifyRequestRef(jsonNodeToasterSlot.put(), "#/components/schemas/toaster2_toaster_toasterSlot", LIST); + verifyRequestRef(jsonNodeToasterSlot.get(), "#/components/schemas/toaster2_toaster_toasterSlot", LIST); final var jsonNodeSlotInfo = doc.paths().get( "/rests/data/toaster2:toaster/toasterSlot={slotId}/toaster-augmented:slotInfo"); - verifyRequestRef(jsonNodeSlotInfo.post(), "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo", + verifyPostDataRequestRef(jsonNodeSlotInfo.post(), "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo", "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo"); - verifyRequestRef1(jsonNodeSlotInfo.put(), "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo", + verifyRequestRef(jsonNodeSlotInfo.put(), "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo", CONTAINER); - verifyRequestRef1(jsonNodeSlotInfo.get(), "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo", + verifyRequestRef(jsonNodeSlotInfo.get(), "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo", CONTAINER); final var jsonNodeLst = doc.paths().get("/rests/data/toaster2:lst={lf1}"); - verifyRequestRef(jsonNodeLst.post(), "#/components/schemas/toaster2_lst", + verifyPostDataRequestRef(jsonNodeLst.post(), "#/components/schemas/toaster2_lst", "#/components/schemas/toaster2_lst"); - verifyRequestRef1(jsonNodeLst.put(), "#/components/schemas/toaster2_lst", LIST); - verifyRequestRef1(jsonNodeLst.get(), "#/components/schemas/toaster2_lst", LIST); + verifyRequestRef(jsonNodeLst.put(), "#/components/schemas/toaster2_lst", LIST); + verifyRequestRef(jsonNodeLst.get(), "#/components/schemas/toaster2_lst", LIST); final var jsonNodeLst1 = doc.paths().get("/rests/data/toaster2:lst={lf1}/lst1={key1},{key2}"); - verifyRequestRef(jsonNodeLst1.post(), "#/components/schemas/toaster2_lst_lst1", + verifyPostDataRequestRef(jsonNodeLst1.post(), "#/components/schemas/toaster2_lst_lst1", "#/components/schemas/toaster2_lst_lst1"); - verifyRequestRef1(jsonNodeLst1.put(), "#/components/schemas/toaster2_lst_lst1", LIST); - verifyRequestRef1(jsonNodeLst1.get(), "#/components/schemas/toaster2_lst_lst1", LIST); + verifyRequestRef(jsonNodeLst1.put(), "#/components/schemas/toaster2_lst_lst1", LIST); + verifyRequestRef(jsonNodeLst1.get(), "#/components/schemas/toaster2_lst_lst1", LIST); final var jsonNodeMakeToast = doc.paths().get("/rests/operations/toaster2:make-toast"); assertNull(jsonNodeMakeToast.get()); - verifyRequestRef(jsonNodeMakeToast.post(), "#/components/schemas/toaster2_make-toast_input_TOP", - "#/components/schemas/toaster2_make-toast_input"); + verifyRequestRef(jsonNodeMakeToast.post(), "#/components/schemas/toaster2_make-toast_input", CONTAINER); final var jsonNodeCancelToast = doc.paths().get("/rests/operations/toaster2:cancel-toast"); assertNull(jsonNodeCancelToast.get()); @@ -404,7 +403,7 @@ public final class OpenApiGeneratorRFC8040Test { /** * Test JSON and XML references for request operation. */ - private static void verifyRequestRef(final Operation operation, final String expectedJsonRef, + private static void verifyPostDataRequestRef(final Operation operation, final String expectedJsonRef, final String expectedXmlRef) { final JsonNode postContent; if (operation.requestBody() != null) { @@ -421,8 +420,7 @@ public final class OpenApiGeneratorRFC8040Test { assertEquals(expectedXmlRef, postXmlRef.textValue()); } - private static void verifyRequestRef1(final Operation operation, final String expectedRef, - final String nodeType) { + private static void verifyRequestRef(final Operation operation, final String expectedRef, final String nodeType) { final JsonNode postContent; if (operation.requestBody() != null) { postContent = operation.requestBody().path("content"); -- 2.36.6