BUG 1330 - list key counts|values diff in payload and URI
[controller.git] / opendaylight / md-sal / sal-rest-connector / src / main / java / org / opendaylight / controller / sal / restconf / impl / ControllerContext.java
index b0916f4500d65d9dfb3291f4435e7c2aad31cc1b..28e6a3c2472ee3b8723c82dc5d1050215c209bee 100644 (file)
@@ -7,6 +7,18 @@
  */
 package org.opendaylight.controller.sal.restconf.impl;
 
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.Iterables;
+
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URLDecoder;
@@ -36,6 +48,7 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdent
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
@@ -54,19 +67,6 @@ import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.HashBiMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-
 public class ControllerContext implements SchemaContextListener {
     private final static Logger LOG = LoggerFactory.getLogger( ControllerContext.class );
 
@@ -82,6 +82,10 @@ public class ControllerContext implements SchemaContextListener {
 
     private final static String URI_ENCODING_CHAR_SET = "ISO-8859-1";
 
+    private static final Splitter SLASH_SPLITTER = Splitter.on('/');
+
+    private static final Splitter COLON_SPLITTER = Splitter.on(':');
+
     private final BiMap<URI, String> uriToModuleName = HashBiMap.<URI, String> create();
 
     private final Map<String, URI> moduleNameToUri = uriToModuleName.inverse();
@@ -128,10 +132,8 @@ public class ControllerContext implements SchemaContextListener {
             final boolean toMountPointIdentifier ) {
         this.checkPreconditions();
 
-        Iterable<String> split = Splitter.on( "/" ).split( restconfInstance );
-        final ArrayList<String> encodedPathArgs = Lists.<String> newArrayList( split );
-        final List<String> pathArgs = this.urlPathArgsDecode( encodedPathArgs );
-        this.omitFirstAndLastEmptyString( pathArgs );
+        final List<String> pathArgs = urlPathArgsDecode( SLASH_SPLITTER.split( restconfInstance ) );
+        omitFirstAndLastEmptyString( pathArgs );
         if( pathArgs.isEmpty() ) {
             return null;
         }
@@ -157,7 +159,7 @@ public class ControllerContext implements SchemaContextListener {
         return iiWithSchemaNode;
     }
 
-    private List<String> omitFirstAndLastEmptyString( final List<String> list ) {
+    private static List<String> omitFirstAndLastEmptyString( final List<String> list ) {
         if( list.isEmpty() ) {
             return list;
         }
@@ -255,7 +257,7 @@ public class ControllerContext implements SchemaContextListener {
     public DataNodeContainer getDataNodeContainerFor( final InstanceIdentifier path ) {
         this.checkPreconditions();
 
-        final List<PathArgument> elements = path.getPath();
+        final Iterable<PathArgument> elements = path.getPathArguments();
         PathArgument head = elements.iterator().next();
         final QName startQName = head.getNodeType();
         final Module initialModule = globalSchema.findModuleByNamespaceAndRevision(
@@ -276,7 +278,7 @@ public class ControllerContext implements SchemaContextListener {
     public String toFullRestconfIdentifier( final InstanceIdentifier path ) {
         this.checkPreconditions();
 
-        final List<PathArgument> elements = path.getPath();
+        final Iterable<PathArgument> elements = path.getPathArguments();
         final StringBuilder builder = new StringBuilder();
         PathArgument head = elements.iterator().next();
         final QName startQName = head.getNodeType();
@@ -561,7 +563,7 @@ public class ControllerContext implements SchemaContextListener {
         }
 
         String head = strings.iterator().next();
-        final String nodeName = this.toNodeName( head );
+        final String nodeName = toNodeName( head );
         final String moduleName = ControllerContext.toModuleName( head );
 
         DataSchemaNode targetNode = null;
@@ -694,8 +696,8 @@ public class ControllerContext implements SchemaContextListener {
             final int keysSize = listNode.getKeyDefinition().size();
             if( (strings.size() - consumed) < keysSize ) {
                 throw new RestconfDocumentedException(
-                        "Missing key for list \"" + listNode.getQName().getLocalName() + "\".",
-                        ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE );
+                        "Missing key value for list element '" + listNode.getQName().getLocalName() + "' in the URI.",
+                        ErrorType.PROTOCOL, ErrorTag.DATA_MISSING );
             }
 
             final List<String> uriKeyValues = strings.subList( consumed, consumed + keysSize );
@@ -804,7 +806,8 @@ public class ControllerContext implements SchemaContextListener {
 
     public boolean isInstantiatedDataSchema( final DataSchemaNode node ) {
         return node instanceof LeafSchemaNode || node instanceof LeafListSchemaNode ||
-                node instanceof ContainerSchemaNode || node instanceof ListSchemaNode;
+                node instanceof ContainerSchemaNode || node instanceof ListSchemaNode ||
+                node instanceof AnyXmlSchemaNode;
     }
 
     private void addKeyValue( final HashMap<QName, Object> map, final DataSchemaNode node,
@@ -837,20 +840,20 @@ public class ControllerContext implements SchemaContextListener {
 
     private static String toModuleName( final String str ) {
         Preconditions.<String> checkNotNull( str );
-        if( str.contains( ":" ) ) {
-            final String[] args = str.split( ":" );
-            if( args.length == 2 ) {
-                return args[0];
+        if( str.indexOf( ':' ) != -1 ) {
+            final Iterable<String> args = COLON_SPLITTER.split( str );
+            if( Iterables.size( args ) == 2 ) {
+                return args.iterator().next();
             }
         }
         return null;
     }
 
-    private String toNodeName( final String str ) {
-        if( str.contains( ":" ) ) {
-            final String[] args = str.split( ":" );
-            if( args.length == 2 ) {
-                return args[1];
+    private static String toNodeName( final String str ) {
+        if( str.indexOf( ':' ) != -1 ) {
+            final Iterable<String> args = COLON_SPLITTER.split( str );
+            if( Iterables.size( args ) == 2 ) {
+                return Iterables.get( args, 1 );
             }
         }
         return str;
@@ -858,7 +861,7 @@ public class ControllerContext implements SchemaContextListener {
 
     private QName toQName( final String name ) {
         final String module = toModuleName( name );
-        final String node = this.toNodeName( name );
+        final String node = toNodeName( name );
         Set<Module> modules = globalSchema.getModules();
 
         final Comparator<Module> comparator = new Comparator<Module>() {
@@ -914,7 +917,7 @@ public class ControllerContext implements SchemaContextListener {
         }
     }
 
-    public List<String> urlPathArgsDecode( final List<String> strings ) {
+    public static List<String> urlPathArgsDecode( final Iterable<String> strings ) {
         try {
             List<String> decodedPathArgs = new ArrayList<String>();
             for( final String pathArg : strings ) {
@@ -996,7 +999,7 @@ public class ControllerContext implements SchemaContextListener {
             try {
                 builder.append( this.toUriString( keyValues.get( key ) ) );
             } catch( UnsupportedEncodingException e ) {
-                LOG.error( "Error parsing URI: " + keyValues.get( key ), e );
+                LOG.error( "Error parsing URI: {}", keyValues.get( key ), e );
                 return null;
             }
         }