Merge "BUG-1018 Implement BackwardsCompatible BI broker data notifications"
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / md / sal / binding / impl / BindingToNormalizedNodeCodec.java
index 53615ad7dedc6c7d751554fb7f28bf446b96f1ee..f1be5c6922ecda45cc75f343b3f6355e402e013d 100644 (file)
@@ -13,18 +13,17 @@ import java.util.AbstractMap.SimpleEntry;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map.Entry;
-import java.util.concurrent.Callable;
 
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
-import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.util.ClassLoaderUtils;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
@@ -44,6 +43,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 
@@ -142,27 +142,46 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
             return potential;
         }
 
+        int normalizedCount = getAugmentationCount(normalized);
         AugmentationIdentifier lastArgument = (AugmentationIdentifier) Iterables.getLast(normalized.getPath());
 
         // Here we employ small trick - Binding-aware Codec injects an pointer
         // to augmentation class
         // if child is referenced - so we will reference child and then shorten
         // path.
+        LOG.trace("Looking for candidates to match {}", normalized);
         for (QName child : lastArgument.getPossibleChildNames()) {
             org.opendaylight.yangtools.yang.data.api.InstanceIdentifier childPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
                     ImmutableList.<PathArgument> builder().addAll(normalized.getPath()).add(new NodeIdentifier(child))
                             .build());
             try {
-                if (!isChoiceOrCasePath(childPath)) {
-                    InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(toBindingImpl(
-                            childPath).get());
-                    return Optional.<InstanceIdentifier<? extends DataObject>> of(potentialPath);
+                if (isNotRepresentable(childPath)) {
+                    LOG.trace("Path {} is not BI-representable, skipping it", childPath);
+                    continue;
                 }
-            } catch (Exception e) {
-                LOG.trace("Unable to deserialize aug. child path for {}", childPath, e);
+            } catch (DataNormalizationException e) {
+                LOG.warn("Failed to denormalize path {}, skipping it", childPath, e);
+                continue;
+            }
+
+            Optional<InstanceIdentifier<? extends DataObject>> baId = toBindingImpl(childPath);
+            if (!baId.isPresent()) {
+                LOG.debug("No binding-aware identifier found for path {}, skipping it", childPath);
+                continue;
+            }
+
+            InstanceIdentifier<? extends DataObject> potentialPath = shortenToLastAugment(baId.get());
+            int potentialAugmentCount = getAugmentationCount(potentialPath);
+            if (potentialAugmentCount == normalizedCount) {
+                LOG.trace("Found matching path {}", potentialPath);
+                return Optional.<InstanceIdentifier<? extends DataObject>> of(potentialPath);
             }
+
+            LOG.trace("Skipping mis-matched potential path {}", potentialPath);
         }
-        return toBindingImpl(normalized);
+
+        LOG.trace("Failed to find augmentation matching {}", normalized);
+        return Optional.absent();
     }
 
     private Optional<InstanceIdentifier<? extends DataObject>> toBindingImpl(
@@ -171,7 +190,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath;
 
         try {
-            if (isChoiceOrCasePath(normalized)) {
+            if (isNotRepresentable(normalized)) {
                 return Optional.absent();
             }
             legacyPath = legacyToNormalized.toLegacy(normalized);
@@ -183,10 +202,16 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         return Optional.<InstanceIdentifier<? extends DataObject>> of(bindingToLegacy.fromDataDom(legacyPath));
     }
 
-    private boolean isChoiceOrCasePath(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
+    private boolean isNotRepresentable(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
             throws DataNormalizationException {
         DataNormalizationOperation<?> op = findNormalizationOperation(normalized);
-        return op.isMixin() && op.getIdentifier() instanceof NodeIdentifier;
+        if( op.isMixin() && op.getIdentifier() instanceof NodeIdentifier) {
+            return true;
+        }
+        if(op.isLeaf()) {
+            return true;
+        }
+        return false;
     }
 
     private DataNormalizationOperation<?> findNormalizationOperation(
@@ -256,7 +281,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         if (isAugmentationIdentifier(processed)) {
             return processed;
         }
-        // Here we employ small trick - DataNormalizer injecst augmentation
+        // Here we employ small trick - DataNormalizer injects augmentation
         // identifier if child is
         // also part of the path (since using a child we can safely identify
         // augmentation)
@@ -339,11 +364,9 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         } else if (List.class.isAssignableFrom(returnType)) {
             try {
                 return ClassLoaderUtils.withClassLoader(method.getDeclaringClass().getClassLoader(),
-                        new Callable<Class>() {
-
-                            @SuppressWarnings("rawtypes")
+                        new Supplier<Class>() {
                             @Override
-                            public Class call() throws Exception {
+                            public Class get() {
                                 Type listResult = ClassLoaderUtils.getFirstGenericParameter(method
                                         .getGenericReturnType());
                                 if (listResult instanceof Class
@@ -383,4 +406,25 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
     private boolean isAugmentationIdentifier(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier processed) {
         return Iterables.getLast(processed.getPath()) instanceof AugmentationIdentifier;
     }
+
+    private static int getAugmentationCount(final InstanceIdentifier<?> potential) {
+        int count = 0;
+        for(org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : potential.getPathArguments()) {
+            if(isAugmentation(arg.getType())) {
+                count++;
+            }
+
+        }
+        return count;
+    }
+
+    private static int getAugmentationCount(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier potential) {
+        int count = 0;
+        for(PathArgument arg : potential.getPath()) {
+            if(arg instanceof AugmentationIdentifier) {
+                count++;
+            }
+        }
+        return count;
+    }
 }