Remove _XML and _POST containers from OpenApi 42/105042/20
authorPeter Suna <peter.suna@pantheon.tech>
Mon, 27 Mar 2023 11:38:29 +0000 (13:38 +0200)
committerIvan Hrasko <ivan.hrasko@pantheon.tech>
Fri, 2 Jun 2023 12:31:43 +0000 (14:31 +0200)
There is no need to create containers for XML since OpenAPI
can convert the provided data to XML format. Additionally,
containers with the "_POST" extension are identical to those
without it, so creating them only consumes memory
resources unnecessarily.

JIRA: NETCONF-938
Change-Id: I14ac602df087c5115d78daa1425841fd5a54e577
Signed-off-by: Peter Suna <peter.suna@pantheon.tech>
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/DefinitionGenerator.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/model/builder/OperationBuilder.java
restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/impl/OpenApiGeneratorRFC8040Test.java

index 0c101e4a84dcbd4db156fa2401b6d7699966488b..383f274cf2063e19c8d235cba4f2fcde5092bcad 100644 (file)
@@ -11,12 +11,9 @@ import static org.opendaylight.restconf.openapi.impl.BaseYangOpenApiGenerator.MO
 import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.COMPONENTS_PREFIX;
 import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.CONFIG;
 import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.NAME_KEY;
 import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.COMPONENTS_PREFIX;
 import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.CONFIG;
 import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.NAME_KEY;
-import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.POST_SUFFIX;
 import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.TOP;
 import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.XML_KEY;
 import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.TOP;
 import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.XML_KEY;
-import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.XML_SUFFIX;
 
 
-import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -28,13 +25,10 @@ import java.io.IOException;
 import java.math.BigDecimal;
 import java.util.Collection;
 import java.util.HashMap;
 import java.math.BigDecimal;
 import java.util.Collection;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-import java.util.Set;
 import java.util.regex.Pattern;
 import java.util.regex.Pattern;
-import java.util.stream.Collectors;
 import org.opendaylight.restconf.openapi.model.Schema;
 import org.opendaylight.yangtools.yang.common.Decimal64;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.restconf.openapi.model.Schema;
 import org.opendaylight.yangtools.yang.common.Decimal64;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -386,8 +380,6 @@ public class DefinitionGenerator {
                             definitionNames, isConfig, stack);
 
             final String nodeName = parentName + (isConfig ? CONFIG : "") + "_" + localName;
                             definitionNames, isConfig, stack);
 
             final String nodeName = parentName + (isConfig ? CONFIG : "") + "_" + localName;
-            final String postNodeName = parentName + CONFIG + "_" + localName + POST_SUFFIX;
-            final String postXmlNodeName = postNodeName + XML_SUFFIX;
             final String parentNameConfigLocalName = parentName + CONFIG + "_" + localName;
 
             final String description = schemaNode.getDescription().orElse("");
             final String parentNameConfigLocalName = parentName + CONFIG + "_" + localName;
 
             final String description = schemaNode.getDescription().orElse("");
@@ -397,24 +389,12 @@ public class DefinitionGenerator {
                 final List<String> names = List.of(parentNameConfigLocalName,
                         parentNameConfigLocalName + TOP,
                         nameAsParent,
                 final List<String> names = List.of(parentNameConfigLocalName,
                         parentNameConfigLocalName + TOP,
                         nameAsParent,
-                        nameAsParent + TOP,
-                        postNodeName,
-                        postXmlNodeName);
+                        nameAsParent + TOP);
                 discriminator = definitionNames.pickDiscriminator(schemaNode, names);
             } else {
                 discriminator = definitionNames.getDiscriminator(schemaNode);
             }
 
                 discriminator = definitionNames.pickDiscriminator(schemaNode, names);
             } else {
                 discriminator = definitionNames.getDiscriminator(schemaNode);
             }
 
-            if (isConfig) {
-                final Schema postSchema = createPostJsonSchema(schemaNode, properties, postNodeName, description);
-                String truePostNodeName = postNodeName + discriminator;
-                definitions.put(truePostNodeName, postSchema);
-
-                final Schema postXmlSchema = new Schema();
-                postXmlSchema.setRef(COMPONENTS_PREFIX + truePostNodeName);
-                definitions.put(postXmlNodeName + discriminator, postXmlSchema);
-            }
-
             childSchema.setType(OBJECT_TYPE);
             childSchema.setProperties(properties);
             childSchema.setTitle(nodeName);
             childSchema.setType(OBJECT_TYPE);
             childSchema.setProperties(properties);
             childSchema.setTitle(nodeName);
@@ -429,42 +409,6 @@ public class DefinitionGenerator {
         return null;
     }
 
         return null;
     }
 
-    private static Schema createPostJsonSchema(final SchemaNode dataNode, final ObjectNode properties,
-            final String postNodeName, final String description) {
-        final Schema postSchema = new Schema();
-        final ObjectNode postItemProperties;
-        if (dataNode instanceof ListSchemaNode) {
-            postItemProperties = createListItemProperties(properties, (ListSchemaNode) dataNode);
-        } else {
-            postItemProperties = properties.deepCopy();
-        }
-        postSchema.setType(OBJECT_TYPE);
-        postSchema.setProperties(postItemProperties);
-        postSchema.setTitle(postNodeName);
-        postSchema.setDescription(description);
-        postSchema.setXml(buildXmlParameter(dataNode));
-        return postSchema;
-    }
-
-    private static ObjectNode createListItemProperties(final ObjectNode properties, final ListSchemaNode listNode) {
-        final ObjectNode postListItemProperties = JsonNodeFactory.instance.objectNode();
-        final List<QName> keyDefinition = listNode.getKeyDefinition();
-        final Set<String> keys = listNode.getChildNodes().stream()
-                .filter(node -> keyDefinition.contains(node.getQName()))
-                .map(node -> node.getQName().getLocalName())
-                .collect(Collectors.toSet());
-
-        Iterator<Map.Entry<String, JsonNode>> it = properties.fields();
-        while (it.hasNext()) {
-            Map.Entry<String, JsonNode> property = it.next();
-            if (!keys.contains(property.getKey())) {
-                postListItemProperties.set(property.getKey(), property.getValue());
-            }
-        }
-
-        return postListItemProperties;
-    }
-
     /**
      * Processes the nodes.
      */
     /**
      * Processes the nodes.
      */
index 8e46c951a505b5556408f9e24dca5ceac12a8507..dc2fff5e427d9edb810e23176fecfbadfb9ab5fa 100644 (file)
@@ -38,7 +38,6 @@ public final class OperationBuilder {
     public static final String NAME_KEY = "name";
     public static final String NONCONFIG_QUERY_PARAM = "nonconfig";
     public static final String PARAMETERS_KEY = "parameters";
     public static final String NAME_KEY = "name";
     public static final String NONCONFIG_QUERY_PARAM = "nonconfig";
     public static final String PARAMETERS_KEY = "parameters";
-    public static final String POST_SUFFIX = "_post";
     public static final String PROPERTIES_KEY = "properties";
     public static final String REF_KEY = "$ref";
     public static final String REQUEST_BODY_KEY = "requestBody";
     public static final String PROPERTIES_KEY = "properties";
     public static final String REF_KEY = "$ref";
     public static final String REQUEST_BODY_KEY = "requestBody";
@@ -49,7 +48,6 @@ public final class OperationBuilder {
     public static final String TAGS_KEY = "tags";
     public static final String TOP = "_TOP";
     public static final String XML_KEY = "xml";
     public static final String TAGS_KEY = "tags";
     public static final String TOP = "_TOP";
     public static final String XML_KEY = "xml";
-    public static final String XML_SUFFIX = "_xml";
     private static final String CONTENT = "content";
     private static final ArrayNode CONSUMES_PUT_POST;
     private static final String ENUM_KEY = "enum";
     private static final String CONTENT = "content";
     private static final ArrayNode CONSUMES_PUT_POST;
     private static final String ENUM_KEY = "enum";
@@ -80,9 +78,9 @@ public final class OperationBuilder {
         value.set(TAGS_KEY, buildTagsValue(deviceName, moduleName));
         final ArrayNode parameters = JsonNodeFactory.instance.arrayNode().addAll(pathParams);
         final ObjectNode ref = JsonNodeFactory.instance.objectNode();
         value.set(TAGS_KEY, buildTagsValue(deviceName, moduleName));
         final ArrayNode parameters = JsonNodeFactory.instance.arrayNode().addAll(pathParams);
         final ObjectNode ref = JsonNodeFactory.instance.objectNode();
-        final String cleanDefName = parentName + CONFIG + "_" + nodeName + POST_SUFFIX;
+        final String cleanDefName = parentName + CONFIG + "_" + nodeName;
         final String defName = cleanDefName + discriminator;
         final String defName = cleanDefName + discriminator;
-        final String xmlDefName = cleanDefName + XML_SUFFIX + discriminator;
+        final String xmlDefName = cleanDefName + discriminator;
         ref.put(REF_KEY, COMPONENTS_PREFIX + defName);
         insertRequestBodyParameter(value, defName, xmlDefName, nodeName + CONFIG);
         value.set(PARAMETERS_KEY, parameters);
         ref.put(REF_KEY, COMPONENTS_PREFIX + defName);
         insertRequestBodyParameter(value, defName, xmlDefName, nodeName + CONFIG);
         value.set(PARAMETERS_KEY, parameters);
index bec74ecea4dd7788ae16df66476343e622d15397..c51ea4dfdbd32db8a8557fd410b46fd6850cebf1 100644 (file)
@@ -270,8 +270,8 @@ public final class OpenApiGeneratorRFC8040Test {
 
         assertEquals(Set.of("/rests/data", "/rests/data/my-yang:data"), doc.getPaths().keySet());
         final var JsonNodeMyYangData = doc.getPaths().get("/rests/data/my-yang:data");
 
         assertEquals(Set.of("/rests/data", "/rests/data/my-yang:data"), doc.getPaths().keySet());
         final var JsonNodeMyYangData = doc.getPaths().get("/rests/data/my-yang:data");
-        verifyRequestRef(JsonNodeMyYangData.getPost(), "#/components/schemas/my-yang_config_data_post",
-                "#/components/schemas/my-yang_config_data_post_xml");
+        verifyRequestRef(JsonNodeMyYangData.getPost(), "#/components/schemas/my-yang_config_data",
+                "#/components/schemas/my-yang_config_data");
         verifyRequestRef(JsonNodeMyYangData.getPut(), "#/components/schemas/my-yang_config_data_TOP",
                 "#/components/schemas/my-yang_config_data");
         verifyRequestRef(JsonNodeMyYangData.getGet(), "#/components/schemas/my-yang_data_TOP",
         verifyRequestRef(JsonNodeMyYangData.getPut(), "#/components/schemas/my-yang_config_data_TOP",
                 "#/components/schemas/my-yang_config_data");
         verifyRequestRef(JsonNodeMyYangData.getGet(), "#/components/schemas/my-yang_data_TOP",
@@ -279,10 +279,8 @@ public final class OpenApiGeneratorRFC8040Test {
 
         // Test `components/schemas` objects
         final var definitions = doc.getComponents().getSchemas();
 
         // Test `components/schemas` objects
         final var definitions = doc.getComponents().getSchemas();
-        assertEquals(7, definitions.size());
+        assertEquals(5, definitions.size());
         assertTrue(definitions.containsKey("my-yang_config_data"));
         assertTrue(definitions.containsKey("my-yang_config_data"));
-        assertTrue(definitions.containsKey("my-yang_config_data_post"));
-        assertTrue(definitions.containsKey("my-yang_config_data_post_xml"));
         assertTrue(definitions.containsKey("my-yang_config_data_TOP"));
         assertTrue(definitions.containsKey("my-yang_data"));
         assertTrue(definitions.containsKey("my-yang_data_TOP"));
         assertTrue(definitions.containsKey("my-yang_config_data_TOP"));
         assertTrue(definitions.containsKey("my-yang_data"));
         assertTrue(definitions.containsKey("my-yang_data_TOP"));
@@ -295,16 +293,16 @@ public final class OpenApiGeneratorRFC8040Test {
         final var doc = generator.getOpenApiSpec(module, "http", "localhost:8181", "/", "", context);
 
         final var jsonNodeToaster = doc.getPaths().get("/rests/data/toaster2:toaster");
         final var doc = generator.getOpenApiSpec(module, "http", "localhost:8181", "/", "", context);
 
         final var jsonNodeToaster = doc.getPaths().get("/rests/data/toaster2:toaster");
-        verifyRequestRef(jsonNodeToaster.getPost(), "#/components/schemas/toaster2_config_toaster_post",
-                "#/components/schemas/toaster2_config_toaster_post_xml");
+        verifyRequestRef(jsonNodeToaster.getPost(), "#/components/schemas/toaster2_config_toaster",
+                "#/components/schemas/toaster2_config_toaster");
         verifyRequestRef(jsonNodeToaster.getPut(), "#/components/schemas/toaster2_config_toaster_TOP",
                 "#/components/schemas/toaster2_config_toaster");
         verifyRequestRef(jsonNodeToaster.getGet(), "#/components/schemas/toaster2_toaster_TOP",
                 "#/components/schemas/toaster2_toaster_TOP");
 
         final var jsonNodeToasterSlot = doc.getPaths().get("/rests/data/toaster2:toaster/toasterSlot={slotId}");
         verifyRequestRef(jsonNodeToaster.getPut(), "#/components/schemas/toaster2_config_toaster_TOP",
                 "#/components/schemas/toaster2_config_toaster");
         verifyRequestRef(jsonNodeToaster.getGet(), "#/components/schemas/toaster2_toaster_TOP",
                 "#/components/schemas/toaster2_toaster_TOP");
 
         final var jsonNodeToasterSlot = doc.getPaths().get("/rests/data/toaster2:toaster/toasterSlot={slotId}");
-        verifyRequestRef(jsonNodeToasterSlot.getPost(), "#/components/schemas/toaster2_toaster_config_toasterSlot_post",
-                "#/components/schemas/toaster2_toaster_config_toasterSlot_post_xml");
+        verifyRequestRef(jsonNodeToasterSlot.getPost(), "#/components/schemas/toaster2_toaster_config_toasterSlot",
+                "#/components/schemas/toaster2_toaster_config_toasterSlot");
         verifyRequestRef(jsonNodeToasterSlot.getPut(), "#/components/schemas/toaster2_toaster_config_toasterSlot_TOP",
                 "#/components/schemas/toaster2_toaster_config_toasterSlot");
         verifyRequestRef(jsonNodeToasterSlot.getGet(), "#/components/schemas/toaster2_toaster_toasterSlot_TOP",
         verifyRequestRef(jsonNodeToasterSlot.getPut(), "#/components/schemas/toaster2_toaster_config_toasterSlot_TOP",
                 "#/components/schemas/toaster2_toaster_config_toasterSlot");
         verifyRequestRef(jsonNodeToasterSlot.getGet(), "#/components/schemas/toaster2_toaster_toasterSlot_TOP",
@@ -313,8 +311,8 @@ public final class OpenApiGeneratorRFC8040Test {
         final var jsonNodeSlotInfo = doc.getPaths().get(
                 "/rests/data/toaster2:toaster/toasterSlot={slotId}/toaster-augmented:slotInfo");
         verifyRequestRef(jsonNodeSlotInfo.getPost(),
         final var jsonNodeSlotInfo = doc.getPaths().get(
                 "/rests/data/toaster2:toaster/toasterSlot={slotId}/toaster-augmented:slotInfo");
         verifyRequestRef(jsonNodeSlotInfo.getPost(),
-                "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo_post",
-                "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo_post_xml");
+                "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo",
+                "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo");
         verifyRequestRef(jsonNodeSlotInfo.getPut(),
                 "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo_TOP",
                 "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo");
         verifyRequestRef(jsonNodeSlotInfo.getPut(),
                 "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo_TOP",
                 "#/components/schemas/toaster2_toaster_toasterSlot_config_slotInfo");
@@ -322,16 +320,16 @@ public final class OpenApiGeneratorRFC8040Test {
                 "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo_TOP");
 
         final var jsonNodeLst = doc.getPaths().get("/rests/data/toaster2:lst");
                 "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo_TOP");
 
         final var jsonNodeLst = doc.getPaths().get("/rests/data/toaster2:lst");
-        verifyRequestRef(jsonNodeLst.getPost(), "#/components/schemas/toaster2_config_lst_post",
-                "#/components/schemas/toaster2_config_lst_post_xml");
+        verifyRequestRef(jsonNodeLst.getPost(), "#/components/schemas/toaster2_config_lst",
+                "#/components/schemas/toaster2_config_lst");
         verifyRequestRef(jsonNodeLst.getPut(), "#/components/schemas/toaster2_config_lst_TOP",
                 "#/components/schemas/toaster2_config_lst");
         verifyRequestRef(jsonNodeLst.getGet(), "#/components/schemas/toaster2_lst_TOP",
                 "#/components/schemas/toaster2_lst_TOP");
 
         final var jsonNodeLst1 = doc.getPaths().get("/rests/data/toaster2:lst/lst1={key1},{key2}");
         verifyRequestRef(jsonNodeLst.getPut(), "#/components/schemas/toaster2_config_lst_TOP",
                 "#/components/schemas/toaster2_config_lst");
         verifyRequestRef(jsonNodeLst.getGet(), "#/components/schemas/toaster2_lst_TOP",
                 "#/components/schemas/toaster2_lst_TOP");
 
         final var jsonNodeLst1 = doc.getPaths().get("/rests/data/toaster2:lst/lst1={key1},{key2}");
-        verifyRequestRef(jsonNodeLst1.getPost(), "#/components/schemas/toaster2_lst_config_lst1_post",
-                "#/components/schemas/toaster2_lst_config_lst1_post_xml");
+        verifyRequestRef(jsonNodeLst1.getPost(), "#/components/schemas/toaster2_lst_config_lst1",
+                "#/components/schemas/toaster2_lst_config_lst1");
         verifyRequestRef(jsonNodeLst1.getPut(), "#/components/schemas/toaster2_lst_config_lst1_TOP",
                 "#/components/schemas/toaster2_lst_config_lst1");
         verifyRequestRef(jsonNodeLst1.getGet(), "#/components/schemas/toaster2_lst_lst1_TOP",
         verifyRequestRef(jsonNodeLst1.getPut(), "#/components/schemas/toaster2_lst_config_lst1_TOP",
                 "#/components/schemas/toaster2_lst_config_lst1");
         verifyRequestRef(jsonNodeLst1.getGet(), "#/components/schemas/toaster2_lst_lst1_TOP",
@@ -355,7 +353,7 @@ public final class OpenApiGeneratorRFC8040Test {
 
         // Test `components/schemas` objects
         final var definitions = doc.getComponents().getSchemas();
 
         // Test `components/schemas` objects
         final var definitions = doc.getComponents().getSchemas();
-        assertEquals(60, definitions.size());
+        assertEquals(44, definitions.size());
     }
 
     /**
     }
 
     /**