Merge "Custom mailbox that is bounded and instrumented."
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / main / java / org / opendaylight / controller / md / sal / binding / impl / BindingToNormalizedNodeCodec.java
index 003f57cd72f053557a79fa761896894836ced89e..66caaea7083af18f1ffaedc3113f4e35d167b4ff 100644 (file)
@@ -8,11 +8,12 @@
 package org.opendaylight.controller.md.sal.binding.impl;
 
 import java.lang.reflect.Method;
-import java.lang.reflect.Type;
 import java.util.AbstractMap.SimpleEntry;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Map.Entry;
+import java.util.Set;
 
 import javax.annotation.Nullable;
 
@@ -20,17 +21,17 @@ import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizat
 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.yang.binding.Augmentation;
-import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
 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.YangModuleInfo;
 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.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
@@ -39,6 +40,9 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.opendaylight.yangtools.yang.data.impl.codec.DeserializationException;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.slf4j.Logger;
@@ -47,7 +51,7 @@ import org.slf4j.LoggerFactory;
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
-import com.google.common.base.Supplier;
+import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 
@@ -63,7 +67,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         this.bindingToLegacy = mappingService;
     }
 
-    public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toNormalized(
+    public org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalized(
             final InstanceIdentifier<? extends DataObject> binding) {
 
         // Used instance-identifier codec do not support serialization of last
@@ -77,17 +81,17 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         return toNormalizedImpl(binding);
     }
 
-    public Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
+    public Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
             final InstanceIdentifier<? extends DataObject> bindingPath, final DataObject bindingObject) {
         return toNormalizedNode(toBindingEntry(bindingPath, bindingObject));
 
     }
 
-    public Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
+    public Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
             final Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject> binding) {
-        Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> legacyEntry = bindingToLegacy
+        Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, CompositeNode> legacyEntry = bindingToLegacy
                 .toDataDom(binding);
-        Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> normalizedEntry = legacyToNormalized
+        Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> normalizedEntry = legacyToNormalized
                 .toNormalized(legacyEntry);
         LOG.trace("Serialization of {}, Legacy Representation: {}, Normalized Representation: {}", binding,
                 legacyEntry, normalizedEntry);
@@ -98,8 +102,8 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
                 if (child instanceof AugmentationNode) {
                     ImmutableList<PathArgument> childArgs = ImmutableList.<PathArgument> builder()
                             .addAll(normalizedEntry.getKey().getPathArguments()).add(child.getIdentifier()).build();
-                    org.opendaylight.yangtools.yang.data.api.InstanceIdentifier childPath = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.create(
-                            childArgs);
+                    org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier childPath = org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier
+                            .create(childArgs);
                     return toDOMEntry(childPath, child);
                 }
             }
@@ -119,8 +123,8 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
      *
      */
     public Optional<InstanceIdentifier<? extends DataObject>> toBinding(
-            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
-            throws DeserializationException {
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+                    throws DeserializationException {
 
         PathArgument lastArgument = Iterables.getLast(normalized.getPathArguments());
         // Used instance-identifier codec do not support serialization of last
@@ -136,8 +140,8 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
     }
 
     private Optional<InstanceIdentifier<? extends DataObject>> toBindingAugmented(
-            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
-            throws DeserializationException {
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+                    throws DeserializationException {
         Optional<InstanceIdentifier<? extends DataObject>> potential = toBindingImpl(normalized);
         // Shorthand check, if codec already supports deserialization
         // of AugmentationIdentifier we will return
@@ -154,9 +158,7 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         // 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.getPathArguments()).add(new NodeIdentifier(child))
-                            .build());
+            org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier childPath = normalized.node(child);
             try {
                 if (isNotRepresentable(childPath)) {
                     LOG.trace("Path {} is not BI-representable, skipping it", childPath);
@@ -188,9 +190,9 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
     }
 
     private Optional<InstanceIdentifier<? extends DataObject>> toBindingImpl(
-            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
-            throws DeserializationException {
-        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath;
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+                    throws DeserializationException {
+        org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier legacyPath;
 
         try {
             if (isNotRepresentable(normalized)) {
@@ -205,21 +207,21 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         return Optional.<InstanceIdentifier<? extends DataObject>> of(bindingToLegacy.fromDataDom(legacyPath));
     }
 
-    private boolean isNotRepresentable(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
+    private boolean isNotRepresentable(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
             throws DataNormalizationException {
         DataNormalizationOperation<?> op = findNormalizationOperation(normalized);
-        ifop.isMixin() && op.getIdentifier() instanceof NodeIdentifier) {
+        if (op.isMixin() && op.getIdentifier() instanceof NodeIdentifier) {
             return true;
         }
-        if(op.isLeaf()) {
+        if (op.isLeaf()) {
             return true;
         }
         return false;
     }
 
     private DataNormalizationOperation<?> findNormalizationOperation(
-            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized)
-            throws DataNormalizationException {
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized)
+                    throws DataNormalizationException {
         DataNormalizationOperation<?> current = legacyToNormalized.getRootOperation();
         for (PathArgument arg : normalized.getPathArguments()) {
             current = current.getChild(arg);
@@ -234,11 +236,10 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
                 key, value);
     }
 
-    private static final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>> toDOMEntry(
-            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier key,
-            final NormalizedNode<?, ?> value) {
-        return new SimpleEntry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, NormalizedNode<?, ?>>(
-                key, value);
+    private static final Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>> toDOMEntry(
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier key, final NormalizedNode<?, ?> value) {
+        return new SimpleEntry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, NormalizedNode<?, ?>>(key,
+                value);
     }
 
     public DataObject toBinding(final InstanceIdentifier<?> path, final NormalizedNode<?, ?> normalizedNode)
@@ -263,8 +264,8 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
     }
 
     public Optional<Entry<org.opendaylight.yangtools.yang.binding.InstanceIdentifier<? extends DataObject>, DataObject>> toBinding(
-            final Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized)
-            throws DeserializationException {
+            final Entry<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, ? extends NormalizedNode<?, ?>> normalized)
+                    throws DeserializationException {
         Optional<InstanceIdentifier<? extends DataObject>> potentialPath = toBinding(normalized.getKey());
         if (potentialPath.isPresent()) {
             InstanceIdentifier<? extends DataObject> bindingPath = potentialPath.get();
@@ -283,35 +284,162 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         legacyToNormalized = new DataNormalizer(arg0);
     }
 
-    private org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toNormalizedAugmented(
+    private org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalizedAugmented(
             final InstanceIdentifier<?> augPath) {
-        org.opendaylight.yangtools.yang.data.api.InstanceIdentifier processed = toNormalizedImpl(augPath);
+        org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier processed = toNormalizedImpl(augPath);
         // If used instance identifier codec added supports for deserialization
         // of last AugmentationIdentifier we will just reuse it
         if (isAugmentationIdentifier(processed)) {
             return processed;
         }
-        // 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)
-        // so, we scan augmentation for children add it to path
-        // and use original algorithm, then shorten it to last augmentation
-        for (@SuppressWarnings("rawtypes")
-        Class augChild : getAugmentationChildren(augPath.getTargetType())) {
+        Optional<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> additionalSerialized;
+        additionalSerialized = toNormalizedAugmentedUsingChildContainers(augPath, processed);
+
+        if (additionalSerialized.isPresent()) {
+            return additionalSerialized.get();
+        }
+        additionalSerialized = toNormalizedAugmentedUsingChildLeafs(augPath, processed);
+        if (additionalSerialized.isPresent()) {
+            return additionalSerialized.get();
+        }
+        throw new IllegalStateException("Unabled to construct augmentation identfier for " + augPath);
+    }
+
+    /**
+     * Tries to find correct augmentation identifier using children leafs
+     *
+     * This method uses normalized Instance Identifier of parent node to fetch
+     * schema and {@link BindingReflections#getModuleInfo(Class)} to learn about
+     * augmentation namespace, specificly, in which module it was defined.
+     *
+     * Then it uses it to filter all available augmentations for parent by
+     * module. After that it walks augmentations in particular module and
+     * pick-up first which at least one leaf name matches supplied augmentation.
+     * We could do this safely since YANG explicitly states that no any existing
+     * augmentations must differ in leaf fully qualified names.
+     *
+     *
+     * @param augPath
+     *            Binding Aware Path which ends with augment
+     * @param parentPath
+     *            Processed path
+     * @return
+     */
+    private Optional<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> toNormalizedAugmentedUsingChildLeafs(
+            final InstanceIdentifier<?> augPath,
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier parentPath) {
+        try {
+            DataNormalizationOperation<?> parentOp = legacyToNormalized.getOperation(parentPath);
+            if(!parentOp.getDataSchemaNode().isPresent()) {
+                return Optional.absent();
+            }
+            DataSchemaNode parentSchema = parentOp.getDataSchemaNode().get();
+            if (parentSchema instanceof AugmentationTarget) {
+                Set<AugmentationSchema> augmentations = ((AugmentationTarget) parentSchema).getAvailableAugmentations();
+                LOG.info("Augmentations for {}, {}", augPath, augmentations);
+                Optional<AugmentationSchema> schema = findAugmentation(augPath.getTargetType(), augmentations);
+                if (schema.isPresent()) {
+                    AugmentationIdentifier augmentationIdentifier = DataNormalizationOperation
+                            .augmentationIdentifierFrom(schema.get());
+                    return Optional.of(parentPath.node(augmentationIdentifier));
+                }
+            }
+        } catch (DataNormalizationException e) {
+            throw new IllegalArgumentException(e);
+        }
+        return Optional.absent();
+    }
+
+    /**
+     * Creates instance identifier for augmentation child, tries to serialize it
+     * Instance Identifier is then shortened to last augmentation.
+     *
+     * This is for situations, where underlying codec is implementing hydrogen
+     * style DOM APIs (which did not supported {@link AugmentationIdentifier}.)
+     *
+     * @param augPath
+     * @param parentPath
+     *            Path to parent node
+     * @return
+     */
+    @SuppressWarnings("rawtypes")
+    private Optional<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier> toNormalizedAugmentedUsingChildContainers(
+            final InstanceIdentifier<?> augPath,
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier parentPath) {
+        for (Class augChild : BindingReflections.getChildrenClasses(augPath.getTargetType())) {
             @SuppressWarnings("unchecked")
             InstanceIdentifier<?> childPath = augPath.child(augChild);
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized = toNormalizedImpl(childPath);
-            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier potentialDiscovered = shortenToLastAugmentation(normalized);
+            org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized = toNormalizedImpl(childPath);
+            org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier potentialDiscovered = shortenToLastAugmentation(
+                    normalized, parentPath);
             if (potentialDiscovered != null) {
-                return potentialDiscovered;
+                return Optional.of(potentialDiscovered);
+            }
+        }
+        return Optional.absent();
+    }
+
+    private Optional<AugmentationSchema> findAugmentation(final Class<?> targetType,
+            final Set<AugmentationSchema> augmentations) {
+        YangModuleInfo moduleInfo;
+        try {
+            moduleInfo = BindingReflections.getModuleInfo(targetType);
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+        Iterable<AugmentationSchema> filtered = filteredByModuleInfo(augmentations,
+                BindingReflections.getModuleQName(moduleInfo).getModule());
+        filtered.toString();
+        Set<String> targetTypeGetters = getYangModeledGetters(targetType);
+        for (AugmentationSchema schema : filtered) {
+            for (DataSchemaNode child : schema.getChildNodes()) {
+                String getterName = "get" + BindingMapping.getClassName(child.getQName());
+                if (targetTypeGetters.contains(getterName)) {
+                    return Optional.of(schema);
+                }
+            }
+        }
+        return Optional.absent();
+    }
+
+    private static Iterable<AugmentationSchema> filteredByModuleInfo(final Iterable<AugmentationSchema> augmentations,
+            final QNameModule module) {
+        return Iterables.filter(augmentations, new Predicate<AugmentationSchema>() {
+            @Override
+            public boolean apply(final AugmentationSchema schema) {
+                final Collection<DataSchemaNode> childNodes = schema.getChildNodes();
+                return !childNodes.isEmpty() && module.equals(Iterables.get(childNodes, 0).getQName().getModule());
+            }
+        });
+    }
+
+    public static final Set<String> getYangModeledGetters(final Class<?> targetType) {
+        HashSet<String> ret = new HashSet<String>();
+        for (Method method : targetType.getMethods()) {
+            if (isYangModeledGetter(method)) {
+                ret.add(method.getName());
             }
         }
-        return processed;
+        return ret;
+    }
+
+    /**
+     *
+     * Returns true if supplied method represent getter for YANG modeled value
+     *
+     * @param method
+     *            Method to be tested
+     * @return true if method represent getter for YANG Modeled value.
+     */
+    private static final boolean isYangModeledGetter(final Method method) {
+        return !method.getName().equals("getClass") && !method.getName().equals("getImplementedInterface")
+                && method.getName().startsWith("get") && method.getParameterTypes().length == 0;
     }
 
-    private org.opendaylight.yangtools.yang.data.api.InstanceIdentifier shortenToLastAugmentation(
-            final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized) {
+    private org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier shortenToLastAugmentation(
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized,
+            final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier parentPath) {
+        int parentSize = Iterables.size(parentPath.getPathArguments());
         int position = 0;
         int foundPosition = -1;
         for (PathArgument arg : normalized.getPathArguments()) {
@@ -320,9 +448,9 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
                 foundPosition = position;
             }
         }
-        if (foundPosition > 0) {
+        if (foundPosition > 0 && foundPosition > parentSize) {
             Iterable<PathArgument> shortened = Iterables.limit(normalized.getPathArguments(), foundPosition);
-            return org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.create(shortened);
+            return org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.create(shortened);
         }
         return null;
     }
@@ -340,71 +468,15 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         return InstanceIdentifier.create(Iterables.limit(binding.getPathArguments(), foundPosition));
     }
 
-    private org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toNormalizedImpl(
+    private org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier toNormalizedImpl(
             final InstanceIdentifier<? extends DataObject> binding) {
-        final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier legacyPath = bindingToLegacy
+        final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier legacyPath = bindingToLegacy
                 .toDataDom(binding);
-        final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalized = legacyToNormalized
+        final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier normalized = legacyToNormalized
                 .toNormalized(legacyPath);
         return normalized;
     }
 
-    @SuppressWarnings("unchecked")
-    private Iterable<Class<? extends DataObject>> getAugmentationChildren(final Class<?> targetType) {
-        List<Class<? extends DataObject>> ret = new LinkedList<>();
-        for (Method method : targetType.getMethods()) {
-            Class<?> entity = getYangModeledType(method);
-            if (entity != null) {
-                ret.add((Class<? extends DataObject>) entity);
-            }
-        }
-        return ret;
-    }
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    private Class<? extends DataObject> getYangModeledType(final Method method) {
-        if (method.getName().equals("getClass") || !method.getName().startsWith("get")
-                || method.getParameterTypes().length > 0) {
-            return null;
-        }
-
-        Class<?> returnType = method.getReturnType();
-        if (DataContainer.class.isAssignableFrom(returnType)) {
-            return (Class) returnType;
-        } else if (List.class.isAssignableFrom(returnType)) {
-            try {
-                return ClassLoaderUtils.withClassLoader(method.getDeclaringClass().getClassLoader(),
-                        new Supplier<Class>() {
-                            @Override
-                            public Class get() {
-                                Type listResult = ClassLoaderUtils.getFirstGenericParameter(method
-                                        .getGenericReturnType());
-                                if (listResult instanceof Class
-                                        && DataObject.class.isAssignableFrom((Class) listResult)) {
-                                    return (Class<?>) listResult;
-                                }
-                                return null;
-                            }
-
-                        });
-            } catch (Exception e) {
-                LOG.debug("Could not get YANG modeled entity for {}", method, e);
-                return null;
-            }
-
-        }
-        return null;
-    }
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    private static InstanceIdentifier<?> toWildcarded(final InstanceIdentifier<?> orig) {
-        List<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument> wildArgs = new LinkedList<>();
-        for (org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : orig.getPathArguments()) {
-            wildArgs.add(new Item(arg.getType()));
-        }
-        return InstanceIdentifier.create(wildArgs);
-    }
-
     private static boolean isAugmentation(final Class<? extends DataObject> type) {
         return Augmentation.class.isAssignableFrom(type);
     }
@@ -413,14 +485,14 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         return Augmentation.class.isAssignableFrom(potential.getTargetType());
     }
 
-    private boolean isAugmentationIdentifier(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier processed) {
+    private boolean isAugmentationIdentifier(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier processed) {
         return Iterables.getLast(processed.getPathArguments()) 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())) {
+        for (org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument arg : potential.getPathArguments()) {
+            if (isAugmentation(arg.getType())) {
                 count++;
             }
 
@@ -428,21 +500,22 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
         return count;
     }
 
-    private static int getAugmentationCount(final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier potential) {
+    private static int getAugmentationCount(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier potential) {
         int count = 0;
-        for(PathArgument arg : potential.getPathArguments()) {
-            if(arg instanceof AugmentationIdentifier) {
+        for (PathArgument arg : potential.getPathArguments()) {
+            if (arg instanceof AugmentationIdentifier) {
                 count++;
             }
         }
         return count;
     }
 
-    public Function<Optional<NormalizedNode<?, ?>>, Optional<DataObject>>  deserializeFunction(final InstanceIdentifier<?> path) {
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public <T extends DataObject> Function<Optional<NormalizedNode<?, ?>>, Optional<T>>  deserializeFunction(final InstanceIdentifier<T> path) {
         return new DeserializeFunction(this, path);
     }
 
-    private static class DeserializeFunction implements Function<Optional<NormalizedNode<?, ?>>, Optional<DataObject>> {
+    private static class DeserializeFunction<T extends DataObject> implements Function<Optional<NormalizedNode<?, ?>>, Optional<T>> {
 
         private final BindingToNormalizedNodeCodec codec;
         private final InstanceIdentifier<?> path;
@@ -453,9 +526,10 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
             this.path = Preconditions.checkNotNull(path, "Path must not be null");
         }
 
+        @SuppressWarnings("rawtypes")
         @Nullable
         @Override
-        public Optional<DataObject> apply(@Nullable final Optional<NormalizedNode<?, ?>> normalizedNode) {
+        public Optional apply(@Nullable final Optional<NormalizedNode<?, ?>> normalizedNode) {
             if (normalizedNode.isPresent()) {
                 final DataObject dataObject;
                 try {
@@ -472,4 +546,24 @@ public class BindingToNormalizedNodeCodec implements SchemaContextListener {
             return Optional.absent();
         }
     }
+
+    /**
+     * Returns an default object according to YANG schema for supplied path.
+     *
+     * @param path DOM Path
+     * @return Node with defaults set on.
+     */
+    public NormalizedNode<?, ?> getDefaultNodeFor(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier path) {
+        Iterator<PathArgument> iterator = path.getPathArguments().iterator();
+        DataNormalizationOperation<?> currentOp = legacyToNormalized.getRootOperation();
+        while (iterator.hasNext()) {
+            PathArgument currentArg = iterator.next();
+            try {
+                currentOp = currentOp.getChild(currentArg);
+            } catch (DataNormalizationException e) {
+                throw new IllegalArgumentException(String.format("Invalid child encountered in path %s", path), e);
+            }
+        }
+        return currentOp.createDefault(path.getLastPathArgument());
+    }
 }