Use Optional.isEmpty()
[netconf.git] / restconf / restconf-nb-rfc8040 / src / main / java / org / opendaylight / restconf / nb / rfc8040 / utils / parser / YangInstanceIdentifierDeserializer.java
index acbb65a60b38e19684863266122ebc9cade36ee0..de31eb364ddf2936c2b0629854ad6ee56af57119 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.restconf.nb.rfc8040.utils.parser;
 
 import static java.util.Objects.requireNonNull;
-import static org.opendaylight.restconf.nb.rfc8040.utils.RestconfConstants.SLASH;
 
 import com.google.common.base.CharMatcher;
 import com.google.common.collect.ImmutableList;
@@ -32,9 +31,10 @@ import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
 import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
 import org.opendaylight.yangtools.yang.model.api.ActionNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerLike;
 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.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
@@ -64,13 +64,13 @@ public final class YangInstanceIdentifierDeserializer {
     // percent encoded radix for parsing integers
     private static final int PERCENT_ENCODED_RADIX = 16;
 
-    private final SchemaContext schemaContext;
+    private final EffectiveModelContext schemaContext;
     private final String data;
 
     private DataSchemaContextNode<?> current;
     private int offset;
 
-    private YangInstanceIdentifierDeserializer(final SchemaContext schemaContext, final String data) {
+    private YangInstanceIdentifierDeserializer(final EffectiveModelContext schemaContext, final String data) {
         this.schemaContext = requireNonNull(schemaContext);
         this.data = requireNonNull(data);
         current = DataSchemaContextTree.from(schemaContext).getRoot();
@@ -83,7 +83,7 @@ public final class YangInstanceIdentifierDeserializer {
      * @param data path to data, in URL string form
      * @return {@link Iterable} of {@link PathArgument}
      */
-    public static Iterable<PathArgument> create(final SchemaContext schemaContext, final String data) {
+    public static Iterable<PathArgument> create(final EffectiveModelContext schemaContext, final String data) {
         return new YangInstanceIdentifierDeserializer(schemaContext, data).parse();
     }
 
@@ -95,7 +95,7 @@ public final class YangInstanceIdentifierDeserializer {
             final QName qname = prepareQName();
 
             // this is the last identifier (input is consumed) or end of identifier (slash)
-            if (allCharsConsumed() || currentChar() == SLASH) {
+            if (allCharsConsumed() || currentChar() == '/') {
                 prepareIdentifier(qname, path);
                 path.add(current == null ? NodeIdentifier.create(qname) : current.getIdentifier());
             } else if (currentChar() == '=') {
@@ -123,7 +123,7 @@ public final class YangInstanceIdentifierDeserializer {
         skipCurrentChar();
 
         // read key value separated by comma
-        while (keys.hasNext() && !allCharsConsumed() && currentChar() != SLASH) {
+        while (keys.hasNext() && !allCharsConsumed() && currentChar() != '/') {
 
             // empty key value
             if (currentChar() == ',') {
@@ -139,7 +139,7 @@ public final class YangInstanceIdentifierDeserializer {
             // parse value
             final QName key = keys.next();
             Optional<DataSchemaNode> leafSchemaNode = listSchemaNode.findDataChildByName(key);
-            RestconfDocumentedException.throwIf(!leafSchemaNode.isPresent(), ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT,
+            RestconfDocumentedException.throwIf(leafSchemaNode.isEmpty(), ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT,
                     "Schema not found for %s", key);
 
             final String value = findAndParsePercentEncoded(nextIdentifierFromNextSequence(IDENTIFIER_PREDICATE));
@@ -180,10 +180,8 @@ public final class YangInstanceIdentifierDeserializer {
                     schemaNode);
         }
         decoded = RestCodec.from(typedef, null, schemaContext).deserialize(value);
-        if (decoded == null) {
-            if (baseType instanceof IdentityrefTypeDefinition) {
-                decoded = toQName(value, schemaNode, schemaContext);
-            }
+        if (decoded == null && typedef instanceof IdentityrefTypeDefinition) {
+            decoded = toIdentityrefQName(value, schemaNode);
         }
         return decoded;
     }
@@ -319,11 +317,11 @@ public final class YangInstanceIdentifierDeserializer {
     private void validArg() {
         // every identifier except of the first MUST start with slash
         if (offset != 0) {
-            checkValid(SLASH == currentChar(), ErrorTag.MALFORMED_MESSAGE, "Identifier must start with '/'.");
+            checkValid('/' == currentChar(), ErrorTag.MALFORMED_MESSAGE, "Identifier must start with '/'.");
 
             // skip consecutive slashes, users often assume restconf URLs behave just as HTTP does by squashing
             // multiple slashes into a single one
-            while (!allCharsConsumed() && SLASH == currentChar()) {
+            while (!allCharsConsumed() && '/' == currentChar()) {
                 skipCurrentChar();
             }
 
@@ -334,8 +332,8 @@ public final class YangInstanceIdentifierDeserializer {
 
     private QName getQNameOfDataSchemaNode(final String nodeName) {
         final DataSchemaNode dataSchemaNode = current.getDataSchemaNode();
-        if (dataSchemaNode instanceof ContainerSchemaNode) {
-            return getQNameOfDataSchemaNode((ContainerSchemaNode) dataSchemaNode, nodeName);
+        if (dataSchemaNode instanceof ContainerLike) {
+            return getQNameOfDataSchemaNode((ContainerLike) dataSchemaNode, nodeName);
         } else if (dataSchemaNode instanceof ListSchemaNode) {
             return getQNameOfDataSchemaNode((ListSchemaNode) dataSchemaNode, nodeName);
         }
@@ -384,12 +382,18 @@ public final class YangInstanceIdentifierDeserializer {
         return parsedPrefix.toString();
     }
 
-    private static Object toQName(final String value, final DataSchemaNode schemaNode,
-            final SchemaContext schemaContext) {
+    private QName toIdentityrefQName(final String value, final DataSchemaNode schemaNode) {
         final String moduleName = toModuleName(value);
         final String nodeName = toNodeName(value);
-        final Module module = schemaContext.findModules(moduleName).iterator().next();
-        for (final IdentitySchemaNode identitySchemaNode : module.getIdentities()) {
+        final Iterator<? extends Module> modulesIterator = schemaContext.findModules(moduleName).iterator();
+        if (!modulesIterator.hasNext()) {
+            throw new RestconfDocumentedException(String.format("Cannot decode value '%s' for identityref type "
+                    + "in %s. Make sure reserved characters such as comma, single-quote, double-quote, colon,"
+                    + " double-quote, space, and forward slash (,'\":\" /) are percent-encoded,"
+                    + " for example ':' is '%%3A'", value, current.getIdentifier().getNodeType()),
+                    ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
+        }
+        for (final IdentitySchemaNode identitySchemaNode : modulesIterator.next().getIdentities()) {
             final QName qName = identitySchemaNode.getQName();
             if (qName.getLocalName().equals(nodeName)) {
                 return qName;