Refactor OperationBuilder class
[netconf.git] / restconf / restconf-openapi / src / main / java / org / opendaylight / restconf / openapi / model / builder / OperationBuilder.java
index 8e46c951a505b5556408f9e24dca5ceac12a8507..5d6a620024249ca466f8a5a189ca346da9655143 100644 (file)
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-
 package org.opendaylight.restconf.openapi.model.builder;
 
 import static org.opendaylight.restconf.openapi.impl.DefinitionGenerator.INPUT;
 import static org.opendaylight.restconf.openapi.impl.DefinitionGenerator.INPUT_SUFFIX;
 import static org.opendaylight.restconf.openapi.impl.DefinitionGenerator.OUTPUT_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 java.util.ArrayList;
 import java.util.List;
-import java.util.Optional;
 import javax.ws.rs.HttpMethod;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.restconf.openapi.impl.DefinitionNames;
+import org.opendaylight.restconf.openapi.model.Operation;
+import org.opendaylight.restconf.openapi.model.Parameter;
+import org.opendaylight.restconf.openapi.model.Schema;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.InputSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.OperationDefinition;
 import org.opendaylight.yangtools.yang.model.api.OutputSchemaNode;
 
 public final class OperationBuilder {
-    public static final String CONFIG = "_config";
-    public static final String CONFIG_QUERY_PARAM = "config";
     public static final String CONTENT_KEY = "content";
     public static final String COMPONENTS_PREFIX = "#/components/schemas/";
     public static final String DESCRIPTION_KEY = "description";
-    public static final String IN_KEY = "in";
     public static final String INPUT_KEY = "input";
     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 RESPONSES_KEY = "responses";
     public static final String SCHEMA_KEY = "schema";
-    public static final String SUMMARY_KEY = "summary";
-    public static final String SUMMARY_SEPARATOR = " - ";
-    public static final String TAGS_KEY = "tags";
-    public static final String TOP = "_TOP";
+    public static final String SUMMARY_TEMPLATE = "%s - %s - %s - %s";
     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 List<String> MIME_TYPES = List.of(MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON);
     private static final String OBJECT = "object";
-    private static final String REQUIRED_KEY = "required";
-    private static final String STRING = "string";
     private static final String TYPE_KEY = "type";
-    private static final String QUERY = "query";
-
-    static {
-        CONSUMES_PUT_POST = JsonNodeFactory.instance.arrayNode();
-        for (final String mimeType : MIME_TYPES) {
-            CONSUMES_PUT_POST.add(mimeType);
-        }
-    }
 
     private OperationBuilder() {
-
+        // Hidden on purpose
     }
 
-    public static ObjectNode buildPost(final String parentName, final String nodeName, final String discriminator,
-            final String moduleName, final Optional<String> deviceName, final String description,
-            final ArrayNode pathParams) {
-        final ObjectNode value = JsonNodeFactory.instance.objectNode();
-        value.put(DESCRIPTION_KEY, description);
-        value.put(SUMMARY_KEY, buildSummaryValue(HttpMethod.POST, moduleName, deviceName, nodeName));
-        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 defName = cleanDefName + discriminator;
-        final String xmlDefName = cleanDefName + XML_SUFFIX + discriminator;
-        ref.put(REF_KEY, COMPONENTS_PREFIX + defName);
-        insertRequestBodyParameter(value, defName, xmlDefName, nodeName + CONFIG);
-        value.set(PARAMETERS_KEY, parameters);
-
+    public static Operation buildPost(final DataSchemaNode node, final String parentName,
+        final String nodeName,
+            final String discriminator, final String moduleName, final @NonNull String deviceName,
+            final String description, final List<Parameter> pathParams) {
+        final var summary = SUMMARY_TEMPLATE.formatted(HttpMethod.POST, deviceName, moduleName, nodeName);
+        final List<String> tags = List.of(deviceName + " " + moduleName);
+        final List<Parameter> parameters = new ArrayList<>(pathParams);
+        final ObjectNode requestBody;
+        final DataSchemaNode childNode = node == null ? null : getListOrContainerChildNode(node);
+        if (childNode != null && childNode.isConfiguration()) {
+            final String childNodeName = childNode.getQName().getLocalName();
+            final String childDefName = parentName + "_" + nodeName + "_" + childNodeName + discriminator;
+            requestBody = createRequestBodyParameter(childDefName, childNodeName, childNode instanceof ListSchemaNode,
+                summary, childNodeName);
+        } else {
+            final String defName = parentName + "_" + nodeName + discriminator;
+            requestBody = createPostDataRequestBodyParameter(defName, nodeName);
+        }
         final ObjectNode responses = JsonNodeFactory.instance.objectNode();
         responses.set(String.valueOf(Response.Status.CREATED.getStatusCode()),
-                buildResponse(Response.Status.CREATED.getReasonPhrase(), Optional.empty()));
-
-        value.set(RESPONSES_KEY, responses);
-        return value;
+                buildResponse(Response.Status.CREATED.getReasonPhrase()));
+
+        return new Operation.Builder()
+            .tags(tags)
+            .parameters(parameters)
+            .requestBody(requestBody)
+            .responses(responses)
+            .description(description)
+            .summary(summary)
+            .build();
     }
 
-    public static ObjectNode buildGet(final DataSchemaNode node, final String moduleName,
-            final Optional<String> deviceName, final ArrayNode pathParams, final String defName,
-            final boolean isConfig) {
-        final ObjectNode value = JsonNodeFactory.instance.objectNode();
-        value.put(DESCRIPTION_KEY, node.getDescription().orElse(""));
-        value.put(SUMMARY_KEY, buildSummaryValue(HttpMethod.GET, moduleName, deviceName,
-                node.getQName().getLocalName()));
-        value.set(TAGS_KEY, buildTagsValue(deviceName, moduleName));
-        final ArrayNode parameters = JsonNodeFactory.instance.arrayNode().addAll(pathParams);
-
-        addQueryParameters(parameters, isConfig);
-
-        value.set(PARAMETERS_KEY, parameters);
-
+    public static Operation buildGet(final DataSchemaNode node, final String parentName, final String moduleName,
+            final @NonNull String deviceName, final List<Parameter> pathParams, final boolean isConfig) {
+        final String nodeName = node.getQName().getLocalName();
+        final String defName = parentName + "_" + nodeName;
+        final String description = node.getDescription().orElse("");
+        final String summary = SUMMARY_TEMPLATE.formatted(HttpMethod.GET, deviceName, moduleName,
+                node.getQName().getLocalName());
+        final List<String> tags = List.of(deviceName + " " + moduleName);
+        final List<Parameter> parameters = new ArrayList<>(pathParams);
+        parameters.add(buildQueryParameters(isConfig));
         final ObjectNode responses = JsonNodeFactory.instance.objectNode();
-        final ObjectNode schema = JsonNodeFactory.instance.objectNode();
-        schema.put(REF_KEY, COMPONENTS_PREFIX + defName);
-        responses.set(String.valueOf(Response.Status.OK.getStatusCode()),
-                buildResponse(Response.Status.OK.getReasonPhrase(), Optional.of(schema)));
 
-        value.set(RESPONSES_KEY, responses);
-        return value;
+        final boolean isList = node instanceof ListSchemaNode;
+        final ObjectNode response = createRequestBodyParameter(defName, nodeName, isList, summary,
+                String.valueOf(Response.Status.OK.getStatusCode()));
+        responses.set(String.valueOf(Response.Status.OK.getStatusCode()), response);
+
+        return new Operation.Builder()
+            .tags(tags)
+            .parameters(parameters)
+            .responses(responses)
+            .description(description)
+            .summary(summary)
+            .build();
     }
 
-    private static void addQueryParameters(final ArrayNode parameters, final boolean isConfig) {
-        final ObjectNode contentParam = JsonNodeFactory.instance.objectNode();
-        final ArrayNode cases = JsonNodeFactory.instance.arrayNode();
-        cases.add(NONCONFIG_QUERY_PARAM);
-        if (isConfig) {
-            cases.add(CONFIG_QUERY_PARAM);
-        } else {
-            contentParam.put(REQUIRED_KEY, true);
-        }
-        contentParam.put(IN_KEY, QUERY);
-        contentParam.put(NAME_KEY, CONTENT);
-
-        final ObjectNode typeParent = getTypeParentNode(contentParam);
-        typeParent.put(TYPE_KEY, STRING);
-        typeParent.set(ENUM_KEY, cases);
-
-        parameters.add(contentParam);
+    private static Parameter buildQueryParameters(final boolean isConfig) {
+        final ArrayNode cases = JsonNodeFactory.instance.arrayNode()
+            .add("config")
+            .add("nonconfig")
+            .add("all");
+
+        return new Parameter.Builder()
+            .in("query")
+            .name("content")
+            .required(!isConfig)
+            .schema(new Schema.Builder().type("string").schemaEnum(cases).build())
+            .build();
     }
 
-    public static ObjectNode buildPut(final String parentName, final String nodeName, final String discriminator,
-            final String moduleName, final Optional<String> deviceName, final String description,
-            final ArrayNode pathParams) {
-        final ObjectNode value = JsonNodeFactory.instance.objectNode();
-        value.put(DESCRIPTION_KEY, description);
-        value.put(SUMMARY_KEY, buildSummaryValue(HttpMethod.PUT, moduleName, deviceName, nodeName));
-        value.set(TAGS_KEY, buildTagsValue(deviceName, moduleName));
-        final ArrayNode parameters = JsonNodeFactory.instance.arrayNode().addAll(pathParams);
-        final String defName = parentName + CONFIG + "_" + nodeName + TOP;
-        final String xmlDefName = parentName + CONFIG + "_" + nodeName;
-        insertRequestBodyParameter(value, defName, xmlDefName, nodeName + CONFIG);
-        value.set(PARAMETERS_KEY, parameters);
+    public static Operation buildPut(final DataSchemaNode node, final String parentName, final String moduleName,
+            final @NonNull String deviceName, final List<Parameter> pathParams, final String fullName) {
+        final String nodeName = node.getQName().getLocalName();
+        final String summary = SUMMARY_TEMPLATE.formatted(HttpMethod.PUT, moduleName, deviceName, nodeName);
+        final List<String> tags = List.of(deviceName + " " + moduleName);
+        final List<Parameter> parameters = new ArrayList<>(pathParams);
+        final String defName = parentName + "_" + nodeName;
+        final boolean isList = node instanceof ListSchemaNode;
+        final ObjectNode requestBody = createRequestBodyParameter(defName, fullName, isList, summary, nodeName);
 
         final ObjectNode responses = JsonNodeFactory.instance.objectNode();
         responses.set(String.valueOf(Response.Status.CREATED.getStatusCode()),
-                buildResponse(Response.Status.CREATED.getReasonPhrase(), Optional.empty()));
-        responses.set(String.valueOf(Response.Status.NO_CONTENT.getStatusCode()),
-                buildResponse("Updated", Optional.empty()));
-
-        value.set(RESPONSES_KEY, responses);
-        return value;
+            buildResponse(Response.Status.CREATED.getReasonPhrase()));
+        responses.set(String.valueOf(Response.Status.NO_CONTENT.getStatusCode()), buildResponse("Updated"));
+
+        return new Operation.Builder()
+            .tags(tags)
+            .parameters(parameters)
+            .requestBody(requestBody)
+            .responses(responses)
+            .description(node.getDescription().orElse(""))
+            .summary(summary)
+            .build();
     }
 
-    public static ObjectNode buildPatch(final String parentName, final String nodeName, final String moduleName,
-            final Optional<String> deviceName, final String description, final ArrayNode pathParams) {
-        final ObjectNode value = JsonNodeFactory.instance.objectNode();
-        value.put(DESCRIPTION_KEY, description);
-        value.put(SUMMARY_KEY, buildSummaryValue(HttpMethod.PATCH, moduleName, deviceName, nodeName));
-        value.set(TAGS_KEY, buildTagsValue(deviceName, moduleName));
-        final ArrayNode parameters = JsonNodeFactory.instance.arrayNode().addAll(pathParams);
-        final String defName = parentName + CONFIG + "_" + nodeName + TOP;
-        final String xmlDefName = parentName + CONFIG + "_" + nodeName;
-        insertRequestBodyParameter(value, defName, xmlDefName, nodeName + CONFIG);
-        value.set(PARAMETERS_KEY, parameters);
+    public static Operation buildPatch(final DataSchemaNode node, final String parentName, final String moduleName,
+            final @NonNull String deviceName, final List<Parameter> pathParams, final String fullName) {
+        final String nodeName = node.getQName().getLocalName();
+        final String summary = SUMMARY_TEMPLATE.formatted(HttpMethod.PATCH, moduleName, deviceName, nodeName);
+        final List<String> tags = List.of(deviceName + " " + moduleName);
+        final List<Parameter> parameters = new ArrayList<>(pathParams);
+        final String defName = parentName + "_" + nodeName;
+        final boolean isList = node instanceof ListSchemaNode;
+        final ObjectNode requestBody = createRequestBodyParameter(defName, fullName, isList, summary, nodeName);
 
         final ObjectNode responses = JsonNodeFactory.instance.objectNode();
         responses.set(String.valueOf(Response.Status.OK.getStatusCode()),
-                buildResponse(Response.Status.OK.getReasonPhrase(), Optional.empty()));
-        responses.set(String.valueOf(Response.Status.NO_CONTENT.getStatusCode()),
-                buildResponse("Updated", Optional.empty()));
-
-        value.set(RESPONSES_KEY, responses);
-        return value;
+                buildResponse(Response.Status.OK.getReasonPhrase()));
+        responses.set(String.valueOf(Response.Status.NO_CONTENT.getStatusCode()), buildResponse("Updated"));
+
+        return new Operation.Builder()
+            .tags(tags)
+            .parameters(parameters)
+            .requestBody(requestBody)
+            .responses(responses)
+            .description(node.getDescription().orElse(""))
+            .summary(summary)
+            .build();
     }
 
-    public static ObjectNode buildDelete(final DataSchemaNode node, final String moduleName,
-            final Optional<String> deviceName, final ArrayNode pathParams) {
-        final ObjectNode value = JsonNodeFactory.instance.objectNode();
-        value.put(SUMMARY_KEY, buildSummaryValue(HttpMethod.DELETE, moduleName, deviceName,
-                node.getQName().getLocalName()));
-        value.set(TAGS_KEY, buildTagsValue(deviceName, moduleName));
-        value.put(DESCRIPTION_KEY, node.getDescription().orElse(""));
-        final ArrayNode parameters = JsonNodeFactory.instance.arrayNode().addAll(pathParams);
-        value.set(PARAMETERS_KEY, parameters);
+    public static Operation buildDelete(final DataSchemaNode node, final String moduleName,
+            final @NonNull String deviceName, final List<Parameter> pathParams) {
+        final String summary = SUMMARY_TEMPLATE.formatted(HttpMethod.DELETE, deviceName, moduleName,
+                node.getQName().getLocalName());
+        final List<String> tags = List.of(deviceName + " " + moduleName);
+        final String description = node.getDescription().orElse("");
+        final List<Parameter> parameters = new ArrayList<>(pathParams);
 
         final ObjectNode responses = JsonNodeFactory.instance.objectNode();
-        responses.set(String.valueOf(Response.Status.NO_CONTENT.getStatusCode()),
-                buildResponse("Deleted", Optional.empty()));
-
-        value.set(RESPONSES_KEY, responses);
-        return value;
+        responses.set(String.valueOf(Response.Status.NO_CONTENT.getStatusCode()), buildResponse("Deleted"));
+
+        return new Operation.Builder()
+            .tags(tags)
+            .parameters(parameters)
+            .responses(responses)
+            .description(description)
+            .summary(summary)
+            .build();
     }
 
-    public static ObjectNode buildPostOperation(final OperationDefinition operDef, final String moduleName,
-            final Optional<String> deviceName, final String parentName, final DefinitionNames definitionNames) {
-        final ObjectNode postOperation = JsonNodeFactory.instance.objectNode();
-        final ArrayNode parameters = JsonNodeFactory.instance.arrayNode();
-        final String operName = operDef.getQName().getLocalName();
-        final String inputName = operName + INPUT_SUFFIX;
+    public static Operation buildPostOperation(final OperationDefinition operDef, final String moduleName,
+            final @NonNull String deviceName, final String parentName, final DefinitionNames definitionNames,
+            final List<Parameter> parentPathParameters) {
+        final List<Parameter> parameters = new ArrayList<>(parentPathParameters);
+        final String operationName = operDef.getQName().getLocalName();
+        final String inputName = operationName + INPUT_SUFFIX;
+        final String summary = SUMMARY_TEMPLATE.formatted(HttpMethod.POST, deviceName, moduleName, operationName);
 
         final InputSchemaNode input = operDef.getInput();
         final OutputSchemaNode output = operDef.getOutput();
+        ObjectNode requestBody;
         if (!input.getChildNodes().isEmpty()) {
             final String discriminator = definitionNames.getDiscriminator(input);
-            final String clearDefName = parentName + "_" + operName + INPUT_SUFFIX;
+            final String clearDefName = parentName + "_" + operationName + INPUT_SUFFIX;
             final String defName = clearDefName + discriminator;
-            final String defTopName = clearDefName + TOP + discriminator;
-            insertRequestBodyParameter(postOperation, defTopName, defName, inputName);
+            requestBody = createRequestBodyParameter(defName, INPUT_KEY, false, summary, inputName);
         } else {
             final ObjectNode payload = JsonNodeFactory.instance.objectNode();
             final ObjectNode jsonSchema = JsonNodeFactory.instance.objectNode();
@@ -241,45 +234,72 @@ public final class OperationBuilder {
 
             payload.set(CONTENT_KEY, content);
             payload.put(DESCRIPTION_KEY, inputName);
-            postOperation.set(REQUEST_BODY_KEY, payload);
+            requestBody = payload;
         }
-        postOperation.set(PARAMETERS_KEY, parameters);
         final ObjectNode responses = JsonNodeFactory.instance.objectNode();
-        final String description = String.format("RPC %s success", operName);
+        final String description = String.format("RPC %s success", operationName);
 
         if (!output.getChildNodes().isEmpty()) {
             final ObjectNode schema = JsonNodeFactory.instance.objectNode();
-            final String defName = parentName + "_" + operName + 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,
-                    Optional.of(schema)));
+            responses.set(String.valueOf(Response.Status.OK.getStatusCode()), buildResponse(description, schema));
         } else {
-            responses.set(String.valueOf(Response.Status.NO_CONTENT.getStatusCode()), buildResponse(description,
-                    Optional.empty()));
+            responses.set(String.valueOf(Response.Status.NO_CONTENT.getStatusCode()), buildResponse(description));
         }
-        postOperation.set(RESPONSES_KEY, responses);
-        postOperation.put(DESCRIPTION_KEY, operDef.getDescription().orElse(""));
-        postOperation.put(SUMMARY_KEY, buildSummaryValue(HttpMethod.POST, moduleName, deviceName, operName));
-        postOperation.set(TAGS_KEY, buildTagsValue(deviceName, moduleName));
-        return postOperation;
+        final String desc = operDef.getDescription().orElse("");
+        final List<String> tags = List.of(deviceName + " " + moduleName);
+        return new Operation.Builder()
+            .tags(tags)
+            .parameters(parameters)
+            .requestBody(requestBody)
+            .responses(responses)
+            .description(desc)
+            .summary(summary)
+            .build();
     }
 
-    private static void insertRequestBodyParameter(final ObjectNode operation, final String defName,
-            final String xmlDefName, final String name) {
+    private static ObjectNode createPostDataRequestBodyParameter(final String defName, final String name) {
         final ObjectNode payload = JsonNodeFactory.instance.objectNode();
         final ObjectNode content = JsonNodeFactory.instance.objectNode();
-        final JsonNode node = operation.get(SUMMARY_KEY);
-        if (node != null && node.asText().contains(HttpMethod.PATCH)) {
-            content.set("application/yang-data+json", buildMimeTypeValue(defName));
-            content.set("application/yang-data+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;
+    }
+
+    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();
+        final ObjectNode properties = JsonNodeFactory.instance.objectNode();
+        if (isList) {
+            final ObjectNode list = JsonNodeFactory.instance.objectNode();
+            final ObjectNode listValue = JsonNodeFactory.instance.objectNode();
+            listValue.put(TYPE_KEY, "array");
+            listValue.set("items", buildRefSchema(defName));
+            list.set(name, listValue);
+            properties.set(PROPERTIES_KEY, list);
         } else {
-            content.set(MediaType.APPLICATION_JSON, buildMimeTypeValue(defName));
-            content.set(MediaType.APPLICATION_XML, buildMimeTypeValue(xmlDefName));
+            final ObjectNode container = JsonNodeFactory.instance.objectNode();
+            container.set(name, buildRefSchema(defName));
+            properties.set(PROPERTIES_KEY, container);
+        }
+        final ObjectNode jsonSchema = JsonNodeFactory.instance.objectNode();
+        jsonSchema.set(SCHEMA_KEY, properties);
+        if (summary != null && summary.contains(HttpMethod.PATCH)) {
+            content.set("application/yang-data+json", jsonSchema);
+            content.set("application/yang-data+xml", buildMimeTypeValue(defName));
+        } else {
+            content.set(MediaType.APPLICATION_JSON, jsonSchema);
+            content.set(MediaType.APPLICATION_XML, buildMimeTypeValue(defName));
         }
         payload.set(CONTENT_KEY, content);
-        payload.put(DESCRIPTION_KEY, name);
-        operation.set(REQUEST_BODY_KEY, payload);
+        payload.put(DESCRIPTION_KEY, description);
+        return payload;
     }
 
     private static ObjectNode buildRefSchema(final String defName) {
@@ -294,38 +314,28 @@ public final class OperationBuilder {
         return mimeTypeValue;
     }
 
-    public static ObjectNode buildResponse(final String description, final Optional<ObjectNode> schema) {
+    private static ObjectNode buildResponse(final String description) {
         final ObjectNode response = JsonNodeFactory.instance.objectNode();
-
-        if (schema.isPresent()) {
-            final ObjectNode schemaValue = schema.orElseThrow();
-            final ObjectNode content = JsonNodeFactory.instance.objectNode();
-            final ObjectNode body = JsonNodeFactory.instance.objectNode();
-            for (final String mimeType : MIME_TYPES) {
-                content.set(mimeType, body);
-            }
-            body.set(SCHEMA_KEY, schemaValue);
-            response.set(CONTENT_KEY, content);
-        }
         response.put(DESCRIPTION_KEY, description);
         return response;
     }
 
-    private static String buildSummaryValue(final String httpMethod, final String moduleName,
-            final Optional<String> deviceName, final String nodeName) {
-        return httpMethod + SUMMARY_SEPARATOR + deviceName.map(s -> s + SUMMARY_SEPARATOR).orElse("")
-                + moduleName + SUMMARY_SEPARATOR + nodeName;
-    }
-
-    public static ArrayNode buildTagsValue(final Optional<String> deviceName, final String moduleName) {
-        final ArrayNode tagsValue = JsonNodeFactory.instance.arrayNode();
-        tagsValue.add(deviceName.map(s -> "mounted " + s).orElse("controller") + " " + moduleName);
-        return tagsValue;
+    private static ObjectNode buildResponse(final String description, final ObjectNode schema) {
+        final ObjectNode response = JsonNodeFactory.instance.objectNode();
+        final ObjectNode content = JsonNodeFactory.instance.objectNode();
+        final ObjectNode body = JsonNodeFactory.instance.objectNode();
+        for (final String mimeType : MIME_TYPES) {
+            content.set(mimeType, body);
+        }
+        body.set(SCHEMA_KEY, schema);
+        response.set(CONTENT_KEY, content);
+        response.put(DESCRIPTION_KEY, description);
+        return response;
     }
 
-    public static ObjectNode getTypeParentNode(final ObjectNode parameter) {
-        final ObjectNode schema = JsonNodeFactory.instance.objectNode();
-        parameter.set(SCHEMA_KEY, schema);
-        return schema;
+    private static DataSchemaNode getListOrContainerChildNode(final DataSchemaNode node) {
+        return ((DataNodeContainer) node).getChildNodes().stream()
+            .filter(n -> n instanceof ListSchemaNode || n instanceof ContainerSchemaNode)
+            .findFirst().orElse(null);
     }
 }