Create SchemasEntity class to simplify SchemasStream 08/109908/7
authorlubos-cicut <lubos.cicut@pantheon.tech>
Mon, 22 Jan 2024 12:34:45 +0000 (13:34 +0100)
committerIvan Hrasko <ivan.hrasko@pantheon.tech>
Tue, 30 Jan 2024 13:15:15 +0000 (13:15 +0000)
Created SchemasEntity class to simplify SchemasStream. SchemasEntity
now hold collection of SchemaEntity as in PathsEntity. Class
SchemaStream is no more necessary.

JIRA: NETCONF-938
Change-Id: I02ac62704dabe94d5c793af383bb6a0c7bbd4a0a
Signed-off-by: lubos-cicut <lubos.cicut@pantheon.tech>
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/ComponentsStream.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/SchemaStream.java [deleted file]
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/SchemasStream.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/model/OpenApiEntity.java
restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/model/SchemasEntity.java [new file with mode: 0644]

index 5b97b7b52faa3519cac5c45d048bba1bb2295582..a9e236e2693799170d0e39727f1873af05bca751 100644 (file)
@@ -42,8 +42,8 @@ public final class ComponentsStream extends InputStream {
     private ReadableByteChannel channel;
 
     public ComponentsStream(final EffectiveModelContext context, final OpenApiBodyWriter writer,
-        final JsonGenerator generator, final ByteArrayOutputStream stream,
-        final Iterator<? extends Module> iterator, final boolean isForSingleModule) {
+            final JsonGenerator generator, final ByteArrayOutputStream stream,
+            final Iterator<? extends Module> iterator, final boolean isForSingleModule) {
         this.iterator = iterator;
         this.context = context;
         this.writer = writer;
@@ -64,8 +64,8 @@ public final class ComponentsStream extends InputStream {
         var read = reader.read();
         while (read == -1) {
             if (!schemasWritten) {
-                reader = new InputStreamReader(new SchemasStream(context, writer, generator, stream, iterator,
-                    isForSingleModule), StandardCharsets.UTF_8);
+                reader = new InputStreamReader(new SchemasStream(context, writer, iterator, isForSingleModule),
+                    StandardCharsets.UTF_8);
                 read = reader.read();
                 schemasWritten = true;
                 continue;
@@ -98,9 +98,8 @@ public final class ComponentsStream extends InputStream {
         var read = channel.read(ByteBuffer.wrap(array, off, len));
         while (read == -1) {
             if (!schemasWritten) {
-                channel = Channels.newChannel(new SchemasStream(context, writer, generator, stream, iterator,
-                    isForSingleModule));
-                read = channel.read(ByteBuffer.wrap(array));
+                channel = Channels.newChannel(new SchemasStream(context, writer, iterator, isForSingleModule));
+                read = channel.read(ByteBuffer.wrap(array, off, len));
                 schemasWritten = true;
                 continue;
             }
diff --git a/restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/SchemaStream.java b/restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/impl/SchemaStream.java
deleted file mode 100644 (file)
index dc75c69..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2023 PANTHEON.tech, s.r.o. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * 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.impl;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.ByteBuffer;
-import java.nio.channels.Channels;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.charset.StandardCharsets;
-import java.util.Deque;
-import org.opendaylight.restconf.openapi.jaxrs.OpenApiBodyWriter;
-import org.opendaylight.restconf.openapi.model.OpenApiEntity;
-import org.opendaylight.restconf.openapi.model.SchemaEntity;
-
-public final class SchemaStream extends InputStream {
-    private final Deque<SchemaEntity> stack;
-    private final OpenApiBodyWriter writer;
-
-    private Reader reader;
-    private ReadableByteChannel channel;
-
-    public SchemaStream(final Deque<SchemaEntity> schemas, final OpenApiBodyWriter writer) {
-        this.stack = schemas;
-        this.writer = writer;
-    }
-
-    @Override
-    public int read() throws IOException {
-        if (reader == null) {
-            if (stack.isEmpty()) {
-                return -1;
-            }
-            reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(writeNextEntity(stack.pop())),
-                StandardCharsets.UTF_8));
-        }
-
-        var read = reader.read();
-        while (read == -1) {
-            if (stack.isEmpty()) {
-                return -1;
-            }
-            reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(writeNextEntity(stack.pop())),
-                StandardCharsets.UTF_8));
-            read = reader.read();
-        }
-
-        return read;
-    }
-
-    @Override
-    public int read(final byte[] array, final int off, final int len) throws IOException {
-        if (channel == null) {
-            if (stack.isEmpty()) {
-                return -1;
-            }
-            channel = Channels.newChannel(new ByteArrayInputStream(writeNextEntity(stack.pop())));
-        }
-
-        var read = channel.read(ByteBuffer.wrap(array, off, len));
-        while (read == -1) {
-            if (stack.isEmpty()) {
-                return -1;
-            }
-            channel = Channels.newChannel(new ByteArrayInputStream(writeNextEntity(stack.pop())));
-            read = channel.read(ByteBuffer.wrap(array, off, len));
-        }
-
-        return read;
-    }
-
-    private byte[] writeNextEntity(final OpenApiEntity entity) throws IOException {
-        writer.writeTo(entity, null, null, null, null, null, null);
-        return writer.readFrom();
-    }
-}
index fa4e8280d461eb0bf2c899010c3fe77ea01b326c..ff5d0d69bd6637cce43fa85809b40381c2867bfd 100644 (file)
@@ -7,10 +7,8 @@
  */
 package org.opendaylight.restconf.openapi.impl;
 
-import com.fasterxml.jackson.core.JsonGenerator;
 import java.io.BufferedReader;
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -25,7 +23,9 @@ import java.util.Deque;
 import java.util.Iterator;
 import java.util.List;
 import org.opendaylight.restconf.openapi.jaxrs.OpenApiBodyWriter;
+import org.opendaylight.restconf.openapi.model.OpenApiEntity;
 import org.opendaylight.restconf.openapi.model.SchemaEntity;
+import org.opendaylight.restconf.openapi.model.SchemasEntity;
 import org.opendaylight.yangtools.yang.model.api.ActionNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
@@ -44,137 +44,96 @@ public final class SchemasStream extends InputStream {
     private final Iterator<? extends Module> iterator;
     private final OpenApiBodyWriter writer;
     private final EffectiveModelContext context;
-    private final JsonGenerator generator;
-    private final ByteArrayOutputStream stream;
     private final boolean isForSingleModule;
 
     private Reader reader;
     private ReadableByteChannel channel;
-    private boolean schemesWritten;
 
     public SchemasStream(final EffectiveModelContext context, final OpenApiBodyWriter writer,
-            final JsonGenerator generator, final ByteArrayOutputStream stream,
             final Iterator<? extends Module> iterator, final boolean isForSingleModule) {
         this.iterator = iterator;
         this.context = context;
         this.writer = writer;
-        this.generator = generator;
-        this.stream = stream;
         this.isForSingleModule = isForSingleModule;
     }
 
     @Override
     public int read() throws IOException {
         if (reader == null) {
-            generator.writeObjectFieldStart("schemas");
-            generator.flush();
             reader = new BufferedReader(
-                new InputStreamReader(new ByteArrayInputStream(stream.toByteArray()), StandardCharsets.UTF_8));
-            stream.reset();
+                new InputStreamReader(new ByteArrayInputStream(writeNextEntity(
+                    new SchemasEntity(toComponents(iterator, context, isForSingleModule)))),
+                    StandardCharsets.UTF_8));
         }
-
-        var read = reader.read();
-        while (read == -1) {
-            if (iterator.hasNext()) {
-                reader = new BufferedReader(
-                    new InputStreamReader(new SchemaStream(toComponents(iterator.next(), context, isForSingleModule),
-                        writer), StandardCharsets.UTF_8));
-                read = reader.read();
-                continue;
-            }
-            if (!schemesWritten) {
-                generator.writeEndObject();
-                schemesWritten = true;
-                continue;
-            }
-            generator.flush();
-            reader = new BufferedReader(
-                new InputStreamReader(new ByteArrayInputStream(stream.toByteArray()), StandardCharsets.UTF_8));
-            stream.reset();
-            return reader.read();
-        }
-
-        return read;
+        return reader.read();
     }
 
     @Override
     public int read(final byte[] array, final int off, final int len) throws IOException {
         if (channel == null) {
-            generator.writeObjectFieldStart("schemas");
-            generator.flush();
-            channel = Channels.newChannel(new ByteArrayInputStream(stream.toByteArray()));
-            stream.reset();
-        }
-
-        var read = channel.read(ByteBuffer.wrap(array, off, len));
-        while (read == -1) {
-            if (iterator.hasNext()) {
-                channel = Channels.newChannel(new SchemaStream(toComponents(iterator.next(), context,
-                    isForSingleModule), writer));
-                read = channel.read(ByteBuffer.wrap(array, off, len));
-                continue;
-            }
-            if (!schemesWritten) {
-                generator.writeEndObject();
-                schemesWritten = true;
-                continue;
-            }
-            generator.flush();
-            channel = Channels.newChannel(new ByteArrayInputStream(stream.toByteArray()));
-            stream.reset();
-            return channel.read(ByteBuffer.wrap(array, off, len));
+            channel = Channels.newChannel(new ByteArrayInputStream(writeNextEntity(
+                new SchemasEntity(toComponents(iterator, context, isForSingleModule)))));
         }
+        return channel.read(ByteBuffer.wrap(array, off, len));
+    }
 
-        return read;
+    private byte[] writeNextEntity(final OpenApiEntity next) throws IOException {
+        writer.writeTo(next, null, null, null, null, null, null);
+        return writer.readFrom();
     }
 
-    private static Deque<SchemaEntity> toComponents(final Module module, final EffectiveModelContext context,
-            final boolean isForSingleModule) {
+    private static Deque<SchemaEntity> toComponents(final Iterator<? extends Module> iterator,
+            final EffectiveModelContext context, final boolean isForSingleModule) {
         final var result = new ArrayDeque<SchemaEntity>();
-        final var definitionNames = new DefinitionNames();
-        final var stack = SchemaInferenceStack.of(context);
-        final var moduleName = module.getName();
-        if (isForSingleModule) {
-            definitionNames.addUnlinkedName(moduleName + "_module");
-        }
-        final var children = new ArrayList<DataSchemaNode>();
-        for (final var rpc : module.getRpcs()) {
-            stack.enterSchemaTree(rpc.getQName());
-            final var rpcName = rpc.getQName().getLocalName();
-            final var rpcInput = rpc.getInput();
-            if (!rpcInput.getChildNodes().isEmpty()) {
-                final var input = new SchemaEntity(rpcInput, moduleName + "_" + rpcName + INPUT_SUFFIX, null,
-                    OBJECT_TYPE, stack, moduleName, false, definitionNames, EntityType.RPC);
-                result.add(input);
-                stack.enterSchemaTree(rpcInput.getQName());
-                for (final var child : rpcInput.getChildNodes()) {
-                    if (!children.contains(child)) {
-                        children.add(child);
-                        processDataAndActionNodes(child, moduleName, stack, definitionNames, result, moduleName, false);
+        while (iterator.hasNext()) {
+            final var module = iterator.next();
+            final var definitionNames = new DefinitionNames();
+            final var stack = SchemaInferenceStack.of(context);
+            final var moduleName = module.getName();
+            if (isForSingleModule) {
+                definitionNames.addUnlinkedName(moduleName + "_module");
+            }
+            final var children = new ArrayList<DataSchemaNode>();
+            for (final var rpc : module.getRpcs()) {
+                stack.enterSchemaTree(rpc.getQName());
+                final var rpcName = rpc.getQName().getLocalName();
+                final var rpcInput = rpc.getInput();
+                if (!rpcInput.getChildNodes().isEmpty()) {
+                    final var input = new SchemaEntity(rpcInput, moduleName + "_" + rpcName + INPUT_SUFFIX, null,
+                        OBJECT_TYPE, stack, moduleName, false, definitionNames, EntityType.RPC);
+                    result.add(input);
+                    stack.enterSchemaTree(rpcInput.getQName());
+                    for (final var child : rpcInput.getChildNodes()) {
+                        if (!children.contains(child)) {
+                            children.add(child);
+                            processDataAndActionNodes(child, moduleName, stack, definitionNames, result, moduleName,
+                                false);
+                        }
                     }
+                    stack.exit();
                 }
-                stack.exit();
-            }
-            final var rpcOutput = rpc.getOutput();
-            if (!rpcOutput.getChildNodes().isEmpty()) {
-                final var output = new SchemaEntity(rpcOutput, moduleName + "_" + rpcName + OUTPUT_SUFFIX, null,
-                    OBJECT_TYPE, stack, moduleName, false, definitionNames, EntityType.RPC);
-                result.add(output);
-                stack.enterSchemaTree(rpcOutput.getQName());
-                for (final var child : rpcOutput.getChildNodes()) {
-                    if (!children.contains(child)) {
-                        children.add(child);
-                        processDataAndActionNodes(child, moduleName, stack, definitionNames, result, moduleName, false);
+                final var rpcOutput = rpc.getOutput();
+                if (!rpcOutput.getChildNodes().isEmpty()) {
+                    final var output = new SchemaEntity(rpcOutput, moduleName + "_" + rpcName + OUTPUT_SUFFIX, null,
+                        OBJECT_TYPE, stack, moduleName, false, definitionNames, EntityType.RPC);
+                    result.add(output);
+                    stack.enterSchemaTree(rpcOutput.getQName());
+                    for (final var child : rpcOutput.getChildNodes()) {
+                        if (!children.contains(child)) {
+                            children.add(child);
+                            processDataAndActionNodes(child, moduleName, stack, definitionNames, result, moduleName,
+                                false);
+                        }
                     }
+                    stack.exit();
                 }
                 stack.exit();
             }
-            stack.exit();
-        }
 
-        for (final var childNode : module.getChildNodes()) {
-            processDataAndActionNodes(childNode, moduleName, stack, definitionNames, result, moduleName,
-                true);
+            for (final var childNode : module.getChildNodes()) {
+                processDataAndActionNodes(childNode, moduleName, stack, definitionNames, result, moduleName,
+                    true);
+            }
         }
         return result;
     }
index a669837fe6f725b66f62ea81c366bda2e42a9f66..fa99d2094f523fba096ed9f37a68ad2259ef5275 100644 (file)
@@ -14,8 +14,9 @@ import org.eclipse.jdt.annotation.NonNull;
 /**
  * A response entity for complex generated type.
  */
-public abstract sealed class OpenApiEntity permits SchemaEntity, ComponentsEntity, InfoEntity, OpenApiVersionEntity,
-        OperationEntity, PathEntity, PathsEntity, SecuritySchemesEntity, ServerEntity, ServersEntity, SecurityEntity {
+public abstract sealed class OpenApiEntity permits ComponentsEntity, InfoEntity, OpenApiVersionEntity, OperationEntity,
+        PathEntity, PathsEntity, SchemaEntity, SchemasEntity, SecurityEntity, SecuritySchemesEntity, ServerEntity,
+        ServersEntity {
     /**
      * Generate JSON events into specified generator.
      *
diff --git a/restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/model/SchemasEntity.java b/restconf/restconf-openapi/src/main/java/org/opendaylight/restconf/openapi/model/SchemasEntity.java
new file mode 100644 (file)
index 0000000..25db223
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * 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;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import java.io.IOException;
+import java.util.Deque;
+
+public final class SchemasEntity extends OpenApiEntity {
+    private final Deque<SchemaEntity> schemas;
+
+    public SchemasEntity(final Deque<SchemaEntity> schemas) {
+        this.schemas = schemas;
+    }
+
+    @Override
+    public void generate(final JsonGenerator generator) throws IOException {
+        generator.writeObjectFieldStart("schemas");
+        for (final var schema : schemas) {
+            schema.generate(generator);
+        }
+        generator.writeEndObject();
+    }
+}