Remove OpenApiObject builder 79/106479/42
authorOleksandr Zharov <oleksandr.zharov@pantheon.tech>
Wed, 14 Jun 2023 08:45:03 +0000 (10:45 +0200)
committerIvan Hrasko <ivan.hrasko@pantheon.tech>
Tue, 8 Aug 2023 06:58:42 +0000 (06:58 +0000)
Removed builder for OpenApiObject and changed all affected methods
according to new logic.

Refactored code to avoid mutating schemas and paths.

JIRA: NETCONF-1052
Change-Id: I949dbdf79705a9e95353ce92b6c6ff8e321db4fe
Signed-off-by: Oleksandr Zharov <oleksandr.zharov@pantheon.tech>
Signed-off-by: Ivan Hrasko <ivan.hrasko@pantheon.tech>
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/BaseYangOpenApiGenerator.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/OpenApiServiceImpl.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/model/OpenApiObject.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/mountpoints/MountPointOpenApi.java

index 17068dfd20601f3b2422dd3b1b7fa45426d8c65f..6aff8f46ba636c314240b49afcc579542d7d6bb6 100644 (file)
@@ -87,53 +87,30 @@ public abstract class BaseYangOpenApiGenerator {
         this.schemaService = requireNonNull(schemaService);
     }
 
-    public OpenApiObject getAllModulesDoc(final UriInfo uriInfo, final DefinitionNames definitionNames) {
-        final EffectiveModelContext schemaContext = schemaService.getGlobalContext();
-        Preconditions.checkState(schemaContext != null);
-        return getAllModulesDoc(uriInfo, schemaContext, "Controller", "", definitionNames).build();
-    }
-
-    public OpenApiObject.Builder getAllModulesDoc(final UriInfo uriInfo, final EffectiveModelContext schemaContext,
-            final @NonNull String deviceName, final String context, final DefinitionNames definitionNames) {
-        return getFilledDoc(uriInfo, schemaContext, deviceName, context, definitionNames,
-            getSortedModules(schemaContext));
-    }
-
-    public OpenApiObject.Builder getAllModulesDoc(final UriInfo uriInfo, final Range<Integer> range,
-            final EffectiveModelContext schemaContext, final @NonNull String deviceName, final String context,
-            final DefinitionNames definitionNames) {
-        final SortedSet<Module> sortedModules = getSortedModules(schemaContext);
-        final Set<Module> filteredModules = filterByRange(sortedModules, range);
-        return getFilledDoc(uriInfo, schemaContext, deviceName, context, definitionNames, filteredModules);
-    }
-
-    private OpenApiObject.Builder getFilledDoc(final UriInfo uriInfo, final EffectiveModelContext schemaContext,
-            final String deviceName, final String context, final DefinitionNames definitionNames,
-            final Set<Module> modules) {
+    public OpenApiObject getControllerModulesDoc(final UriInfo uriInfo, final DefinitionNames definitionNames) {
+        final var context = requireNonNull(schemaService.getGlobalContext());
         final var schema = createSchemaFromUriInfo(uriInfo);
         final var host = createHostFromUriInfo(uriInfo);
-        final var title = deviceName + " modules of RESTCONF";
-        final var docBuilder = new OpenApiObject.Builder();
-        docBuilder.openapi(OPEN_API_VERSION);
-        docBuilder.info(new Info(API_VERSION, title));
-        docBuilder.servers(List.of(new Server(schema + "://" + host + BASE_PATH)));
-        docBuilder.components(new Components(new HashMap<>(), new SecuritySchemes(OPEN_API_BASIC_AUTH)));
-        docBuilder.security(SECURITY);
-        docBuilder.paths(new HashMap<>());
-        for (final var module : modules) {
-            final var revisionString = module.getQNameModule().getRevision().map(Revision::toString).orElse(null);
-
-            LOG.debug("Working on [{},{}]...", module.getName(), revisionString);
-
-            docBuilder.getComponents().schemas().putAll(getSchemas(module, schemaContext, definitionNames, false));
-            docBuilder.getPaths().putAll(getPaths(module, context, deviceName, schemaContext, definitionNames, false));
+        final var title = "Controller modules of RESTCONF";
+        final var info = new Info(API_VERSION, title);
+        final var servers = List.of(new Server(schema + "://" + host + BASE_PATH));
+
+        final var paths = new HashMap<String, Path>();
+        final var schemas = new HashMap<String, Schema>();
+        for (final var module : getSortedModules(context)) {
+            LOG.debug("Working on [{},{}]...", module.getName(), module.getQNameModule().getRevision().orElse(null));
+            schemas.putAll(getSchemas(module, context, definitionNames, false));
+            paths.putAll(getPaths(module, "", "Controller", context, definitionNames, false));
         }
 
-        // FIXME rework callers logic to make possible to return OpenApiObject from here
-        return docBuilder;
+        final var components = new Components(schemas, new SecuritySchemes(OPEN_API_BASIC_AUTH));
+        return new OpenApiObject(OPEN_API_VERSION, info, servers, paths, components, SECURITY);
     }
 
-    private static Set<Module> filterByRange(final SortedSet<Module> modules, final Range<Integer> range) {
+    public static Set<Module> filterByRange(final SortedSet<Module> modules, final Range<Integer> range) {
+        if (range.equals(Range.all())) {
+            return modules;
+        }
         final int begin = range.lowerEndpoint();
         final int end = range.upperEndpoint();
 
@@ -204,21 +181,16 @@ public abstract class BaseYangOpenApiGenerator {
 
     public OpenApiObject getOpenApiSpec(final Module module, final String schema, final String host,
             final String basePath, final String context, final EffectiveModelContext schemaContext) {
-        final var docBuilder = new OpenApiObject.Builder();
-        docBuilder.openapi(OPEN_API_VERSION);
-        docBuilder.info(new Info(API_VERSION, module.getName()));
-        docBuilder.servers(List.of(new Server(schema + "://" + host + basePath)));
-        docBuilder.components(new Components(new HashMap<>(), new SecuritySchemes(OPEN_API_BASIC_AUTH)));
-        docBuilder.security(SECURITY);
+        final var info = new Info(API_VERSION, module.getName());
+        final var servers = List.of(new Server(schema + "://" + host + basePath));
         final var definitionNames = new DefinitionNames();
         final var schemas = getSchemas(module, schemaContext, definitionNames, true);
+        final var components = new Components(schemas, new SecuritySchemes(OPEN_API_BASIC_AUTH));
         final var paths = getPaths(module, context, null, schemaContext, definitionNames, true);
-        docBuilder.getComponents().schemas().putAll(schemas);
-        docBuilder.paths(paths);
-        return docBuilder.build();
+        return new OpenApiObject(OPEN_API_VERSION, info, servers, paths, components, SECURITY);
     }
 
-    private Map<String, Path> getPaths(final Module module, final String context, final String deviceName,
+    public Map<String, Path> getPaths(final Module module, final String context, final String deviceName,
             final EffectiveModelContext schemaContext, final DefinitionNames definitionNames,
             final boolean isForSingleModule) {
         final Map<String, Path> paths = new HashMap<>();
@@ -265,7 +237,7 @@ public abstract class BaseYangOpenApiGenerator {
         return paths;
     }
 
-    private Map<String, Schema> getSchemas(final Module module, final EffectiveModelContext schemaContext,
+    public Map<String, Schema> getSchemas(final Module module, final EffectiveModelContext schemaContext,
             final DefinitionNames definitionNames, final boolean isForSingleModule) {
         Map<String, Schema> schemas = new HashMap<>();
         try {
@@ -404,7 +376,7 @@ public abstract class BaseYangOpenApiGenerator {
         return path.toString();
     }
 
-    private static SortedSet<Module> getSortedModules(final EffectiveModelContext schemaContext) {
+    public static SortedSet<Module> getSortedModules(final EffectiveModelContext schemaContext) {
         if (schemaContext == null) {
             return Collections.emptySortedSet();
         }
index d5298138484e03de015285738150d2cc4015f9b1..b758618408f18a7e35ed6fa5efaea2e0b373433b 100644 (file)
@@ -77,7 +77,7 @@ public final class OpenApiServiceImpl implements OpenApiService {
     @Override
     public synchronized Response getAllModulesDoc(final UriInfo uriInfo) {
         final DefinitionNames definitionNames = new DefinitionNames();
-        final OpenApiObject doc = openApiGeneratorRFC8040.getAllModulesDoc(uriInfo, definitionNames);
+        final OpenApiObject doc = openApiGeneratorRFC8040.getControllerModulesDoc(uriInfo, definitionNames);
         return Response.ok(doc).build();
     }
 
index 6c1b08d1cea89001d20dafce098dd3082f2feb48..1041cde0b8e772b9563d8b5f8068e92f3809dd8b 100644 (file)
@@ -14,64 +14,11 @@ import java.util.List;
 import java.util.Map;
 
 @JsonInclude(Include.NON_NULL)
-public record OpenApiObject(String openapi, Info info, List<Server> servers, Map<String, Path> paths,
-        Components components, ArrayNode security) {
-
-    private OpenApiObject(final Builder builder) {
-        this(builder.openapi, builder.info, builder.servers, builder.paths, builder.components, builder.security);
-    }
-
-    @SuppressWarnings("checkstyle:hiddenField")
-    public static class Builder {
-        private String openapi;
-        private Info info;
-        private List<Server> servers;
-        private Map<String, Path> paths;
-        private Components components;
-        private ArrayNode security;
-
-        public Builder openapi(final String openapi) {
-            this.openapi = openapi;
-            return this;
-        }
-
-        public Builder info(final Info info) {
-            this.info = info;
-            return this;
-        }
-
-        public Builder servers(final List<Server> servers) {
-            this.servers = servers;
-            return this;
-        }
-
-        public Builder paths(final Map<String, Path> paths) {
-            this.paths = paths;
-            return this;
-        }
-
-        public Builder components(final Components components) {
-            this.components = components;
-            return this;
-        }
-
-        public Builder security(final ArrayNode security) {
-            this.security = security;
-            return this;
-        }
-
-        public OpenApiObject build() {
-            return new OpenApiObject(this);
-        }
-
-        // FIXME remove this getter
-        public Components getComponents() {
-            return this.components;
-        }
-
-        // FIXME remove this getter
-        public Map<String, Path> getPaths() {
-            return this.paths;
-        }
-    }
+public record OpenApiObject(
+        String openapi,
+        Info info,
+        List<Server> servers,
+        Map<String, Path> paths,
+        Components components,
+        ArrayNode security) {
 }
index 84a9990c931b8b1eb1d5d5cfb0d81f01a7d852e7..402b62c053ce58f829be96f946f36128f8d08ac6 100644 (file)
@@ -14,6 +14,8 @@ import static org.opendaylight.restconf.openapi.impl.BaseYangOpenApiGenerator.BA
 import static org.opendaylight.restconf.openapi.impl.BaseYangOpenApiGenerator.OPEN_API_BASIC_AUTH;
 import static org.opendaylight.restconf.openapi.impl.BaseYangOpenApiGenerator.OPEN_API_VERSION;
 import static org.opendaylight.restconf.openapi.impl.BaseYangOpenApiGenerator.SECURITY;
+import static org.opendaylight.restconf.openapi.impl.BaseYangOpenApiGenerator.filterByRange;
+import static org.opendaylight.restconf.openapi.impl.BaseYangOpenApiGenerator.getSortedModules;
 import static org.opendaylight.restconf.openapi.impl.OpenApiServiceImpl.DEFAULT_PAGESIZE;
 import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.DESCRIPTION_KEY;
 import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.SUMMARY_SEPARATOR;
@@ -44,6 +46,7 @@ import org.opendaylight.restconf.openapi.model.Info;
 import org.opendaylight.restconf.openapi.model.OpenApiObject;
 import org.opendaylight.restconf.openapi.model.Operation;
 import org.opendaylight.restconf.openapi.model.Path;
+import org.opendaylight.restconf.openapi.model.Schema;
 import org.opendaylight.restconf.openapi.model.SecuritySchemes;
 import org.opendaylight.restconf.openapi.model.Server;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -159,41 +162,50 @@ public class MountPointOpenApi implements DOMMountPointListener, AutoCloseable {
     }
 
     public OpenApiObject getMountPointApi(final UriInfo uriInfo, final Long id, final @Nullable String strPageNum) {
-        final YangInstanceIdentifier iid = getInstanceId(id);
-        final EffectiveModelContext context = getSchemaContext(iid);
-        final String urlPrefix = getYangMountUrl(iid);
-        final String deviceName = extractDeviceName(iid);
+        final var iid = getInstanceId(id);
+        final var context = getSchemaContext(iid);
+        final var urlPrefix = getYangMountUrl(iid);
+        final var deviceName = extractDeviceName(iid);
 
         if (context == null) {
             return null;
         }
-        final DefinitionNames definitionNames = new DefinitionNames();
+        final var definitionNames = new DefinitionNames();
 
         boolean includeDataStore = true;
-
-        final OpenApiObject.Builder openApiObjectBuilder;
+        Range<Integer> range = Range.all();
         if (strPageNum != null) {
-            final int pageNum = Integer.parseInt(strPageNum);
-            final int end = DEFAULT_PAGESIZE * pageNum - 1;
+            final var pageNum = Integer.parseInt(strPageNum);
+            final var end = DEFAULT_PAGESIZE * pageNum - 1;
             int start = end - DEFAULT_PAGESIZE;
             if (pageNum == 1) {
                 start++;
             } else {
                 includeDataStore = false;
             }
-            openApiObjectBuilder = openApiGenerator.getAllModulesDoc(uriInfo, Range.closed(start, end), context,
-                deviceName, urlPrefix, definitionNames);
-        } else {
-            openApiObjectBuilder = openApiGenerator.getAllModulesDoc(uriInfo, context, deviceName, urlPrefix,
-                definitionNames);
+            range = Range.closed(start, end);
         }
 
+        final var schema = openApiGenerator.createSchemaFromUriInfo(uriInfo);
+        final var host = openApiGenerator.createHostFromUriInfo(uriInfo);
+        final var title = deviceName + " modules of RESTCONF";
+        final var info = new Info(API_VERSION, title);
+        final var servers = List.of(new Server(schema + "://" + host + BASE_PATH));
+
+        final var modules = getSortedModules(context);
+        final var filteredModules = filterByRange(modules, range);
+        final var paths = new HashMap<String, Path>();
+        final var schemas = new HashMap<String, Schema>();
+        for (final var module : filteredModules) {
+            LOG.debug("Working on [{},{}]...", module.getName(), module.getQNameModule().getRevision().orElse(null));
+            schemas.putAll(openApiGenerator.getSchemas(module, context, definitionNames, false));
+            paths.putAll(openApiGenerator.getPaths(module, urlPrefix, deviceName, context, definitionNames, false));
+        }
+        final var components = new Components(schemas, new SecuritySchemes(OPEN_API_BASIC_AUTH));
         if (includeDataStore) {
-            final var paths = new HashMap<>(openApiObjectBuilder.getPaths());
             paths.putAll(getDataStoreApiPaths(urlPrefix, deviceName));
-            openApiObjectBuilder.paths(paths);
         }
-        return openApiObjectBuilder.build();
+        return new OpenApiObject(OPEN_API_VERSION, info, servers, paths, components, SECURITY);
     }
 
     private static String extractDeviceName(final YangInstanceIdentifier iid) {
@@ -203,16 +215,13 @@ public class MountPointOpenApi implements DOMMountPointListener, AutoCloseable {
 
     private OpenApiObject generateDataStoreOpenApi(final UriInfo uriInfo, final String context,
             final String deviceName) {
+        final var info = new Info(API_VERSION, context);
         final var schema = openApiGenerator.createSchemaFromUriInfo(uriInfo);
         final var host = openApiGenerator.createHostFromUriInfo(uriInfo);
-        return new OpenApiObject.Builder()
-            .openapi(OPEN_API_VERSION)
-            .info(new Info(API_VERSION, context))
-            .servers(List.of(new Server(schema + "://" + host + BASE_PATH)))
-            .components(new Components(new HashMap<>(), new SecuritySchemes(OPEN_API_BASIC_AUTH)))
-            .security(SECURITY)
-            .paths(getDataStoreApiPaths(context, deviceName))
-            .build();
+        final var servers = List.of(new Server(schema + "://" + host + BASE_PATH));
+        final var components = new Components(new HashMap<>(), new SecuritySchemes(OPEN_API_BASIC_AUTH));
+        final var paths = getDataStoreApiPaths(context, deviceName);
+        return new OpenApiObject(OPEN_API_VERSION, info, servers, paths, components, SECURITY);
     }
 
     private Map<String, Path> getDataStoreApiPaths(final String context, final String deviceName) {