Use OpenApiServiceImpl#DEFAULT_PAGESIZE after rewrite
[netconf.git] / restconf / restconf-openapi / src / main / java / org / opendaylight / restconf / openapi / mountpoints / MountPointOpenApi.java
index 30502244f2557841042071db7c739a27d2d9e1a9..d1c2375678c41693596a76c21063f1e970f6226e 100644 (file)
@@ -10,11 +10,14 @@ package org.opendaylight.restconf.openapi.mountpoints;
 import static com.google.common.base.Preconditions.checkState;
 import static java.util.Objects.requireNonNull;
 import static org.opendaylight.restconf.openapi.impl.BaseYangOpenApiGenerator.SECURITY;
+import static org.opendaylight.restconf.openapi.impl.OpenApiServiceImpl.DEFAULT_PAGESIZE;
 
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentSkipListMap;
 import java.util.concurrent.atomic.AtomicLong;
@@ -27,9 +30,13 @@ import org.opendaylight.restconf.openapi.impl.BaseYangOpenApiGenerator;
 import org.opendaylight.restconf.openapi.impl.OpenApiInputStream;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.Revision;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.slf4j.Logger;
@@ -156,11 +163,17 @@ public class MountPointOpenApi implements DOMMountPointListener, AutoCloseable {
         }
 
         boolean includeDataStore = true;
+        var modules = context.getModules();
         if (strPageNum != null) {
             final var pageNum = Integer.parseInt(strPageNum);
-            if (pageNum != 1) {
+            final var end = DEFAULT_PAGESIZE * pageNum - 1;
+            int start = end - DEFAULT_PAGESIZE;
+            if (pageNum == 1) {
+                start++;
+            } else {
                 includeDataStore = false;
             }
+            modules = filterByRange(context, start);
         }
 
         final var schema = openApiGenerator.createSchemaFromUriInfo(uriInfo);
@@ -168,7 +181,6 @@ public class MountPointOpenApi implements DOMMountPointListener, AutoCloseable {
         final var title = deviceName + " modules of RESTCONF";
         final var url = schema + "://" + host + "/";
         final var basePath = openApiGenerator.getBasePath();
-        final var modules = context.getModules();
         return new OpenApiInputStream(context, title, url, SECURITY, deviceName, urlPrefix, false, includeDataStore,
             modules, basePath);
     }
@@ -203,4 +215,46 @@ public class MountPointOpenApi implements DOMMountPointListener, AutoCloseable {
         final Long id = instanceIdToLongId.remove(path);
         longIdToInstanceId.remove(id);
     }
+
+    private static Set<Module> filterByRange(final EffectiveModelContext schemaContext, final Integer start) {
+        final var sortedModules = new TreeSet<Module>((module1, module2) -> {
+            int result = module1.getName().compareTo(module2.getName());
+            if (result == 0) {
+                result = Revision.compare(module1.getRevision(), module2.getRevision());
+            }
+            if (result == 0) {
+                result = module1.getNamespace().compareTo(module2.getNamespace());
+            }
+            return result;
+        });
+        sortedModules.addAll(schemaContext.getModules());
+
+        final int end = start + DEFAULT_PAGESIZE - 1;
+
+        var firstModule = sortedModules.first();
+
+        final var iterator = sortedModules.iterator();
+        int counter = 0;
+        while (iterator.hasNext() && counter < end) {
+            final var module = iterator.next();
+            if (containsListOrContainer(module.getChildNodes()) || !module.getRpcs().isEmpty()) {
+                if (counter == start) {
+                    firstModule = module;
+                }
+                counter++;
+            }
+        }
+
+        return iterator.hasNext()
+            ? sortedModules.subSet(firstModule, iterator.next()) : sortedModules.tailSet(firstModule);
+    }
+
+    private static boolean containsListOrContainer(final Iterable<? extends DataSchemaNode> nodes) {
+        for (final var child : nodes) {
+            if (child instanceof ListSchemaNode || child instanceof ContainerSchemaNode) {
+                return true;
+            }
+        }
+        return false;
+    }
 }