Further cleanups of code
[yangtools.git] / yang / yang-data-util / src / main / java / org / opendaylight / yangtools / yang / data / util / XpathStringParsingPathArgumentBuilder.java
index d25f0655c0652bdf383e4051dda65059c36e2298..fe5aaffee788e3809563d6f9ac68c4c49d19d617 100644 (file)
@@ -12,6 +12,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import java.util.LinkedList;
+import java.util.List;
 import javax.annotation.Nullable;
 import org.opendaylight.yangtools.concepts.Builder;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -70,12 +71,12 @@ class XpathStringParsingPathArgumentBuilder implements Builder<Iterable<PathArgu
     private final AbstractStringInstanceIdentifierCodec codec;
     private final String data;
 
-    private final LinkedList<PathArgument> product = new LinkedList<>();
+    private final List<PathArgument> product = new LinkedList<>();
 
     private DataSchemaContextNode<?> current;
     private int offset;
 
-    XpathStringParsingPathArgumentBuilder(AbstractStringInstanceIdentifierCodec codec, String data) {
+    XpathStringParsingPathArgumentBuilder(final AbstractStringInstanceIdentifierCodec codec, final String data) {
         this.codec = Preconditions.checkNotNull(codec);
         this.data = Preconditions.checkNotNull(data);
         this.current = codec.getDataContextTree().getRoot();
@@ -92,11 +93,11 @@ class XpathStringParsingPathArgumentBuilder implements Builder<Iterable<PathArgu
     }
 
     private PathArgument computeNextArgument() {
-        checkValid(SLASH  == currentChar(),"Identifier must start with '/'.");
+        checkValid(SLASH == currentChar(), "Identifier must start with '/'.");
         skipCurrentChar();
-
+        checkValid(!allCharactersConsumed(), "Identifier cannot end with '/'.");
         QName name = nextQName();
-        if(allCharactersConsumed() || SLASH == currentChar()) {
+        if (allCharactersConsumed() || SLASH == currentChar()) {
             return computeIdentifier(name);
         } else {
             checkValid(PRECONDITION_START == currentChar(), "Last element must be identifier, predicate or '/'");
@@ -105,10 +106,10 @@ class XpathStringParsingPathArgumentBuilder implements Builder<Iterable<PathArgu
     }
 
 
-    private DataSchemaContextNode<?> nextContextNode(QName name) {
+    private DataSchemaContextNode<?> nextContextNode(final QName name) {
         current = current.getChild(name);
         checkValid(current != null, "%s is not correct schema node identifier.",name);
-        while(current.isMixin()) {
+        while (current.isMixin()) {
             product.add(current.getIdentifier());
             current = current.getChild(name);
         }
@@ -132,16 +133,16 @@ class XpathStringParsingPathArgumentBuilder implements Builder<Iterable<PathArgu
      * @param name QName of node, for which predicates are computed.
      * @return PathArgument representing node selection with predictes
      */
-    private PathArgument computeIdentifierWithPredicate(QName name) {
+    private PathArgument computeIdentifierWithPredicate(final QName name) {
         DataSchemaContextNode<?> currentNode = nextContextNode(name);
         checkValid(currentNode.isKeyedEntry(), "Entry %s does not allow specifying predicates.", name);
 
         ImmutableMap.Builder<QName,Object> keyValues = ImmutableMap.builder();
-        while(!allCharactersConsumed() && PRECONDITION_START == currentChar()) {
+        while (!allCharactersConsumed() && PRECONDITION_START == currentChar()) {
             skipCurrentChar();
             skipWhitespaces();
             final QName key;
-            if(DOT == currentChar()) {
+            if (DOT == currentChar()) {
                 key = null;
                 skipCurrentChar();
             } else {
@@ -150,22 +151,25 @@ class XpathStringParsingPathArgumentBuilder implements Builder<Iterable<PathArgu
             skipWhitespaces();
             checkCurrentAndSkip(EQUALS, "Precondition must contain '='");
             skipWhitespaces();
-            final Object value = deserializeValue(key,nextQuotedValue());
+            final String keyValue = nextQuotedValue();
             skipWhitespaces();
             checkCurrentAndSkip(PRECONDITION_END, "Precondition must ends with ']'");
 
             // Break-out from method for leaf-list case
-            if(key == null && currentNode.isLeaf()) {
+            if (key == null && currentNode.isLeaf()) {
                 checkValid(offset == data.length(), "Leaf argument must be last argument of instance identifier.");
-                return new YangInstanceIdentifier.NodeWithValue(name, value);
+                return new YangInstanceIdentifier.NodeWithValue<>(name, keyValue);
             }
+            final DataSchemaContextNode<?> keyNode = currentNode.getChild(key);
+            checkValid(keyNode != null, "%s is not correct schema node identifier.", key);
+            final Object value = codec.deserializeKeyValue(keyNode.getDataSchemaNode(), keyValue);
             keyValues.put(key, value);
         }
         return new YangInstanceIdentifier.NodeIdentifierWithPredicates(name, keyValues.build());
     }
 
 
-    private PathArgument computeIdentifier(QName name) {
+    private PathArgument computeIdentifier(final QName name) {
         DataSchemaContextNode<?> currentNode = nextContextNode(name);
         checkValid(!currentNode.isKeyedEntry(), "Entry %s requires key or value predicate to be present", name);
         return currentNode.getIdentifier();
@@ -182,7 +186,7 @@ class XpathStringParsingPathArgumentBuilder implements Builder<Iterable<PathArgu
         // Consume prefix or identifie
         final String maybePrefix = nextIdentifier();
         final String prefix,localName;
-        if(COLON == currentChar()) {
+        if (COLON == currentChar()) {
             // previous token is prefix;
             prefix = maybePrefix;
             skipCurrentChar();
@@ -206,7 +210,7 @@ class XpathStringParsingPathArgumentBuilder implements Builder<Iterable<PathArgu
     }
 
 
-    private QName createQName(String prefix, String localName) {
+    private QName createQName(final String prefix, final String localName) {
         return codec.createQName(prefix, localName);
     }
 
@@ -217,7 +221,7 @@ class XpathStringParsingPathArgumentBuilder implements Builder<Iterable<PathArgu
      * @param expected Expected character
      * @param errorMsg Error message if {@link #currentChar()} does not match expected.
      */
-    private void checkCurrentAndSkip(char expected, String errorMsg) {
+    private void checkCurrentAndSkip(final char expected, final String errorMsg) {
         checkValid(expected == currentChar(), errorMsg);
         offset++;
     }
@@ -231,7 +235,7 @@ class XpathStringParsingPathArgumentBuilder implements Builder<Iterable<PathArgu
      * @param value Value to be checked and deserialized
      * @return Object representing value in yang-data-api format.
      */
-    private Object deserializeValue(@Nullable QName key, String value) {
+    private Object deserializeValue(@Nullable final QName key, final String value) {
         // FIXME: Use codec to deserialize value to correct Java type
         return value;
     }
@@ -247,7 +251,7 @@ class XpathStringParsingPathArgumentBuilder implements Builder<Iterable<PathArgu
      * @param errorMsg Error message which will be provided to user.
      * @param attributes
      */
-    private void checkValid(boolean condition, String errorMsg, Object... attributes) {
+    private void checkValid(final boolean condition, final String errorMsg, final Object... attributes) {
         Preconditions.checkArgument(condition, "Could not parse Instance Identifier '%s'. Offset: %s : Reason: %s",
                 data,
                 offset,
@@ -310,13 +314,13 @@ class XpathStringParsingPathArgumentBuilder implements Builder<Iterable<PathArgu
         return data.substring(start, offset);
     }
 
-    private void nextSequenceEnd(CharMatcher matcher) {
-        while(!allCharactersConsumed() && matcher.matches(data.charAt(offset))) {
+    private void nextSequenceEnd(final CharMatcher matcher) {
+        while (!allCharactersConsumed() && matcher.matches(data.charAt(offset))) {
             offset++;
         }
     }
 
-    private void checkValidQuotation(char quoteChar) {
+    private void checkValidQuotation(final char quoteChar) {
         checkValid(
                 SQUOTE.matches(quoteChar) || DQUOTE.matches(quoteChar),
                 "Value must be qoute escaped with ''' or '\"'.");