X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-dom-adapter%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fdom%2Fadapter%2FLazyDataObjectModification.java;h=fc2c9366ec3705d30c238017154a378b5f88be4d;hb=e5ad7bce7fe6ffc268636656085a147906cefd7f;hp=e7046162c4ba1724a701e96b1a79ab82349c3a9e;hpb=eba291adf975802b00780ef36d904b4a142e18a6;p=mdsal.git
diff --git a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/LazyDataObjectModification.java b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/LazyDataObjectModification.java
index e7046162c4..fc2c9366ec 100644
--- a/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/LazyDataObjectModification.java
+++ b/binding/mdsal-binding-dom-adapter/src/main/java/org/opendaylight/mdsal/binding/dom/adapter/LazyDataObjectModification.java
@@ -7,21 +7,22 @@
*/
package org.opendaylight.mdsal.binding.dom.adapter;
-import org.opendaylight.mdsal.binding.api.DataObjectModification;
-
-import com.google.common.base.Optional;
+import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
-import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeNode;
+import java.util.Optional;
+import org.opendaylight.mdsal.binding.api.DataObjectModification;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.ChildOf;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.binding.Identifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -32,6 +33,7 @@ import org.slf4j.LoggerFactory;
/**
* Lazily translated {@link DataObjectModification} based on {@link DataTreeCandidateNode}.
*
+ *
* {@link LazyDataObjectModification} 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 data object modification.
@@ -40,12 +42,14 @@ import org.slf4j.LoggerFactory;
*/
final class LazyDataObjectModification implements DataObjectModification {
- private final static Logger LOG = LoggerFactory.getLogger(LazyDataObjectModification.class);
+ private static final Logger LOG = LoggerFactory.getLogger(LazyDataObjectModification.class);
private final BindingCodecTreeNode codec;
private final DataTreeCandidateNode domData;
private final PathArgument identifier;
- private Collection> childNodesCache;
+
+ private volatile Collection> childNodesCache;
+ private volatile ModificationType modificationType;
private LazyDataObjectModification(final BindingCodecTreeNode codec, final DataTreeCandidateNode domData) {
this.codec = Preconditions.checkNotNull(codec);
@@ -58,8 +62,8 @@ final class LazyDataObjectModification implements DataObje
return new LazyDataObjectModification<>(codec,domData);
}
- private static Collection> from(final BindingCodecTreeNode> parentCodec,
- final Collection domChildNodes) {
+ private static Collection> from(final BindingCodecTreeNode>
+ parentCodec, final Collection domChildNodes) {
final List> result = new ArrayList<>(domChildNodes.size());
populateList(result, parentCodec, domChildNodes);
return result;
@@ -104,8 +108,8 @@ final class LazyDataObjectModification implements DataObje
case UNKNOWN:
case VISIBLE_CONTAINER:
result.add(create(childCodec, domChildNode));
- default:
break;
+ default:
}
}
@@ -137,29 +141,81 @@ final class LazyDataObjectModification implements DataObje
}
@Override
- public DataObjectModification.ModificationType getModificationType() {
- switch(domData.getModificationType()) {
+ public ModificationType getModificationType() {
+ ModificationType localType = modificationType;
+ if (localType != null) {
+ return localType;
+ }
+
+ switch (domData.getModificationType()) {
case APPEARED:
case WRITE:
- return DataObjectModification.ModificationType.WRITE;
- case SUBTREE_MODIFIED:
- return DataObjectModification.ModificationType.SUBTREE_MODIFIED;
+ localType = ModificationType.WRITE;
+ break;
case DISAPPEARED:
case DELETE:
- return DataObjectModification.ModificationType.DELETE;
-
+ localType = ModificationType.DELETE;
+ break;
+ case SUBTREE_MODIFIED:
+ localType = resolveSubtreeModificationType();
+ break;
default:
// TODO: Should we lie about modification type instead of exception?
throw new IllegalStateException("Unsupported DOM Modification type " + domData.getModificationType());
}
+
+ modificationType = localType;
+ return localType;
+ }
+
+ private ModificationType resolveSubtreeModificationType() {
+ switch (codec.getChildAddressabilitySummary()) {
+ case ADDRESSABLE:
+ // All children are addressable, it is safe to report SUBTREE_MODIFIED
+ return ModificationType.SUBTREE_MODIFIED;
+ case UNADDRESSABLE:
+ // All children are non-addressable, report WRITE
+ return ModificationType.WRITE;
+ case MIXED:
+ // This case is not completely trivial, as we may have NOT_ADDRESSABLE nodes underneath us. If that
+ // is the case, we need to turn this modification into a WRITE operation, so that the user is able
+ // to observe those nodes being introduced. This is not efficient, but unfortunately unavoidable,
+ // as we cannot accurately represent such changes.
+ for (DataTreeCandidateNode child : domData.getChildNodes()) {
+ if (BindingStructuralType.recursiveFrom(child) == BindingStructuralType.NOT_ADDRESSABLE) {
+ // We have a non-addressable child, turn this modification into a write
+ return ModificationType.WRITE;
+ }
+ }
+
+ // No unaddressable children found, proceed in addressed mode
+ return ModificationType.SUBTREE_MODIFIED;
+ default:
+ throw new IllegalStateException("Unsupported child addressability summary "
+ + codec.getChildAddressabilitySummary());
+ }
}
@Override
public Collection> getModifiedChildren() {
- if (childNodesCache == null) {
- childNodesCache = from(codec, domData.getChildNodes());
+ Collection> local = childNodesCache;
+ if (local == null) {
+ childNodesCache = local = from(codec, domData.getChildNodes());
}
- return childNodesCache;
+ return local;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public > Collection>
+ getModifiedChildren(final Class childType) {
+ List> children = new ArrayList<>();
+ for (DataObjectModification extends DataObject> potential : getModifiedChildren()) {
+ if (childType.isAssignableFrom(potential.getDataType())) {
+ children.add((DataObjectModification) potential);
+ }
+ }
+ return children;
}
@Override
@@ -179,22 +235,27 @@ final class LazyDataObjectModification implements DataObje
@Override
@SuppressWarnings("unchecked")
- public & ChildOf super T>, K extends Identifier> DataObjectModification getModifiedChildListItem(
- final Class listItem, final K listKey) {
- return (DataObjectModification) getModifiedChild(new InstanceIdentifier.IdentifiableItem<>(listItem, listKey));
+ public & ChildOf super T>, K extends Identifier> DataObjectModification
+ getModifiedChildListItem(final Class listItem, final K listKey) {
+ return (DataObjectModification) getModifiedChild(IdentifiableItem.of(listItem, listKey));
}
@Override
@SuppressWarnings("unchecked")
public > DataObjectModification getModifiedChildContainer(final Class arg) {
- return (DataObjectModification) getModifiedChild(new InstanceIdentifier.Item<>(arg));
+ return (DataObjectModification) getModifiedChild(Item.of(arg));
}
@Override
@SuppressWarnings("unchecked")
public & DataObject> DataObjectModification getModifiedAugmentation(
final Class augmentation) {
- return (DataObjectModification) getModifiedChild(new InstanceIdentifier.Item<>(augmentation));
+ return (DataObjectModification) getModifiedChild(Item.of(augmentation));
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("identifier", identifier).add("domData", domData).toString();
}
private T deserialize(final Optional> dataAfter) {