Add FormattingNormalizedNodeStreamWriter 53/100053/2
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 9 Mar 2022 19:58:07 +0000 (20:58 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 9 Mar 2022 20:36:45 +0000 (21:36 +0100)
We will need some sort of quick validation for
YangInstanceIdentifierWriter and Strings seem to be convenient. Expose a
FormattingNormalizedNodeStreamWriter for other users as well.

Change-Id: I2383b4e206f593f0b6568e31fa0c6b829b7dd3f1
JIRA: YANGTOOLS-1392
Signed-off-by: Tomas Cere <tomas.cere@pantheon.tech>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/stream/AbstractIndentingNormalizedNodeStreamWriter.java [new file with mode: 0644]
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/stream/FormattingNormalizedNodeStreamWriter.java [new file with mode: 0644]
data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/stream/LoggingNormalizedNodeStreamWriter.java

diff --git a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/stream/AbstractIndentingNormalizedNodeStreamWriter.java b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/stream/AbstractIndentingNormalizedNodeStreamWriter.java
new file mode 100644 (file)
index 0000000..299da8e
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. 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.yangtools.yang.data.api.schema.stream;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import javax.xml.transform.dom.DOMSource;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+
+/**
+ * A {@link NormalizedNodeStreamWriter} which maintains some amount of indentation.
+ */
+abstract class AbstractIndentingNormalizedNodeStreamWriter implements NormalizedNodeStreamWriter {
+    private static final int DEFAULT_INDENT_SIZE = 2;
+
+    private final Deque<String> indent = new ArrayDeque<>();
+    private final String indentStr;
+
+    AbstractIndentingNormalizedNodeStreamWriter() {
+        this(DEFAULT_INDENT_SIZE);
+    }
+
+    AbstractIndentingNormalizedNodeStreamWriter(final int indentSize) {
+        indentStr = " ".repeat(indentSize);
+        indent.push("");
+    }
+
+    private String ind() {
+        return indent.peek();
+    }
+
+    private void decIndent() {
+        indent.pop();
+    }
+
+    private void incIndent() {
+        indent.push(ind() + indentStr);
+    }
+
+    @Override
+    public final void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) {
+        enterUnkeyedListItem(name, ind());
+        incIndent();
+    }
+
+    abstract void enterUnkeyedListItem(NodeIdentifier name, String indent);
+
+    @Override
+    public final void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) {
+        enterUnkeyedList(name, ind());
+        incIndent();
+    }
+
+    abstract void enterUnkeyedList(NodeIdentifier name, String indent);
+
+    @Override
+    public final void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) {
+        startMapNode(name, childSizeHint);
+    }
+
+    @Override
+    public final void startMapNode(final NodeIdentifier name, final int childSizeHint) {
+        enterMapNode(name, ind());
+        incIndent();
+    }
+
+    abstract void enterMapNode(NodeIdentifier name, String indent);
+
+    @Override
+    public final void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint) {
+        enterMapEntryNode(identifier, ind());
+        incIndent();
+    }
+
+    abstract void enterMapEntryNode(NodeIdentifierWithPredicates identifier, String indent);
+
+    @Override
+    public final void startLeafSet(final NodeIdentifier name, final int childSizeHint) {
+        enterLeafSet(name, ind());
+        incIndent();
+    }
+
+    abstract void enterLeafSet(NodeIdentifier name, String indent);
+
+    @Override
+    public final void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) {
+        startLeafSet(name, childSizeHint);
+    }
+
+    @Override
+    public final void startContainerNode(final NodeIdentifier name, final int childSizeHint) {
+        enterContainerNode(name, ind());
+        incIndent();
+    }
+
+    abstract void enterContainerNode(NodeIdentifier name, String indent);
+
+    @Override
+    public final void startChoiceNode(final NodeIdentifier name, final int childSizeHint) {
+        enterChoiceNode(name, ind());
+        incIndent();
+    }
+
+    abstract void enterChoiceNode(NodeIdentifier name, String indent);
+
+    @Override
+    public final void startAugmentationNode(final AugmentationIdentifier identifier) {
+        enterAugmentationNode(identifier, ind());
+        incIndent();
+    }
+
+    abstract void enterAugmentationNode(AugmentationIdentifier identifier, String indent);
+
+    @Override
+    public final void startLeafSetEntryNode(final NodeWithValue<?> name) {
+        enterLeafSetEntryNode(name, ind());
+        incIndent();
+    }
+
+    abstract void enterLeafSetEntryNode(NodeWithValue<?> name, String indent);
+
+    @Override
+    public final void startLeafNode(final NodeIdentifier name) {
+        enterLeafNode(name, ind());
+        incIndent();
+    }
+
+    abstract void enterLeafNode(NodeIdentifier name, String indent);
+
+    @Override
+    public final boolean startAnyxmlNode(final NodeIdentifier name, final Class<?> objectModel) {
+        enterAnyxmlNode(name, ind());
+        incIndent();
+        return true;
+    }
+
+    abstract void enterAnyxmlNode(NodeIdentifier name, String indent);
+
+    @Override
+    public final boolean startAnydataNode(final NodeIdentifier name, final Class<?> objectModel) {
+        enterAnydataNode(name, ind());
+        incIndent();
+        return true;
+    }
+
+    abstract void enterAnydataNode(NodeIdentifier name, String indent);
+
+    @Override
+    public final void endNode() {
+        decIndent();
+        exitNode(ind());
+    }
+
+    abstract void exitNode(String indent);
+
+    @Override
+    public final void scalarValue(final Object value) {
+        scalarValue(value, ind());
+    }
+
+    abstract void scalarValue(@NonNull Object value, String indent);
+
+    @Override
+    public final void domSourceValue(final DOMSource value) {
+        scalarValue(requireNonNull(value));
+    }
+}
diff --git a/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/stream/FormattingNormalizedNodeStreamWriter.java b/data/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/stream/FormattingNormalizedNodeStreamWriter.java
new file mode 100644 (file)
index 0000000..94cc7f5
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2022 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.yangtools.yang.data.api.schema.stream;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+
+/**
+ * A {@link NormalizedNodeStreamWriter} which formats events into a String, available via #result().
+ */
+@Beta
+public final class FormattingNormalizedNodeStreamWriter extends AbstractIndentingNormalizedNodeStreamWriter {
+    private final StringBuilder sb = new StringBuilder();
+
+    private boolean closed;
+
+    public FormattingNormalizedNodeStreamWriter() {
+        // Default constructor
+    }
+
+    public FormattingNormalizedNodeStreamWriter(final int indentSize) {
+        super(indentSize);
+    }
+
+    /**
+     * Return the formatted String result capturing the events which have been streamed into this writer.
+     *
+     * @return Formatted string
+     * @throws IllegalStateException if this writer was not {@link #close()}d
+     */
+    public @NonNull String result() {
+        checkState(closed, "Attempted to access the result of unclosed writer");
+        return sb.toString();
+    }
+
+    @Override
+    public void flush() {
+        // No-op
+    }
+
+    @Override
+    public void close() {
+        closed = true;
+    }
+
+    @Override
+    void enterUnkeyedListItem(final NodeIdentifier name, final String indent) {
+        sb.append(indent).append(name).append("[](no key)\n");
+    }
+
+    @Override
+    void enterUnkeyedList(final NodeIdentifier name, final String indent) {
+        sb.append(indent).append(name).append("(no key)\n");
+    }
+
+    @Override
+    void enterMapNode(final NodeIdentifier name, final String indent) {
+        sb.append(indent).append(name).append("(key)\n");
+    }
+
+    @Override
+    void enterMapEntryNode(final NodeIdentifierWithPredicates identifier, final String indent) {
+        sb.append(indent).append(identifier).append("[](key)\n");
+    }
+
+    @Override
+    void enterLeafSet(final NodeIdentifier name, final String indent) {
+        sb.append(indent).append(name).append("(leaf-list)\n");
+    }
+
+    @Override
+    void enterContainerNode(final NodeIdentifier name, final String indent) {
+        sb.append(indent).append(name).append("(container)\n");
+    }
+
+    @Override
+    void enterChoiceNode(final NodeIdentifier name, final String indent) {
+        sb.append(indent).append(name).append("(choice)\n");
+    }
+
+    @Override
+    void enterAugmentationNode(final AugmentationIdentifier identifier, final String indent) {
+        sb.append(indent).append(identifier).append("(augmentation)\n");
+    }
+
+    @Override
+    void enterLeafSetEntryNode(final NodeWithValue<?> name, final String indent) {
+        sb.append(indent).append(name.getNodeType()).append("(entry)\n");
+    }
+
+    @Override
+    void enterLeafNode(final NodeIdentifier name, final String indent) {
+        sb.append(indent).append(name).append("(leaf)\n");
+    }
+
+    @Override
+    void enterAnyxmlNode(final NodeIdentifier name, final String indent) {
+        sb.append(indent).append(name).append("(anyxml)\n");
+    }
+
+    @Override
+    void enterAnydataNode(final NodeIdentifier name, final String indent) {
+        sb.append(indent).append(name).append("(anydata)\n");
+    }
+
+    @Override
+    void exitNode(final String indent) {
+        sb.append(indent).append("(end)\n");
+    }
+
+    @Override
+    void scalarValue(final Object value, final String indent) {
+        sb.append(indent).append('(').append(value.getClass().getSimpleName()).append(")=").append(value).append('\n');
+    }
+}
index 10e19b997dd3bdc5874a5a2f6fba9a61faa3b98d..4a5a9e89b9dd4b51ff7583d805082e584aa967b3 100644 (file)
@@ -7,13 +7,8 @@
  */
 package org.opendaylight.yangtools.yang.data.api.schema.stream;
 
-import static java.util.Objects.requireNonNull;
-
 import com.google.common.annotations.Beta;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import java.util.ArrayDeque;
-import java.util.Deque;
-import javax.xml.transform.dom.DOMSource;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
@@ -25,142 +20,95 @@ import org.slf4j.LoggerFactory;
  * A {@link NormalizedNodeStreamWriter} which logs the events into a {@link Logger}.
  */
 @Beta
-public final class LoggingNormalizedNodeStreamWriter implements NormalizedNodeStreamWriter {
+public final class LoggingNormalizedNodeStreamWriter extends AbstractIndentingNormalizedNodeStreamWriter {
     private static final Logger LOG = LoggerFactory.getLogger(LoggingNormalizedNodeStreamWriter.class);
-    private static final int DEFAULT_INDENT_SIZE = 2;
-
-    private final Deque<String> indent = new ArrayDeque<>();
-    private final String indentStr;
 
     public LoggingNormalizedNodeStreamWriter() {
-        this(DEFAULT_INDENT_SIZE);
+        // Default constructor
     }
 
     public LoggingNormalizedNodeStreamWriter(final int indentSize) {
-        this.indentStr = " ".repeat(indentSize);
-        indent.push("");
-    }
-
-    private String ind() {
-        return indent.peek();
-    }
-
-    private void decIndent() {
-        indent.pop();
-    }
-
-    private void incIndent() {
-        indent.push(ind() + indentStr);
-    }
-
-    @Override
-    public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) {
-        LOG.debug("{}{}[](no key)", ind(), name);
-        incIndent();
+        super(indentSize);
     }
 
     @Override
-    public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) {
-        LOG.debug("{}{}(no key)", ind(), name);
-        incIndent();
-    }
-
-    @Override
-    public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) {
-        startMapNode(name, childSizeHint);
+    public void flush() {
+        LOG.trace("<<FLUSH>>");
     }
 
     @Override
-    public void startMapNode(final NodeIdentifier name, final int childSizeHint) {
-        LOG.debug("{}{}(key)", ind(), name);
-        incIndent();
+    public void close() {
+        LOG.debug("<<END-OF-STREAM>>");
     }
 
     @Override
-    public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint) {
-        LOG.debug("{}{}[](key)", ind(), identifier);
-        incIndent();
+    void enterUnkeyedListItem(final NodeIdentifier name, final String indent) {
+        LOG.debug("{}{}[](no key)", indent, name);
     }
 
     @Override
-    public void startLeafSet(final NodeIdentifier name, final int childSizeHint) {
-        LOG.debug("{}{}(leaf-list)", ind(), name);
-        incIndent();
+    void enterUnkeyedList(final NodeIdentifier name, final String indent) {
+        LOG.debug("{}{}(no key)", indent, name);
     }
 
     @Override
-    public void startOrderedLeafSet(final NodeIdentifier name, final int childSizeHint) {
-        startLeafSet(name, childSizeHint);
+    void enterMapNode(final NodeIdentifier name, final String indent) {
+        LOG.debug("{}{}(key)", indent, name);
     }
 
     @Override
-    public void startContainerNode(final NodeIdentifier name, final int childSizeHint) {
-        LOG.debug("{}{}(container)", ind(), name);
-        incIndent();
+    void enterMapEntryNode(final NodeIdentifierWithPredicates identifier, final String indent) {
+        LOG.debug("{}{}[](key)", indent, identifier);
     }
 
     @Override
-    public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) {
-        LOG.debug("{}{}(choice)", ind(), name);
-        incIndent();
+    void enterLeafSet(final NodeIdentifier name, final String indent) {
+        LOG.debug("{}{}(leaf-list)", indent, name);
     }
 
     @Override
-    public void startAugmentationNode(final AugmentationIdentifier identifier) {
-        LOG.debug("{}{}(augmentation)", ind(), identifier);
-        incIndent();
+    void enterContainerNode(final NodeIdentifier name, final String indent) {
+        LOG.debug("{}{}(container)", indent, name);
     }
 
     @Override
-    public void startLeafSetEntryNode(final NodeWithValue<?> name) {
-        LOG.debug("{}{}(entry}", ind(), name.getNodeType());
-        incIndent();
+    void enterChoiceNode(final NodeIdentifier name, final String indent) {
+        LOG.debug("{}{}(choice)", indent, name);
     }
 
     @Override
-    public void startLeafNode(final NodeIdentifier name) {
-        LOG.debug("{}{}(leaf)", ind(), name);
-        incIndent();
+    void enterAugmentationNode(final AugmentationIdentifier identifier, final String indent) {
+        LOG.debug("{}{}(augmentation)", indent, identifier);
     }
 
     @Override
-    public void endNode() {
-        decIndent();
-        LOG.debug("{}(end)", ind());
+    void enterLeafSetEntryNode(final NodeWithValue<?> name, final String indent) {
+        LOG.debug("{}{}(entry}", indent, name.getNodeType());
     }
 
     @Override
-    public boolean startAnyxmlNode(final NodeIdentifier name, final Class<?> objectModel) {
-        LOG.debug("{}{}(anyxml)", ind(), name);
-        incIndent();
-        return true;
+    void enterLeafNode(final NodeIdentifier name, final String indent) {
+        LOG.debug("{}{}(leaf)", indent, name);
     }
 
     @Override
-    public boolean startAnydataNode(final NodeIdentifier name, final Class<?> objectModel) {
-        LOG.debug("{}{}(anydata)", ind(), name);
-        incIndent();
-        return true;
+    void enterAnyxmlNode(final NodeIdentifier name, final String indent) {
+        LOG.debug("{}{}(anyxml)", indent, name);
     }
 
     @Override
-    public void flush() {
-        LOG.trace("<<FLUSH>>");
+    void enterAnydataNode(final NodeIdentifier name, final String indent) {
+        LOG.debug("{}{}(anydata)", indent, name);
     }
 
     @Override
-    public void close() {
-        LOG.debug("<<END-OF-STREAM>>");
+    void exitNode(final String indent) {
+        LOG.debug("{}(end)", indent);
     }
 
     @Override
     @SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
-    public void scalarValue(final Object value) {
-        LOG.debug("{}({})={}", ind(), requireNonNull(value).getClass().getSimpleName(), value);
-    }
-
-    @Override
-    public void domSourceValue(final DOMSource value) {
-        scalarValue(value);
+    void scalarValue(final Object value, final String indent) {
+        LOG.debug("{}({})={}", indent, value.getClass().getSimpleName(), value);
     }
 }