Bug 2258: Fixed Type Definition search in runtime generated codecs
authorTony Tkacik <ttkacik@cisco.com>
Mon, 27 Oct 2014 13:11:37 +0000 (14:11 +0100)
committerRobert Varga <nite@hq.sk>
Fri, 16 Jan 2015 14:46:08 +0000 (14:46 +0000)
Type Definition search in runtime generated codecs, did not look
up nested (scoped) type definitions properly, which resulted
in IllegalArgumentException in schema context update which
prevented further working of codec.

Updated code to perform correct nested search in grouping
and type-definitoions.

Change-Id: I3860c2f70b5e0ba3d265b7f2b032e89eadaced08
Signed-off-by: Tony Tkacik <ttkacik@cisco.com>
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/YangSchemaUtils.java

index 3079c556b16293568a699092e0693d20fd4d7389..1084a0bf0f7dc8139825d3cbef4f83cf3abbdff4 100644 (file)
@@ -7,18 +7,20 @@
  */
 package org.opendaylight.yangtools.sal.binding.generator.util;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 
+import com.google.common.base.Preconditions;
 import java.net.URI;
 import java.util.Date;
-import java.util.List;
-
+import java.util.Iterator;
+import javax.annotation.Nullable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
 import org.opendaylight.yangtools.yang.model.api.NamespaceRevisionAware;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
@@ -34,7 +36,7 @@ public final class YangSchemaUtils {
 
     public static QName getAugmentationQName(final AugmentationSchema augmentation) {
         checkNotNull(augmentation, "Augmentation must not be null.");
-        QName identifier = getAugmentationIdentifier(augmentation);
+        final QName identifier = getAugmentationIdentifier(augmentation);
         if(identifier != null) {
             return identifier;
         }
@@ -45,7 +47,7 @@ public final class YangSchemaUtils {
             revision = ((NamespaceRevisionAware) augmentation).getRevision();
         }
         if(namespace == null || revision == null) {
-            for(DataSchemaNode child : augmentation.getChildNodes()) {
+            for(final DataSchemaNode child : augmentation.getChildNodes()) {
                 // Derive QName from child nodes
                 if(!child.isAugmenting()) {
                     namespace = child.getQName().getNamespace();
@@ -61,7 +63,7 @@ public final class YangSchemaUtils {
     }
 
     public static QName getAugmentationIdentifier(final AugmentationSchema augmentation) {
-        for(UnknownSchemaNode extension : augmentation.getUnknownSchemaNodes()) {
+        for(final UnknownSchemaNode extension : augmentation.getUnknownSchemaNodes()) {
             if(AUGMENT_IDENTIFIER.equals(extension.getNodeType().getLocalName())) {
                 return extension.getQName();
             }
@@ -69,17 +71,40 @@ public final class YangSchemaUtils {
         return null;
     }
 
+    @Nullable
     public static TypeDefinition<?> findTypeDefinition(final SchemaContext context, final SchemaPath path) {
-        List<QName> arguments = path.getPath();
-        QName first = arguments.get(0);
-        QName typeQName = arguments.get(arguments.size() -1);
-        DataNodeContainer previous = context.findModuleByNamespaceAndRevision(first.getNamespace(), first.getRevision());
-        if(previous == null) {
+        final Iterator<QName> arguments = path.getPathFromRoot().iterator();
+        Preconditions.checkArgument(arguments.hasNext(), "Type Definition path must contain at least one element.");
+
+        QName currentArg = arguments.next();
+        DataNodeContainer currentNode = context.findModuleByNamespaceAndRevision(currentArg.getNamespace(), currentArg.getRevision());
+        if(currentNode == null) {
             return null;
         }
-        checkArgument(arguments.size() == 1);
-        for(TypeDefinition<?> typedef : previous.getTypeDefinitions()) {
-            if(typedef.getQName().equals(typeQName)) {
+        // Last argument is type definition, so we need to cycle until we hit last argument.
+        while(arguments.hasNext()) {
+            // Nested private type - we need to find container/grouping to which type belongs.
+            final DataSchemaNode child = currentNode.getDataChildByName(currentArg);
+            if(child instanceof DataNodeContainer) {
+                currentNode = (DataNodeContainer) child;
+            } else if (child instanceof ChoiceNode) {
+                final QName caseQName = arguments.next();
+                Preconditions.checkArgument(arguments.hasNext(), "Path must not refer case only.");
+                currentNode = ((ChoiceNode) child).getCaseNodeByName(caseQName);
+            } else {
+                // Search in grouping
+                for( final GroupingDefinition grouping : currentNode.getGroupings()) {
+                    if(currentArg.equals(grouping.getQName())) {
+                        currentNode = grouping;
+                        break;
+                    }
+                }
+            }
+            currentArg = arguments.next();
+        }
+
+        for(final TypeDefinition<?> typedef : currentNode.getTypeDefinitions()) {
+            if(typedef.getQName().equals(currentArg)) {
                 return typedef;
             }
         }