Revert "Remove SchemaNode#getPath usage from JsonToPatchBodyReader"
[netconf.git] / restconf / restconf-nb-bierman02 / src / main / java / org / opendaylight / netconf / sal / rest / impl / JsonToPatchBodyReader.java
index 53cc16f8d35053e7d06f95147c9c2741233291e4..f17666c59e72c72f3ad3d7c0533f336af6e72c2b 100644 (file)
@@ -5,9 +5,11 @@
  * 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.netconf.sal.rest.impl;
 
+import static com.google.common.base.Verify.verify;
+
+import com.google.common.base.Throwables;
 import com.google.common.collect.ImmutableList;
 import com.google.gson.stream.JsonReader;
 import com.google.gson.stream.JsonToken;
@@ -23,24 +25,24 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicReference;
-import javax.annotation.Nonnull;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.WebApplicationException;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.ext.MessageBodyReader;
 import javax.ws.rs.ext.Provider;
+import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.netconf.sal.rest.api.Draft02;
 import org.opendaylight.netconf.sal.rest.api.RestconfService;
 import org.opendaylight.netconf.sal.restconf.impl.ControllerContext;
 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
-import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
-import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
 import org.opendaylight.restconf.common.patch.PatchContext;
 import org.opendaylight.restconf.common.patch.PatchEditOperation;
 import org.opendaylight.restconf.common.patch.PatchEntity;
 import org.opendaylight.restconf.common.util.RestUtil;
+import org.opendaylight.yangtools.yang.common.ErrorTag;
+import org.opendaylight.yangtools.yang.common.ErrorType;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -50,8 +52,10 @@ import org.opendaylight.yangtools.yang.data.codec.gson.JsonParserStream;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
 import org.opendaylight.yangtools.yang.data.impl.schema.ResultAlreadySetException;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -68,7 +72,7 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
 
     private static final Logger LOG = LoggerFactory.getLogger(JsonToPatchBodyReader.class);
 
-    public JsonToPatchBodyReader(ControllerContext controllerContext) {
+    public JsonToPatchBodyReader(final ControllerContext controllerContext) {
         super(controllerContext);
     }
 
@@ -83,7 +87,7 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
     public PatchContext readFrom(final Class<PatchContext> type, final Type genericType,
                                  final Annotation[] annotations, final MediaType mediaType,
                                  final MultivaluedMap<String, String> httpHeaders, final InputStream entityStream)
-            throws IOException, WebApplicationException {
+            throws WebApplicationException {
         try {
             return readFrom(getInstanceIdentifierContext(), entityStream);
         } catch (final Exception e) {
@@ -105,7 +109,7 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
     private PatchContext readFrom(final InstanceIdentifierContext<?> path, final InputStream entityStream)
             throws IOException {
         final Optional<InputStream> nonEmptyInputStreamOptional = RestUtil.isInputStreamEmpty(entityStream);
-        if (!nonEmptyInputStreamOptional.isPresent()) {
+        if (nonEmptyInputStreamOptional.isEmpty()) {
             return new PatchContext(path, null, null);
         }
 
@@ -119,15 +123,14 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
     }
 
     private static RuntimeException propagateExceptionAs(final Exception exception) throws RestconfDocumentedException {
-        if (exception instanceof RestconfDocumentedException) {
-            throw (RestconfDocumentedException)exception;
-        }
+        Throwables.throwIfInstanceOf(exception, RestconfDocumentedException.class);
+        LOG.debug("Error parsing json input", exception);
 
         if (exception instanceof ResultAlreadySetException) {
-            LOG.debug("Error parsing json input:", exception);
             throw new RestconfDocumentedException("Error parsing json input: Failed to create new parse result data. ");
         }
 
+        RestconfDocumentedException.throwIfYangError(exception);
         throw new RestconfDocumentedException("Error parsing json input: " + exception.getMessage(), ErrorType.PROTOCOL,
                 ErrorTag.MALFORMED_MESSAGE, exception);
     }
@@ -188,11 +191,11 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
      * @param resultCollection collection of parsed edits
      * @throws IOException if operation fails
      */
-    private void parseByName(@Nonnull final String name, @Nonnull final PatchEdit edit,
-                             @Nonnull final JsonReader in, @Nonnull final InstanceIdentifierContext<?> path,
-                             @Nonnull final StringModuleInstanceIdentifierCodec codec,
-                             @Nonnull final List<PatchEntity> resultCollection,
-                             @Nonnull final AtomicReference<String> patchId) throws IOException {
+    private void parseByName(final @NonNull String name, final @NonNull PatchEdit edit,
+                             final @NonNull JsonReader in, final @NonNull InstanceIdentifierContext<?> path,
+                             final @NonNull StringModuleInstanceIdentifierCodec codec,
+                             final @NonNull List<PatchEntity> resultCollection,
+                             final @NonNull AtomicReference<String> patchId) throws IOException {
         switch (name) {
             case "edit" :
                 if (in.peek() == JsonToken.BEGIN_ARRAY) {
@@ -228,10 +231,10 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
      * @param codec StringModuleInstanceIdentifierCodec codec
      * @throws IOException if operation fails
      */
-    private void readEditDefinition(@Nonnull final PatchEdit edit, @Nonnull final JsonReader in,
-                                    @Nonnull final InstanceIdentifierContext<?> path,
-                                    @Nonnull final StringModuleInstanceIdentifierCodec codec) throws IOException {
-        final StringBuffer value = new StringBuffer();
+    private void readEditDefinition(final @NonNull PatchEdit edit, final @NonNull JsonReader in,
+                                    final @NonNull InstanceIdentifierContext<?> path,
+                                    final @NonNull StringModuleInstanceIdentifierCodec codec) throws IOException {
+        final StringBuilder value = new StringBuilder();
         in.beginObject();
 
         while (in.hasNext()) {
@@ -251,9 +254,14 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
                         edit.setTargetSchemaNode(path.getSchemaContext());
                     } else {
                         edit.setTarget(codec.deserialize(codec.serialize(path.getInstanceIdentifier()).concat(target)));
-                        edit.setTargetSchemaNode(SchemaContextUtil.findDataSchemaNode(path.getSchemaContext(),
-                                codec.getDataContextTree().getChild(edit.getTarget()).getDataSchemaNode().getPath()
-                                        .getParent()));
+
+                        final EffectiveStatement<?, ?> parentStmt = SchemaInferenceStack.ofInstantiatedPath(
+                            path.getSchemaContext(),
+                            codec.getDataContextTree().findChild(edit.getTarget()).orElseThrow().getDataSchemaNode()
+                                .getPath().getParent())
+                            .currentStatement();
+                        verify(parentStmt instanceof SchemaNode, "Unexpected parent %s", parentStmt);
+                        edit.setTargetSchemaNode((SchemaNode) parentStmt);
                     }
 
                     break;
@@ -280,35 +288,35 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
      * @param in JsonReader reader
      * @throws IOException if operation fails
      */
-    private void readValueNode(@Nonnull final StringBuffer value, @Nonnull final JsonReader in) throws IOException {
+    private void readValueNode(final @NonNull StringBuilder value, final @NonNull JsonReader in) throws IOException {
         in.beginObject();
-        value.append("{");
+        value.append('{');
 
-        value.append("\"" + in.nextName() + "\"" + ":");
+        value.append('"').append(in.nextName()).append("\":");
 
         if (in.peek() == JsonToken.BEGIN_ARRAY) {
             in.beginArray();
-            value.append("[");
+            value.append('[');
 
             while (in.hasNext()) {
                 if (in.peek() == JsonToken.STRING) {
-                    value.append("\"" + in.nextString() + "\"");
+                    value.append('"').append(in.nextString()).append('"');
                 } else {
                     readValueObject(value, in);
                 }
                 if (in.peek() != JsonToken.END_ARRAY) {
-                    value.append(",");
+                    value.append(',');
                 }
             }
 
             in.endArray();
-            value.append("]");
+            value.append(']');
         } else {
             readValueObject(value, in);
         }
 
         in.endObject();
-        value.append("}");
+        value.append('}');
     }
 
     /**
@@ -317,52 +325,51 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
      * @param in JsonReader reader
      * @throws IOException if operation fails
      */
-    private void readValueObject(@Nonnull final StringBuffer value, @Nonnull final JsonReader in) throws IOException {
+    private void readValueObject(final @NonNull StringBuilder value, final @NonNull JsonReader in) throws IOException {
         // read simple leaf value
         if (in.peek() == JsonToken.STRING) {
-            value.append("\"" + in.nextString() + "\"");
+            value.append('"').append(in.nextString()).append('"');
             return;
         }
 
         in.beginObject();
-        value.append("{");
+        value.append('{');
 
         while (in.hasNext()) {
-            value.append("\"" + in.nextName() + "\"");
-            value.append(":");
+            value.append('"').append(in.nextName()).append("\":");
 
             if (in.peek() == JsonToken.STRING) {
-                value.append("\"" + in.nextString() + "\"");
+                value.append('"').append(in.nextString()).append('"');
             } else {
                 if (in.peek() == JsonToken.BEGIN_ARRAY) {
                     in.beginArray();
-                    value.append("[");
+                    value.append('[');
 
                     while (in.hasNext()) {
                         if (in.peek() == JsonToken.STRING) {
-                            value.append("\"" + in.nextString() + "\"");
+                            value.append('"').append(in.nextString()).append('"');
                         } else {
                             readValueObject(value, in);
                         }
                         if (in.peek() != JsonToken.END_ARRAY) {
-                            value.append(",");
+                            value.append(',');
                         }
                     }
 
                     in.endArray();
-                    value.append("]");
+                    value.append(']');
                 } else {
                     readValueObject(value, in);
                 }
             }
 
             if (in.peek() != JsonToken.END_OBJECT) {
-                value.append(",");
+                value.append(',');
             }
         }
 
         in.endObject();
-        value.append("}");
+        value.append('}');
     }
 
     /**
@@ -370,13 +377,14 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
      * @param in reader JsonReader reader
      * @return NormalizedNode representing data
      */
-    private static NormalizedNode<?, ?> readEditData(@Nonnull final JsonReader in,
-            @Nonnull final SchemaNode targetSchemaNode, @Nonnull final InstanceIdentifierContext<?> path) {
+    private static NormalizedNode readEditData(final @NonNull JsonReader in,
+            final @NonNull SchemaNode targetSchemaNode, final @NonNull InstanceIdentifierContext<?> path) {
         final NormalizedNodeResult resultHolder = new NormalizedNodeResult();
         final NormalizedNodeStreamWriter writer = ImmutableNormalizedNodeStreamWriter.from(resultHolder);
-        JsonParserStream.create(writer,
-            JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(path.getSchemaContext()),
-            targetSchemaNode).parse(in);
+        final EffectiveModelContext context = path.getSchemaContext();
+        JsonParserStream.create(writer, JSONCodecFactorySupplier.DRAFT_LHOTKA_NETMOD_YANG_JSON_02.getShared(context),
+            SchemaInferenceStack.ofInstantiatedPath(context,  targetSchemaNode.getPath()).toInference())
+            .parse(in);
 
         return resultHolder.getResult();
     }
@@ -386,7 +394,7 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
      * @param edit Instance of PatchEdit
      * @return PatchEntity Patch entity
      */
-    private static PatchEntity prepareEditOperation(@Nonnull final PatchEdit edit) {
+    private static PatchEntity prepareEditOperation(final @NonNull PatchEdit edit) {
         if (edit.getOperation() != null && edit.getTargetSchemaNode() != null
                 && checkDataPresence(edit.getOperation(), edit.getData() != null)) {
             if (edit.getOperation().isWithValue()) {
@@ -414,7 +422,7 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
      * @return true if data is present when operation requires it or if there are no data when operation does not
      *     allow it, false otherwise
      */
-    private static boolean checkDataPresence(@Nonnull final PatchEditOperation operation, final boolean hasData) {
+    private static boolean checkDataPresence(final @NonNull PatchEditOperation operation, final boolean hasData) {
         return operation.isWithValue() == hasData;
     }
 
@@ -426,7 +434,7 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
         private PatchEditOperation operation;
         private YangInstanceIdentifier target;
         private SchemaNode targetSchemaNode;
-        private NormalizedNode<?, ?> data;
+        private NormalizedNode data;
 
         public String getId() {
             return this.id;
@@ -460,11 +468,11 @@ public class JsonToPatchBodyReader extends AbstractIdentifierAwareJaxRsProvider
             this.targetSchemaNode = targetSchemaNode;
         }
 
-        public NormalizedNode<?, ?> getData() {
+        public NormalizedNode getData() {
             return this.data;
         }
 
-        public void setData(final NormalizedNode<?, ?> data) {
+        public void setData(final NormalizedNode data) {
             this.data = data;
         }