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=b030e0ede33fabc67e10da2228449b9e1caf104a;hb=bcd8ee2d680bfb8d01eb4191ce35803fdcec9931;hp=66f7548d924b90c028b8bdc3abfad705b2afcdd8;hpb=c77348ddc6ccebb90ef32b5e55f38e0997047f36;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 66f7548d92..b030e0ede3 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,289 +7,52 @@ */ package org.opendaylight.mdsal.binding.dom.adapter; -import static java.util.Objects.requireNonNull; -import static org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType.UNMODIFIED; - -import com.google.common.base.MoreObjects; -import java.util.ArrayList; +import com.google.common.base.MoreObjects.ToStringHelper; import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.Stream; 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.ChoiceIn; +import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode; 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.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.YangInstanceIdentifier.PathArgument; 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; +import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode; /** * 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. + * {@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. * * @param Type of Binding Data Object */ -final class LazyDataObjectModification implements DataObjectModification { - - private static final Logger LOG = LoggerFactory.getLogger(LazyDataObjectModification.class); - - private final BindingCodecTreeNode codec; - private final DataTreeCandidateNode domData; - private final PathArgument identifier; - - private volatile Collection> childNodesCache; - private volatile ModificationType modificationType; - - private LazyDataObjectModification(final BindingCodecTreeNode codec, final DataTreeCandidateNode domData) { - this.codec = requireNonNull(codec); - this.domData = requireNonNull(domData); - this.identifier = codec.deserializePathArgument(domData.getIdentifier()); - } - - static LazyDataObjectModification create(final BindingCodecTreeNode codec, - final DataTreeCandidateNode domData) { - return new LazyDataObjectModification<>(codec, domData); - } - - private static Collection> from(final BindingCodecTreeNode - parentCodec, final Collection domChildNodes) { - final List> result = new ArrayList<>(domChildNodes.size()); - populateList(result, parentCodec, domChildNodes); - return result; - } - - private static void populateList(final List> result, - final BindingCodecTreeNode parentCodec, final Collection domChildNodes) { - for (final DataTreeCandidateNode domChildNode : domChildNodes) { - if (domChildNode.getModificationType() != UNMODIFIED) { - 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 BindingCodecTreeNode 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> result, - final BindingStructuralType type, final BindingCodecTreeNode 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> result, - final BindingCodecTreeNode codec, final Collection childNodes) { - for (final DataTreeCandidateNode child : childNodes) { - if (child.getModificationType() != UNMODIFIED) { - result.add(create(codec, child)); - } - } - } - - @Override - public T getDataBefore() { - return deserialize(domData.getDataBefore()); - } - - @Override - public T getDataAfter() { - return deserialize(domData.getDataAfter()); - } - - @Override - public Class getDataType() { - return codec.getBindingClass(); - } - - @Override - public PathArgument getIdentifier() { - return identifier; +final class LazyDataObjectModification + extends AbstractDataObjectModification> { + LazyDataObjectModification(final BindingDataObjectCodecTreeNode codec, final DataTreeCandidateNode domData) { + super(domData, codec, codec.deserializePathArgument(domData.getIdentifier())); } @Override - public ModificationType getModificationType() { - ModificationType localType = modificationType; - if (localType != null) { - return localType; - } - - switch (domData.getModificationType()) { - case APPEARED: - case WRITE: - localType = ModificationType.WRITE; - break; - case DISAPPEARED: - case 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() { - Collection> local = childNodesCache; - if (local == null) { - childNodesCache = local = from(codec, domData.getChildNodes()); - } - return local; + Collection domChildNodes() { + return domData.getChildNodes(); } @Override - public > Collection> - getModifiedChildren(final Class childType) { - return streamModifiedChildren(childType).collect(Collectors.toList()); + org.opendaylight.yangtools.yang.data.tree.api.ModificationType domModificationType() { + return domData.getModificationType(); } @Override - public & DataObject, C extends ChildOf> - Collection> getModifiedChildren(final Class caseType, - final Class childType) { - return streamModifiedChildren(childType) - .filter(child -> caseType.equals(child.identifier.getCaseType().orElse(null))) - .collect(Collectors.toList()); - } - - @SuppressWarnings("unchecked") - private Stream> streamModifiedChildren( - final Class childType) { - return getModifiedChildren().stream() - .filter(child -> childType.isAssignableFrom(child.getDataType())) - .map(child -> (LazyDataObjectModification) child); + T deserialize(final NormalizedNode normalized) { + return codec.deserialize(normalized); } @Override - public DataObjectModification getModifiedChild(final PathArgument arg) { - final List domArgumentList = new ArrayList<>(); - final BindingCodecTreeNode childCodec = codec.bindingPathArgumentChild(arg, domArgumentList); - final Iterator toEnter = domArgumentList.iterator(); - DataTreeCandidateNode current = domData; - while (toEnter.hasNext() && current != null) { - current = current.getModifiedChild(toEnter.next()).orElse(null); - } - return current != null && current.getModificationType() != UNMODIFIED ? create(childCodec, current) : null; + DataTreeCandidateNode firstModifiedChild(final PathArgument arg) { + return domData.getModifiedChild(arg).orElse(null); } @Override - @SuppressWarnings("unchecked") - public & ChildOf, K extends Identifier> DataObjectModification - getModifiedChildListItem(final Class listItem, final K listKey) { - return (DataObjectModification) getModifiedChild(IdentifiableItem.of(listItem, listKey)); - } - - @Override - @SuppressWarnings("unchecked") - public & DataObject, C extends Identifiable & ChildOf, - K extends Identifier> DataObjectModification getModifiedChildListItem(final Class caseType, - final Class listItem, final K listKey) { - return (DataObjectModification) getModifiedChild(IdentifiableItem.of(caseType, listItem, listKey)); - } - - @Override - @SuppressWarnings("unchecked") - public > DataObjectModification getModifiedChildContainer(final Class child) { - return (DataObjectModification) getModifiedChild(Item.of(child)); - } - - @Override - @SuppressWarnings("unchecked") - public & DataObject, C extends ChildOf> DataObjectModification - getModifiedChildContainer(final Class caseType, final Class child) { - return (DataObjectModification) getModifiedChild(Item.of(caseType, child)); - } - - @Override - @SuppressWarnings("unchecked") - public & DataObject> DataObjectModification getModifiedAugmentation( - final Class 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) { - return dataAfter.map(codec::deserialize).orElse(null); + ToStringHelper addToStringAttributes(final ToStringHelper helper) { + return super.addToStringAttributes(helper).add("domData", domData); } }