Resolve generated type for leafrefs targetting unions
[mdsal.git] / binding / mdsal-binding-generator-impl / src / main / java / org / opendaylight / mdsal / binding / yang / types / AbstractTypeProvider.java
index 0d33ef4236717c026968c285ce02e47553dad3e1..88af37f1e5d3ca53bd792f196d39dac0eba99a59 100644 (file)
@@ -9,8 +9,8 @@ package org.opendaylight.mdsal.binding.yang.types;
 
 import static java.util.Objects.requireNonNull;
 import static org.opendaylight.mdsal.binding.model.util.BindingTypes.TYPE_OBJECT;
-import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath;
+import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataTreeSchemaNode;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
 
 import com.google.common.annotations.Beta;
@@ -223,6 +223,17 @@ public abstract class AbstractTypeProvider implements TypeProvider {
         return returnType;
     }
 
+    public SchemaNode getTargetForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode) {
+        final PathExpression xpath = leafrefType.getPathStatement();
+        Preconditions.checkArgument(xpath != null, "The Path Statement for Leafref Type Definition cannot be NULL!");
+
+        final Module module = findParentModule(schemaContext, parentNode);
+        Preconditions.checkArgument(module != null, "Failed to find module for parent %s", parentNode);
+
+        return xpath.isAbsolute() ? findDataTreeSchemaNode(schemaContext, module.getQNameModule(), xpath)
+                : findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath);
+    }
+
     private GeneratedTransferObject shadedTOWithRestrictions(final GeneratedTransferObject gto,
             final Restrictions restrictions) {
         final GeneratedTOBuilder gtob = newGeneratedTOBuilder(gto.getIdentifier());
@@ -244,45 +255,42 @@ public abstract class AbstractTypeProvider implements TypeProvider {
     }
 
     private boolean isLeafRefSelfReference(final LeafrefTypeDefinition leafref, final SchemaNode parentNode) {
-        final SchemaNode leafRefValueNode;
-        final PathExpression leafRefXPath = leafref.getPathStatement();
-        final PathExpression leafRefStrippedXPath = new PathExpressionImpl(
-            GROUPS_PATTERN.matcher(leafRefXPath.getOriginalString()).replaceAll(""), leafRefXPath.isAbsolute());
-
-        ///// skip leafrefs in augments - they're checked once augments are resolved
-        final Iterator<QName> iterator = parentNode.getPath().getPathFromRoot().iterator();
-        boolean isAugmenting = false;
+        /*
+         * First check if the leafref is an augment. If that is the case, skip it as it will be checked once augments
+         * are resolved.
+         */
         DataNodeContainer current = null;
         DataSchemaNode dataChildByName;
-
-        while (iterator.hasNext() && !isAugmenting) {
-            final QName next = iterator.next();
+        for (QName next : parentNode.getPath().getPathFromRoot()) {
             if (current == null) {
                 dataChildByName = schemaContext.getDataChildByName(next);
             } else {
                 dataChildByName = current.getDataChildByName(next);
             }
-            if (dataChildByName != null) {
-                isAugmenting = dataChildByName.isAugmenting();
-            } else {
+            if (dataChildByName == null) {
+                return false;
+            }
+            if (dataChildByName.isAugmenting()) {
                 return false;
             }
             if (dataChildByName instanceof DataNodeContainer) {
                 current = (DataNodeContainer) dataChildByName;
             }
         }
-        if (isAugmenting) {
-            return false;
-        }
-        /////
 
+        // Then try to look up the expression.
+        final PathExpression leafRefXPath = leafref.getPathStatement();
         final Module parentModule = getParentModule(parentNode);
-        if (!leafRefStrippedXPath.isAbsolute()) {
-            leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule,
-                    parentNode, leafRefStrippedXPath);
+        final SchemaNode leafRefValueNode;
+        if (leafRefXPath.isAbsolute()) {
+            leafRefValueNode = SchemaContextUtil.findDataTreeSchemaNode(schemaContext, parentModule.getQNameModule(),
+                leafRefXPath);
         } else {
-            leafRefValueNode = SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, leafRefStrippedXPath);
+            leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule,
+                parentNode, new PathExpressionImpl(
+                    GROUPS_PATTERN.matcher(leafRefXPath.getOriginalString()).replaceAll(""), false));
         }
+
         return leafRefValueNode != null && leafRefValueNode.equals(parentNode);
     }
 
@@ -517,7 +525,7 @@ public abstract class AbstractTypeProvider implements TypeProvider {
 
         final SchemaNode dataNode;
         if (xpath.isAbsolute()) {
-            dataNode = findDataSchemaNode(schemaContext, module, xpath);
+            dataNode = findDataTreeSchemaNode(schemaContext, module.getQNameModule(), xpath);
         } else {
             dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath);
             if (dataNode == null && inGrouping) {
@@ -561,7 +569,7 @@ public abstract class AbstractTypeProvider implements TypeProvider {
             returnType = Types.listTypeFor(referencedTypes.get(dataNode.getPath()));
         }
         if (returnType == null) {
-            returnType = resolveTypeFromDataSchemaNode(dataNode);
+            returnType = resolveTypeFromDataSchemaNode(dataNode, inGrouping);
         }
         Preconditions.checkArgument(returnType != null, "Failed to find leafref target: %s in module %s (%s)",
                 strXPath, this.getParentModule(parentNode).getName(), parentNode.getQName().getModule(), this);
@@ -717,16 +725,16 @@ public abstract class AbstractTypeProvider implements TypeProvider {
      * @param dataNode contains information about YANG type
      * @return JAVA <code>Type</code> representation of <code>dataNode</code>
      */
-    private Type resolveTypeFromDataSchemaNode(final SchemaNode dataNode) {
+    private Type resolveTypeFromDataSchemaNode(final SchemaNode dataNode, final boolean inGrouping) {
         Type returnType = null;
         if (dataNode != null) {
             if (dataNode instanceof LeafSchemaNode) {
                 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
                 final TypeDefinition<?> type = CompatUtils.compatType(leaf);
-                returnType = javaTypeForSchemaDefinitionType(type, leaf);
+                returnType = javaTypeForSchemaDefinitionType(type, leaf, inGrouping);
             } else if (dataNode instanceof LeafListSchemaNode) {
                 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
-                returnType = javaTypeForSchemaDefinitionType(leafList.getType(), leafList);
+                returnType = javaTypeForSchemaDefinitionType(leafList.getType(), leafList, inGrouping);
             }
         }
         return returnType;
@@ -1535,7 +1543,7 @@ public abstract class AbstractTypeProvider implements TypeProvider {
                 if (module != null) {
                     final SchemaNode dataNode;
                     if (xpath.isAbsolute()) {
-                        dataNode = findDataSchemaNode(schemaContext, module, xpath);
+                        dataNode = findDataTreeSchemaNode(schemaContext, module.getQNameModule(), xpath);
                     } else {
                         dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath);
                     }