X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-binding-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fmd%2Fsal%2Fbinding%2Fimpl%2FLazyDataObjectModification.java;fp=opendaylight%2Fmd-sal%2Fsal-binding-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fmd%2Fsal%2Fbinding%2Fimpl%2FLazyDataObjectModification.java;h=4c8eb9a594d9a303e035ca439796ff62a6dd3ad9;hb=73b138d9a09d44a760c92a64a53164a2fa6618f5;hp=35c320d30c97af746d85fa75fc0595f3470d0a52;hpb=b8716b003471f99e74609e34f761a053ff70b934;p=controller.git diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/LazyDataObjectModification.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/LazyDataObjectModification.java index 35c320d30c..4c8eb9a594 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/LazyDataObjectModification.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/LazyDataObjectModification.java @@ -14,6 +14,7 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; import org.opendaylight.controller.md.sal.binding.api.DataObjectModification; +import org.opendaylight.mdsal.binding.dom.adapter.BindingStructuralType; import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode; import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.ChildOf; @@ -44,7 +45,9 @@ final class LazyDataObjectModification implements DataObje 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); @@ -136,28 +139,68 @@ 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; } @Override