Bump MRI upstreams
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / codecs / RestCodec.java
index 947002c9f014af93fdc631c6958480d6ced6fbff..d455e813f15c198faf8af5b187914388092e0401 100644 (file)
@@ -7,21 +7,27 @@
  */
 package org.opendaylight.restconf.nb.rfc8040.codecs;
 
-import com.google.common.base.Preconditions;
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.collect.Iterables;
-import java.net.URI;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.Set;
+import org.opendaylight.mdsal.dom.api.DOMMountPoint;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
 import org.opendaylight.restconf.common.util.IdentityValuesDTO;
 import org.opendaylight.restconf.common.util.IdentityValuesDTO.IdentityValue;
 import org.opendaylight.restconf.common.util.IdentityValuesDTO.Predicate;
 import org.opendaylight.restconf.common.util.RestUtil;
-import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.concepts.IllegalArgumentCodec;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.XMLNamespace;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
@@ -31,12 +37,13 @@ import org.opendaylight.yangtools.yang.data.api.codec.IdentityrefCodec;
 import org.opendaylight.yangtools.yang.data.api.codec.InstanceIdentifierCodec;
 import org.opendaylight.yangtools.yang.data.api.codec.LeafrefCodec;
 import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
-import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -56,26 +63,27 @@ public final class RestCodec {
     private RestCodec() {
     }
 
-    public static Codec<Object, Object> from(final TypeDefinition<?> typeDefinition,
-            final DOMMountPoint mountPoint, final SchemaContext schemaContext) {
+    // FIXME: IllegalArgumentCodec is not quite accurate
+    public static IllegalArgumentCodec<Object, Object> from(final TypeDefinition<?> typeDefinition,
+            final DOMMountPoint mountPoint, final EffectiveModelContext schemaContext) {
         return new ObjectCodec(typeDefinition, mountPoint, schemaContext);
     }
 
     @SuppressWarnings("rawtypes")
-    public static final class ObjectCodec implements Codec<Object, Object> {
+    public static final class ObjectCodec implements IllegalArgumentCodec<Object, Object> {
 
         private static final Logger LOG = LoggerFactory.getLogger(ObjectCodec.class);
 
-        public static final Codec LEAFREF_DEFAULT_CODEC = new LeafrefCodecImpl();
-        private final Codec instanceIdentifier;
-        private final Codec identityrefCodec;
+        public static final IllegalArgumentCodec LEAFREF_DEFAULT_CODEC = new LeafrefCodecImpl();
+        private final IllegalArgumentCodec instanceIdentifier;
+        private final IllegalArgumentCodec identityrefCodec;
 
         private final TypeDefinition<?> type;
 
-        private final SchemaContext schemaContext;
+        private final EffectiveModelContext schemaContext;
 
         private ObjectCodec(final TypeDefinition<?> typeDefinition, final DOMMountPoint mountPoint,
-                final SchemaContext schemaContext) {
+                final EffectiveModelContext schemaContext) {
             this.schemaContext = schemaContext;
             this.type = RestUtil.resolveBaseTypeFrom(typeDefinition);
             if (this.type instanceof IdentityrefTypeDefinition) {
@@ -101,7 +109,7 @@ public final class RestCodec {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug(
                             "Value is not instance of IdentityrefTypeDefinition but is {}. "
-                                    + "Therefore NULL is used as translation of  - {}",
+                                    + "Therefore NULL is used as translation of - {}",
                             input == null ? "null" : input.getClass(), String.valueOf(input));
                     }
                     return null;
@@ -122,15 +130,12 @@ public final class RestCodec {
                         }
                         return typeAwarecodec.deserialize(String.valueOf(input));
                     } else {
-                        LOG.debug("Codec for type \"" + this.type.getQName().getLocalName()
-                                + "\" is not implemented yet.");
+                        LOG.debug("Codec for type \"{}\" is not implemented yet.", type.getQName().getLocalName());
                         return null;
                     }
                 }
             } catch (final ClassCastException e) { // TODO remove this catch when everyone use codecs
-                LOG.error(
-                        "ClassCastException was thrown when codec is invoked with parameter " + String.valueOf(input),
-                        e);
+                LOG.error("ClassCastException was thrown when codec is invoked with parameter {}", input, e);
                 return null;
             }
         }
@@ -152,20 +157,16 @@ public final class RestCodec {
                         return typeAwarecodec.serialize(input);
                     } else {
                         if (LOG.isDebugEnabled()) {
-                            LOG.debug("Codec for type \"" + this.type.getQName().getLocalName()
-                                + "\" is not implemented yet.");
+                            LOG.debug("Codec for type \"{}\" is not implemented yet.", type.getQName().getLocalName());
                         }
                         return null;
                     }
                 }
             } catch (final ClassCastException e) { // TODO remove this catch when everyone use codecs
-                LOG.error(
-                        "ClassCastException was thrown when codec is invoked with parameter " + String.valueOf(input),
-                        e);
+                LOG.error("ClassCastException was thrown when codec is invoked with parameter {}", input, e);
                 return input;
             }
         }
-
     }
 
     public static class IdentityrefCodecImpl implements IdentityrefCodec<IdentityValuesDTO> {
@@ -233,11 +234,11 @@ public final class RestCodec {
                 final IdentityValue identityValue = qNameToIdentityValue(pathArgument.getNodeType());
                 if (pathArgument instanceof NodeIdentifierWithPredicates && identityValue != null) {
                     final List<Predicate> predicates =
-                            keyValuesToPredicateList(((NodeIdentifierWithPredicates) pathArgument).getKeyValues());
+                            keyValuesToPredicateList(((NodeIdentifierWithPredicates) pathArgument).entrySet());
                     identityValue.setPredicates(predicates);
                 } else if (pathArgument instanceof NodeWithValue && identityValue != null) {
                     final List<Predicate> predicates = new ArrayList<>();
-                    final String value = String.valueOf(((NodeWithValue) pathArgument).getValue());
+                    final String value = String.valueOf(((NodeWithValue<?>) pathArgument).getValue());
                     predicates.add(new Predicate(null, value));
                     identityValue.setPredicates(predicates);
                 }
@@ -246,6 +247,10 @@ public final class RestCodec {
             return identityValuesDTO;
         }
 
+        @SuppressFBWarnings(value = {
+            "NP_PARAMETER_MUST_BE_NONNULL_BUT_MARKED_AS_NULLABLE",
+            "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"
+        }, justification = "Unrecognised NullableDecl")
         @Override
         public YangInstanceIdentifier deserialize(final IdentityValuesDTO data) {
             final List<PathArgument> result = new ArrayList<>();
@@ -264,7 +269,7 @@ public final class RestCodec {
             final List<IdentityValue> identities = data.getValuesWithNamespaces();
             for (int i = 0; i < identities.size(); i++) {
                 final IdentityValue identityValue = identities.get(i);
-                URI validNamespace =
+                XMLNamespace validNamespace =
                         resolveValidNamespace(identityValue.getNamespace(), this.mountPoint, schemaContext);
                 final DataSchemaNode node = findInstanceDataChildByNameAndNamespace(
                         parentContainer, identityValue.getValue(), validNamespace);
@@ -298,7 +303,7 @@ public final class RestCodec {
                                     predicate.getName().getValue(), validNamespace);
                             predicatesMap.put(listKey.getQName(), predicate.getValue());
                         }
-                        pathArgument = new NodeIdentifierWithPredicates(qName, predicatesMap);
+                        pathArgument = NodeIdentifierWithPredicates.of(qName, predicatesMap);
                     } else {
                         LOG.info("Node {} is not List or Leaf-list.", node);
                         LOG.info("Instance-identifier will be translated as NULL for data - {}",
@@ -323,10 +328,11 @@ public final class RestCodec {
             return result.isEmpty() ? null : YangInstanceIdentifier.create(result);
         }
 
-        private static List<Predicate> keyValuesToPredicateList(final Map<QName, Object> keyValues) {
+        private static List<Predicate> keyValuesToPredicateList(final Set<Entry<QName, Object>> keyValues) {
             final List<Predicate> result = new ArrayList<>();
-            for (final QName qualifiedName : keyValues.keySet()) {
-                final Object value = keyValues.get(qualifiedName);
+            for (final Entry<QName, Object> entry : keyValues) {
+                final QName qualifiedName = entry.getKey();
+                final Object value = entry.getValue();
                 result.add(new Predicate(qNameToIdentityValue(qualifiedName), String.valueOf(value)));
             }
             return result;
@@ -340,38 +346,40 @@ public final class RestCodec {
         }
     }
 
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private static Module getModuleByNamespace(final String namespace, final DOMMountPoint mountPoint,
             final SchemaContext schemaContext) {
-        final URI validNamespace = resolveValidNamespace(namespace, mountPoint, schemaContext);
+        final XMLNamespace validNamespace = resolveValidNamespace(namespace, mountPoint, schemaContext);
         Module module = null;
         if (mountPoint != null) {
-            module = mountPoint.getSchemaContext().findModules(validNamespace).iterator().next();
+            module = modelContext(mountPoint).findModules(validNamespace).iterator().next();
         } else {
             module = schemaContext.findModules(validNamespace).iterator().next();
         }
         if (module == null) {
-            LOG.info("Module for namespace " + validNamespace + " wasn't found.");
+            LOG.info("Module for namespace {} was not found.", validNamespace);
             return null;
         }
         return module;
     }
 
-    private static URI resolveValidNamespace(final String namespace, final DOMMountPoint mountPoint,
+    private static XMLNamespace resolveValidNamespace(final String namespace, final DOMMountPoint mountPoint,
             final SchemaContext schemaContext) {
-        URI validNamespace;
+        XMLNamespace validNamespace;
         if (mountPoint != null) {
-            validNamespace = findFirstModuleByName(schemaContext, namespace);
+            validNamespace = findFirstModuleByName(modelContext(mountPoint), namespace);
         } else {
             validNamespace = findFirstModuleByName(schemaContext, namespace);
         }
         if (validNamespace == null) {
-            validNamespace = URI.create(namespace);
+            validNamespace = XMLNamespace.of(namespace);
         }
 
         return validNamespace;
     }
 
-    private static URI findFirstModuleByName(final SchemaContext schemaContext, final String name) {
+    private static XMLNamespace findFirstModuleByName(final SchemaContext schemaContext, final String name) {
         for (final Module module : schemaContext.getModules()) {
             if (module.getName().equals(name)) {
                 return module.getNamespace();
@@ -380,9 +388,11 @@ public final class RestCodec {
         return null;
     }
 
+    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
+            justification = "https://github.com/spotbugs/spotbugs/issues/811")
     private static DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container,
-            final String name, final URI namespace) {
-        Preconditions.checkNotNull(namespace);
+            final String name, final XMLNamespace namespace) {
+        requireNonNull(namespace);
 
         final Iterable<DataSchemaNode> result = Iterables.filter(findInstanceDataChildrenByName(container, name),
             node -> namespace.equals(node.getQName().getNamespace()));
@@ -391,18 +401,16 @@ public final class RestCodec {
 
     private static List<DataSchemaNode> findInstanceDataChildrenByName(final DataNodeContainer container,
             final String name) {
-        Preconditions.checkNotNull(container);
-        Preconditions.checkNotNull(name);
-
         final List<DataSchemaNode> instantiatedDataNodeContainers = new ArrayList<>();
-        collectInstanceDataNodeContainers(instantiatedDataNodeContainers, container, name);
+        collectInstanceDataNodeContainers(instantiatedDataNodeContainers, requireNonNull(container),
+            requireNonNull(name));
         return instantiatedDataNodeContainers;
     }
 
     private static void collectInstanceDataNodeContainers(final List<DataSchemaNode> potentialSchemaNodes,
             final DataNodeContainer container, final String name) {
 
-        final Iterable<DataSchemaNode> nodes =
+        final Iterable<? extends DataSchemaNode> nodes =
                 Iterables.filter(container.getChildNodes(), node -> name.equals(node.getQName().getLocalName()));
 
         // Can't combine this loop with the filter above because the filter is
@@ -415,8 +423,8 @@ public final class RestCodec {
 
         final Iterable<ChoiceSchemaNode> choiceNodes =
                 Iterables.filter(container.getChildNodes(), ChoiceSchemaNode.class);
-        final Iterable<Collection<CaseSchemaNode>> map = Iterables.transform(choiceNodes,
-            choice -> choice.getCases().values());
+        final Iterable<Collection<? extends CaseSchemaNode>> map = Iterables.transform(choiceNodes,
+            ChoiceSchemaNode::getCases);
         for (final CaseSchemaNode caze : Iterables.concat(map)) {
             collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name);
         }
@@ -425,6 +433,12 @@ public final class RestCodec {
     private static boolean isInstantiatedDataSchema(final DataSchemaNode node) {
         return node instanceof LeafSchemaNode || node instanceof LeafListSchemaNode
                 || node instanceof ContainerSchemaNode || node instanceof ListSchemaNode
-                || node instanceof AnyXmlSchemaNode;
+                || node instanceof AnyxmlSchemaNode;
+    }
+
+    private static EffectiveModelContext modelContext(final DOMMountPoint mountPoint) {
+        return mountPoint.getService(DOMSchemaService.class)
+            .flatMap(svc -> Optional.ofNullable(svc.getGlobalContext()))
+            .orElse(null);
     }
 }