Binding v2 runtime - codecs - modificators 41/59141/2
authorJakub Toth <jakub.toth@pantheon.tech>
Tue, 13 Jun 2017 09:54:00 +0000 (11:54 +0200)
committerMartin Ciglan <martin.ciglan@pantheon.tech>
Mon, 19 Jun 2017 10:26:47 +0000 (10:26 +0000)
Change-Id: Ifd0512bbcb2c6de7cf2d02feedc8976ddd325e61
Signed-off-by: Jakub Toth <jakub.toth@pantheon.tech>
(cherry picked from commit 54c8c2cb5d7aa515cdbcc7a2fd50ec8ab1504d36)

binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/modification/BindingStructuralType.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/modification/LazyDataTreeModification.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/modification/LazyTreeNodeModification.java [new file with mode: 0644]
binding2/mdsal-binding2-dom-codec/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/AbstractBindingRuntimeTest.java [moved from binding2/mdsal-binding2-dom-codec/src/main/test/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/AbstractBindingRuntimeTest.java with 100% similarity]
binding2/mdsal-binding2-dom-codec/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/NonCachingCodecTest.java [moved from binding2/mdsal-binding2-dom-codec/src/main/test/org/opendaylight/mdsal/binding/javav2/dom/codec/NonCachingCodecTest.java with 89% similarity]
binding2/mdsal-binding2-dom-codec/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/context/UnionValueOptionContextTest.java [moved from binding2/mdsal-binding2-dom-codec/src/main/test/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/context/UnionValueOptionContextTest.java with 100% similarity]
binding2/mdsal-binding2-dom-codec/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/value/EnumerationCodecTest.java [moved from binding2/mdsal-binding2-dom-codec/src/main/test/org/opendaylight/mdsal/binding/javav2/dom/codec/impl/value/EnumerationCodecTest.java with 100% similarity]
binding2/mdsal-binding2-dom-codec/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/codec/modification/LazyDataTreeModificationTest.java [new file with mode: 0644]

diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/modification/BindingStructuralType.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/modification/BindingStructuralType.java
new file mode 100644 (file)
index 0000000..2ffbc33
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.javav2.dom.codec.modification;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Optional;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
+
+/**
+ * Defines structural mapping of Normalized Node to Binding data addressable by Instance Identifier.
+ *
+ * <p>
+ * Not all binding data are addressable by instance identifier and there are some differences.
+ *
+ * <p>
+ * See {@link #NOT_ADDRESSABLE},{@link #INVISIBLE_CONTAINER},{@link #VISIBLE_CONTAINER} for more details.
+ */
+@Beta
+enum BindingStructuralType {
+
+    /**
+     * DOM Item is not addressable in Binding Instance Identifier, data is not lost, but are available only
+     * via parent object.
+     *
+     * <p>
+     * Such types of data are leaf-lists, leafs, list without keys or anyxml.
+     *
+     */
+    NOT_ADDRESSABLE,
+    /**
+     * Data container is addressable in NormalizedNode format, but in Binding it is not represented in
+     * Instance Identifier.
+     *
+     * <p>
+     * This are choice / case nodes.
+     *
+     * <p>
+     * This data is still accessible using parent object and their children are addressable.
+     *
+     */
+    INVISIBLE_CONTAINER,
+    /**
+     * Data container is addressable in NormalizedNode format, but in Binding it is not represented in
+     * Instance Identifier.
+     *
+     * <p>
+     * This are list nodes.
+     *
+     * <p>
+     * This data is still accessible using parent object and their children are addressable.
+     *
+     */
+    INVISIBLE_LIST,
+    /**
+     * Data container is addressable in Binding Instance Identifier format and also YangInstanceIdentifier
+     * format.
+     *
+     */
+    VISIBLE_CONTAINER,
+    /**
+     * Mapping algorithm was unable to detect type or was not updated after introduction of new NormalizedNode
+     * type.
+     */
+    UNKNOWN;
+
+    static BindingStructuralType from(final DataTreeCandidateNode domChildNode) {
+        final Optional<NormalizedNode<?, ?>> dataBased = domChildNode.getDataAfter().or(domChildNode.getDataBefore());
+        if (dataBased.isPresent()) {
+            return from(dataBased.get());
+        }
+        return from(domChildNode.getIdentifier());
+    }
+
+    private static BindingStructuralType from(final PathArgument identifier) {
+        if (identifier instanceof NodeIdentifierWithPredicates || identifier instanceof AugmentationIdentifier) {
+            return VISIBLE_CONTAINER;
+        }
+        if (identifier instanceof NodeWithValue) {
+            return NOT_ADDRESSABLE;
+        }
+        return UNKNOWN;
+    }
+
+    static BindingStructuralType from(final NormalizedNode<?, ?> data) {
+        if (isNotAddressable(data)) {
+            return NOT_ADDRESSABLE;
+        }
+        if (data instanceof MapNode) {
+            return INVISIBLE_LIST;
+        }
+        if (data instanceof ChoiceNode) {
+            return INVISIBLE_CONTAINER;
+        }
+        if (isVisibleContainer(data)) {
+            return VISIBLE_CONTAINER;
+        }
+        return UNKNOWN;
+    }
+
+    private static boolean isVisibleContainer(final NormalizedNode<?, ?> data) {
+        return data instanceof MapEntryNode || data instanceof ContainerNode || data instanceof AugmentationNode;
+    }
+
+    private static boolean isNotAddressable(final NormalizedNode<?, ?> normalizedNode) {
+        return normalizedNode instanceof LeafNode || normalizedNode instanceof AnyXmlNode
+                || normalizedNode instanceof LeafSetNode || normalizedNode instanceof LeafSetEntryNode;
+    }
+
+}
diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/modification/LazyDataTreeModification.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/modification/LazyDataTreeModification.java
new file mode 100644 (file)
index 0000000..d310714
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.javav2.dom.codec.modification;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map.Entry;
+import javax.annotation.Nonnull;
+import org.opendaylight.mdsal.binding.javav2.api.DataTreeIdentifier;
+import org.opendaylight.mdsal.binding.javav2.api.DataTreeModification;
+import org.opendaylight.mdsal.binding.javav2.api.TreeNodeModification;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.api.BindingTreeNodeCodec;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
+
+/**
+ * Lazily translated {@link DataTreeModification} based on {@link DataTreeCandidate}.
+ *
+ * <p>
+ * {@link DataTreeModification} represents Data tree change event, but whole tree is not translated or
+ * resolved eagerly, but only child nodes which are directly accessed by user of tree node modification.
+ *
+ */
+@Beta
+public class LazyDataTreeModification<T extends TreeNode> implements DataTreeModification<T> {
+
+    private final DataTreeIdentifier<T> path;
+    private final TreeNodeModification<T> rootNode;
+
+    private LazyDataTreeModification(final DataTreeIdentifier<T> path, final TreeNodeModification<T> modification) {
+        this.path = Preconditions.checkNotNull(path);
+        this.rootNode = Preconditions.checkNotNull(modification);
+    }
+
+    @Nonnull
+    @Override
+    public TreeNodeModification<T> getRootNode() {
+        return rootNode;
+    }
+
+    @Nonnull
+    @Override
+    public DataTreeIdentifier<T> getRootPath() {
+        return path;
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private static <T extends TreeNode> DataTreeModification<T> create(final BindingToNormalizedNodeCodec codec,
+            final DataTreeCandidate domChange, final LogicalDatastoreType datastoreType) {
+        final Entry<InstanceIdentifier<?>, BindingTreeNodeCodec<?>> codecCtx =
+                codec.getSubtreeCodec(domChange.getRootPath());
+        final DataTreeIdentifier<?> path = DataTreeIdentifier.create(datastoreType, codecCtx.getKey());
+        final TreeNodeModification<?> modification =
+                LazyTreeNodeModification.create(codecCtx.getValue(), domChange.getRootNode());
+        return new LazyDataTreeModification(path, modification);
+    }
+
+    /**
+     * Create instance of Binding date tree modification according to DOM candidate of changes.
+     *
+     * @param codec
+     *            - codec for modificated data
+     * @param candidate
+     *            - changted DOM data
+     * @return modificated data tree
+     */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static <T extends TreeNode> DataTreeModification<T> create(final BindingToNormalizedNodeCodec codec,
+            final DOMDataTreeCandidate candidate) {
+        final Entry<InstanceIdentifier<?>, BindingTreeNodeCodec<?>> codecCtx =
+                codec.getSubtreeCodec(candidate.getRootPath().getRootIdentifier());
+        final DataTreeIdentifier<?> path =
+                DataTreeIdentifier.create(candidate.getRootPath().getDatastoreType(), codecCtx.getKey());
+        final TreeNodeModification<?> modification =
+                LazyTreeNodeModification.create(codecCtx.getValue(), candidate.getRootNode());
+        return new LazyDataTreeModification(path, modification);
+    }
+
+    /**
+     * DOM data changes to new Binding data.
+     *
+     * @param codec
+     *            - Binding to DOM codec
+     * @param domChanges
+     *            - DOM data changes
+     * @param datastoreType
+     *            - datastore type
+     * @return collection of new Binding data according to DOM data changes
+     */
+    public static <T extends TreeNode> Collection<DataTreeModification<T>> from(
+            final BindingToNormalizedNodeCodec codec, final Collection<DataTreeCandidate> domChanges,
+            final LogicalDatastoreType datastoreType) {
+        final List<DataTreeModification<T>> result = new ArrayList<>(domChanges.size());
+        for (final DataTreeCandidate domChange : domChanges) {
+            result.add(LazyDataTreeModification.create(codec, domChange, datastoreType));
+        }
+        return result;
+    }
+
+}
+
diff --git a/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/modification/LazyTreeNodeModification.java b/binding2/mdsal-binding2-dom-codec/src/main/java/org/opendaylight/mdsal/binding/javav2/dom/codec/modification/LazyTreeNodeModification.java
new file mode 100644 (file)
index 0000000..77a32c2
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.javav2.dom.codec.modification;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.mdsal.binding.javav2.api.TreeNodeModification;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.api.BindingTreeNodeCodec;
+import org.opendaylight.mdsal.binding.javav2.spec.base.IdentifiableItem;
+import org.opendaylight.mdsal.binding.javav2.spec.base.Item;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeArgument;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.mdsal.binding.javav2.spec.structural.Augmentation;
+import org.opendaylight.mdsal.binding.javav2.spec.structural.TreeChildNode;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Lazily translated {@link TreeNodeModification} based on {@link DataTreeCandidateNode}.
+ *
+ * <p>
+ * {@link LazyTreeNodeModification} represents Data tree change event, but whole tree is not translated or
+ * resolved eagerly, but only child nodes which are directly accessed by user of tree node modification.
+ *
+ * @param <T>
+ *            Type of Binding Tree Node
+ */
+@Beta
+final class LazyTreeNodeModification<T extends TreeNode> implements TreeNodeModification<T> {
+
+    private static final Logger LOG = LoggerFactory.getLogger(LazyTreeNodeModification.class);
+
+    private final BindingTreeNodeCodec<T> codec;
+    private final DataTreeCandidateNode domData;
+    private final TreeArgument<?> identifier;
+    private Collection<TreeNodeModification<? extends TreeNode>> childNodesCache;
+
+    private LazyTreeNodeModification(final BindingTreeNodeCodec<T> codec, final DataTreeCandidateNode domData) {
+        this.codec = Preconditions.checkNotNull(codec);
+        this.domData = Preconditions.checkNotNull(domData);
+        this.identifier = codec.deserializePathArgument(domData.getIdentifier());
+    }
+
+    static <T extends TreeNode> TreeNodeModification<T> create(final BindingTreeNodeCodec<T> codec,
+            final DataTreeCandidateNode domData) {
+        return new LazyTreeNodeModification<>(codec, domData);
+    }
+
+    private static Collection<TreeNodeModification<? extends TreeNode>> from(final BindingTreeNodeCodec<?> parentCodec,
+            final Collection<DataTreeCandidateNode> domChildNodes) {
+        final List<TreeNodeModification<? extends TreeNode>> result = new ArrayList<>(domChildNodes.size());
+        populateList(result, parentCodec, domChildNodes);
+        return result;
+    }
+
+    private static void populateList(final List<TreeNodeModification<? extends TreeNode>> result,
+            final BindingTreeNodeCodec<?> parentCodec, final Collection<DataTreeCandidateNode> domChildNodes) {
+        for (final DataTreeCandidateNode domChildNode : domChildNodes) {
+            final BindingStructuralType type = BindingStructuralType.from(domChildNode);
+            if (type != BindingStructuralType.NOT_ADDRESSABLE) {
+                /*
+                 * Even if type is UNKNOWN, from perspective of BindingStructuralType we try to load codec for
+                 * it. We will use that type to further specify debug log.
+                 */
+                try {
+                    final BindingTreeNodeCodec<?> childCodec =
+                            parentCodec.yangPathArgumentChild(domChildNode.getIdentifier());
+                    populateList(result, type, childCodec, domChildNode);
+                } catch (final IllegalArgumentException e) {
+                    if (type == BindingStructuralType.UNKNOWN) {
+                        LOG.debug("Unable to deserialize unknown DOM node {}", domChildNode, e);
+                    } else {
+                        LOG.debug("Binding representation for DOM node {} was not found", domChildNode, e);
+                    }
+                }
+            }
+        }
+    }
+
+    private static void populateList(final List<TreeNodeModification<? extends TreeNode>> result,
+            final BindingStructuralType type, final BindingTreeNodeCodec<?> childCodec,
+            final DataTreeCandidateNode domChildNode) {
+        switch (type) {
+            case INVISIBLE_LIST:
+                // We use parent codec intentionally.
+                populateListWithSingleCodec(result, childCodec, domChildNode.getChildNodes());
+                break;
+            case INVISIBLE_CONTAINER:
+                populateList(result, childCodec, domChildNode.getChildNodes());
+                break;
+            case UNKNOWN:
+            case VISIBLE_CONTAINER:
+                result.add(create(childCodec, domChildNode));
+                break;
+            default:
+        }
+    }
+
+    private static void populateListWithSingleCodec(final List<TreeNodeModification<? extends TreeNode>> result,
+            final BindingTreeNodeCodec<?> codec, final Collection<DataTreeCandidateNode> childNodes) {
+        for (final DataTreeCandidateNode child : childNodes) {
+            result.add(create(codec, child));
+        }
+    }
+
+    @Nullable
+    @Override
+    public T getDataBefore() {
+        return deserialize(domData.getDataBefore());
+    }
+
+    @Nullable
+    @Override
+    public T getDataAfter() {
+        return deserialize(domData.getDataAfter());
+    }
+
+    @Nonnull
+    @Override
+    public Class<T> getDataType() {
+        return codec.getBindingClass();
+    }
+
+    @Nonnull
+    @Override
+    public TreeArgument<?> getIdentifier() {
+        return identifier;
+    }
+
+    @Nonnull
+    @Override
+    public TreeNodeModification.ModificationType getModificationType() {
+        switch (domData.getModificationType()) {
+            case APPEARED:
+            case WRITE:
+                return TreeNodeModification.ModificationType.WRITE;
+            case SUBTREE_MODIFIED:
+                return TreeNodeModification.ModificationType.SUBTREE_MODIFIED;
+            case DISAPPEARED:
+            case DELETE:
+                return TreeNodeModification.ModificationType.DELETE;
+
+            default:
+                // TODO: Should we lie about modification type instead of exception?
+                throw new IllegalStateException("Unsupported DOM Modification type " + domData.getModificationType());
+        }
+    }
+
+    @Nonnull
+    @Override
+    public Collection<TreeNodeModification<? extends TreeNode>> getModifiedChildren() {
+        if (childNodesCache == null) {
+            childNodesCache = from(codec, domData.getChildNodes());
+        }
+        return childNodesCache;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <C extends TreeChildNode<? super T, ?>> Collection<TreeNodeModification<C>>
+            getModifiedChildren(@Nonnull final Class<C> childType) {
+        final List<TreeNodeModification<C>> children = new ArrayList<>();
+        for (final TreeNodeModification<? extends TreeNode> potential : getModifiedChildren()) {
+            if (childType.isAssignableFrom(potential.getDataType())) {
+                children.add((TreeNodeModification<C>) potential);
+            }
+        }
+        return children;
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Nullable
+    @Override
+    public TreeNodeModification<? extends TreeNode> getModifiedChild(final TreeArgument childArgument) {
+        final List<YangInstanceIdentifier.PathArgument> domArgumentList = new ArrayList<>();
+        final BindingTreeNodeCodec<?> childCodec = codec.bindingPathArgumentChild(childArgument, domArgumentList);
+        final Iterator<YangInstanceIdentifier.PathArgument> toEnter = domArgumentList.iterator();
+        DataTreeCandidateNode current = domData;
+        while (toEnter.hasNext() && current != null) {
+            current = current.getModifiedChild(toEnter.next());
+        }
+        if (current != null) {
+            return create(childCodec, current);
+        }
+        return null;
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Override
+    public <C extends IdentifiableItem<T, K> & TreeChildNode<? super T, ?>, K extends IdentifiableItem<T, K>>
+            TreeNodeModification<C>
+            getModifiedChildListItem(@Nonnull final Class<C> listItem, @Nonnull final K listKey) {
+        return (TreeNodeModification) getModifiedChild(new IdentifiableItem(listItem, listKey));
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Nullable
+    @Override
+    public <C extends TreeChildNode<? super T, ?>> TreeNodeModification<C>
+            getModifiedChildContainer(@Nonnull final Class<C> child) {
+        return (TreeNodeModification<C>) getModifiedChild(new Item(child));
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Nullable
+    @Override
+    public <C extends Augmentation<T> & TreeNode> TreeNodeModification<C>
+            getModifiedAugmentation(@Nonnull final Class<C> augmentation) {
+        return (TreeNodeModification<C>) getModifiedChild(new Item(augmentation));
+    }
+
+    private T deserialize(final Optional<NormalizedNode<?, ?>> dataAfter) {
+        if (dataAfter.isPresent()) {
+            return codec.deserialize(dataAfter.get());
+        }
+        return null;
+    }
+}
+
@@ -5,7 +5,7 @@
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.mdsal.binding.javav2.dom.codec;
+package org.opendaylight.mdsal.binding.javav2.dom.codec.impl;
 
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -13,7 +13,6 @@ import static org.mockito.Mockito.verify;
 
 import org.junit.Test;
 import org.opendaylight.mdsal.binding.javav2.dom.codec.api.BindingNormalizedNodeCodec;
-import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.NonCachingCodec;
 
 public class NonCachingCodecTest {
 
diff --git a/binding2/mdsal-binding2-dom-codec/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/codec/modification/LazyDataTreeModificationTest.java b/binding2/mdsal-binding2-dom-codec/src/test/java/org/opendaylight/mdsal/binding/javav2/dom/codec/modification/LazyDataTreeModificationTest.java
new file mode 100644 (file)
index 0000000..34f2c98
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.mdsal.binding.javav2.dom.codec.modification;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Test;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.api.BindingTreeCodec;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.api.BindingTreeNodeCodec;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.mdsal.binding.javav2.dom.codec.impl.BindingToNormalizedNodeCodec;
+import org.opendaylight.mdsal.binding.javav2.generator.impl.GeneratedClassLoadingStrategy;
+import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeArgument;
+import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
+import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeCandidate;
+import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
+
+public class LazyDataTreeModificationTest {
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @Test
+    public void basicTest() throws Exception {
+        final BindingNormalizedNodeCodecRegistry registry = mock(BindingNormalizedNodeCodecRegistry.class);
+        final BindingToNormalizedNodeCodec codec =
+                new BindingToNormalizedNodeCodec(
+                        (GeneratedClassLoadingStrategy) GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy(),
+                        registry);
+        final DOMDataTreeCandidate domDataTreeCandidate = mock(DOMDataTreeCandidate.class);
+        final DOMDataTreeIdentifier domDataTreeIdentifier =
+                new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.EMPTY);
+        doReturn(InstanceIdentifier.create(TreeNode.class)).when(registry).fromYangInstanceIdentifier(any());
+        final BindingTreeCodec bindingCodecTree = mock(BindingTreeCodec.class);
+        final BindingTreeNodeCodec bindingCodecTreeNode = mock(BindingTreeNodeCodec.class);
+        doReturn(bindingCodecTreeNode).when(bindingCodecTree).getSubtreeCodec(any(InstanceIdentifier.class));
+        final PathArgument identifier =
+                new YangInstanceIdentifier.NodeIdentifier(QName.create("test", "2017-06-13", "test-l"));
+
+        doReturn(mock(TreeArgument.class)).when(bindingCodecTreeNode).deserializePathArgument(identifier);
+        doReturn(bindingCodecTree).when(registry).getCodecContext();
+        doReturn(domDataTreeIdentifier).when(domDataTreeCandidate).getRootPath();
+        final DataTreeCandidateNode dataTreeCandidate = mock(DataTreeCandidateNode.class);
+        doReturn(dataTreeCandidate).when(domDataTreeCandidate).getRootNode();
+        doReturn(identifier).when(dataTreeCandidate).getIdentifier();
+        assertNotNull(LazyDataTreeModification.create(codec, domDataTreeCandidate));
+    }
+}