Close JSON root context when the writer is closed
[yangtools.git] / yang / yang-data-codec-gson / src / main / java / org / opendaylight / yangtools / yang / data / codec / gson / JSONStreamWriterContext.java
index 5a3be65a1f79c30778da83410d827fcb91c42dc0..fa2a7b9e8bd82bc82a77220216bc222eb2be646b 100644 (file)
@@ -8,13 +8,17 @@
 package org.opendaylight.yangtools.yang.data.codec.gson;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
 
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
 import com.google.gson.stream.JsonWriter;
 import java.io.IOException;
 import java.net.URI;
-import java.util.Iterator;
-import javax.annotation.Nonnull;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -26,7 +30,9 @@ abstract class JSONStreamWriterContext {
     private final JSONStreamWriterContext parent;
     private final boolean mandatory;
     private final int depth;
-    private boolean emittedMyself = false;
+
+    private boolean emittedMyself;
+    private boolean inChild;
 
     /**
      * Construct a new context.
@@ -59,13 +65,11 @@ abstract class JSONStreamWriterContext {
 
         final StringBuilder sb = new StringBuilder();
         // Prepend module name if namespaces do not match
-        final URI ns = qname.getNamespace();
-        if (!ns.equals(getNamespace())) {
-            final Iterator<Module> modules = schema.findModules(ns).iterator();
-            checkArgument(modules.hasNext(), "Could not find module for namespace {}", ns);
-
-            sb.append(modules.next().getName());
-            sb.append(':');
+        final QNameModule module = qname.getModule();
+        if (!module.getNamespace().equals(getNamespace())) {
+            final Optional<String> modules = schema.findModule(module).map(Module::getName);
+            checkArgument(modules.isPresent(), "Could not find module for namespace {}", module);
+            sb.append(modules.get()).append(':');
         }
         sb.append(qname.getLocalName());
 
@@ -90,7 +94,7 @@ abstract class JSONStreamWriterContext {
      *
      * @return Namespace as URI
      */
-    protected abstract @Nonnull URI getNamespace();
+    protected abstract @NonNull URI getNamespace();
 
     /**
      * Emit the start of an element.
@@ -113,7 +117,7 @@ abstract class JSONStreamWriterContext {
     private void emitMyself(final SchemaContext schema, final JsonWriter writer) throws IOException {
         if (!emittedMyself) {
             if (parent != null) {
-                parent.emittingChild(schema, writer);
+                parent.emitMyself(schema, writer);
             }
 
             emitStart(schema, writer);
@@ -131,7 +135,9 @@ abstract class JSONStreamWriterContext {
      * @throws IOException when writer reports it
      */
     final void emittingChild(final SchemaContext schema, final JsonWriter writer) throws IOException {
+        checkState(!inChild, "Duplicate child encountered");
         emitMyself(schema, writer);
+        inChild = true;
     }
 
     /**
@@ -145,13 +151,25 @@ abstract class JSONStreamWriterContext {
      * @throws IllegalArgumentException if this node cannot be ended (e.g. root)
      */
     final JSONStreamWriterContext endNode(final SchemaContext schema, final JsonWriter writer) throws IOException {
+        if (inChild) {
+            inChild = false;
+            return this;
+        }
         if (!emittedMyself && mandatory) {
             emitMyself(schema, writer);
         }
-
         if (emittedMyself) {
             emitEnd(writer);
         }
         return parent;
     }
+
+    @Override
+    public final String toString() {
+        return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
+    }
+
+    protected ToStringHelper addToStringAttributes(final ToStringHelper helper) {
+        return helper;
+    }
 }