Remove DOMDataTreeShard and all related interfaces
[mdsal.git] / dom / mdsal-dom-inmemory-datastore / src / main / java / org / opendaylight / mdsal / dom / store / inmemory / AbstractDOMShardTreeChangePublisher.java
diff --git a/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/AbstractDOMShardTreeChangePublisher.java b/dom/mdsal-dom-inmemory-datastore/src/main/java/org/opendaylight/mdsal/dom/store/inmemory/AbstractDOMShardTreeChangePublisher.java
deleted file mode 100644 (file)
index 62b27ee..0000000
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco Systems, Inc. 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.dom.store.inmemory;
-
-import static com.google.common.base.Preconditions.checkState;
-import static java.util.Objects.requireNonNull;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeListener;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
-import org.opendaylight.mdsal.dom.spi.AbstractDOMDataTreeChangeListenerRegistration;
-import org.opendaylight.mdsal.dom.spi.RegistrationTreeNode;
-import org.opendaylight.mdsal.dom.spi.shard.ChildShardContext;
-import org.opendaylight.mdsal.dom.spi.store.AbstractDOMStoreTreeChangePublisher;
-import org.opendaylight.mdsal.dom.spi.store.DOMStoreTreeChangePublisher;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-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.ContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
-import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNodes;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidates;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-abstract class AbstractDOMShardTreeChangePublisher extends AbstractDOMStoreTreeChangePublisher {
-
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractDOMShardTreeChangePublisher.class);
-
-    private final YangInstanceIdentifier shardPath;
-    private final Map<DOMDataTreeIdentifier, ChildShardContext> childShards;
-    private final DataTree dataTree;
-
-    protected AbstractDOMShardTreeChangePublisher(final DataTree dataTree,
-            final YangInstanceIdentifier shardPath, final Map<DOMDataTreeIdentifier, ChildShardContext> childShards) {
-        this.dataTree = requireNonNull(dataTree);
-        this.shardPath = requireNonNull(shardPath);
-        this.childShards = requireNonNull(childShards);
-    }
-
-    @Override
-    public <L extends DOMDataTreeChangeListener> AbstractDOMDataTreeChangeListenerRegistration<L>
-            registerTreeChangeListener(final YangInstanceIdentifier path, final L listener) {
-        takeLock();
-        try {
-            return setupListenerContext(path, listener);
-        } finally {
-            releaseLock();
-        }
-    }
-
-    private <L extends DOMDataTreeChangeListener> AbstractDOMDataTreeChangeListenerRegistration<L>
-            setupListenerContext(final YangInstanceIdentifier listenerPath, final L listener) {
-        // we need to register the listener registration path based on the shards root
-        // we have to strip the shard path from the listener path and then register
-        YangInstanceIdentifier strippedIdentifier = listenerPath;
-        if (!shardPath.isEmpty()) {
-            strippedIdentifier = YangInstanceIdentifier.create(stripShardPath(listenerPath));
-        }
-
-        final DOMDataTreeListenerWithSubshards subshardListener =
-                new DOMDataTreeListenerWithSubshards(dataTree, strippedIdentifier, listener);
-        final AbstractDOMDataTreeChangeListenerRegistration<L> reg =
-                setupContextWithoutSubshards(strippedIdentifier, subshardListener);
-
-        for (final ChildShardContext maybeAffected : childShards.values()) {
-            if (listenerPath.contains(maybeAffected.getPrefix().getRootIdentifier())) {
-                // consumer has initialDataChangeEvent subshard somewhere on lower level
-                // register to the notification manager with snapshot and forward child notifications to parent
-                LOG.debug("Adding new subshard{{}} to listener at {}", maybeAffected.getPrefix(), listenerPath);
-                subshardListener.addSubshard(maybeAffected);
-            } else if (maybeAffected.getPrefix().getRootIdentifier().contains(listenerPath)) {
-                // bind path is inside subshard
-                // TODO can this happen? seems like in ShardedDOMDataTree we are
-                // already registering to the lowest shard possible
-                throw new UnsupportedOperationException("Listener should be registered directly "
-                        + "into initialDataChangeEvent subshard");
-            }
-        }
-
-        initialDataChangeEvent(listenerPath, listener);
-
-        return reg;
-    }
-
-    private <L extends DOMDataTreeChangeListener> void initialDataChangeEvent(
-            final YangInstanceIdentifier listenerPath, final L listener) {
-        // FIXME Add support for wildcard listeners
-        final Optional<NormalizedNode<?, ?>> preExistingData = dataTree.takeSnapshot()
-                .readNode(YangInstanceIdentifier.create(stripShardPath(listenerPath)));
-        final DataTreeCandidate initialCandidate;
-
-        if (preExistingData.isPresent()) {
-            final NormalizedNode<?, ?> data = preExistingData.get();
-            checkState(data instanceof DataContainerNode, "Expected DataContainer node, but was {}", data.getClass());
-            // if we are listening on root of some shard we still get
-            // empty normalized node, root is always present
-            if (((DataContainerNode<?>) data).getValue().isEmpty()) {
-                initialCandidate = DataTreeCandidates.newDataTreeCandidate(listenerPath,
-                    DataTreeCandidateNodes.empty(data.getIdentifier()));
-            } else {
-                initialCandidate = DataTreeCandidates.fromNormalizedNode(listenerPath,
-                    translateRootShardIdentifierToListenerPath(listenerPath, preExistingData.get()));
-            }
-        } else {
-            initialCandidate = DataTreeCandidates.newDataTreeCandidate(listenerPath,
-                DataTreeCandidateNodes.empty(listenerPath.getLastPathArgument()));
-        }
-
-        listener.onDataTreeChanged(Collections.singleton(initialCandidate));
-    }
-
-    private static NormalizedNode<?, ?> translateRootShardIdentifierToListenerPath(
-            final YangInstanceIdentifier listenerPath, final NormalizedNode<?, ?> node) {
-        if (listenerPath.isEmpty()) {
-            return node;
-        }
-
-        final NormalizedNodeBuilder nodeBuilder;
-        if (node instanceof ContainerNode) {
-            nodeBuilder = ImmutableContainerNodeBuilder.create().withValue(((ContainerNode) node).getValue());
-        } else if (node instanceof MapEntryNode) {
-            nodeBuilder = ImmutableMapEntryNodeBuilder.create().withValue(((MapEntryNode) node).getValue());
-        } else {
-            throw new IllegalArgumentException("Expected ContainerNode or MapEntryNode, but was " + node.getClass());
-        }
-        nodeBuilder.withNodeIdentifier(listenerPath.getLastPathArgument());
-        return nodeBuilder.build();
-    }
-
-    private <L extends DOMDataTreeChangeListener> AbstractDOMDataTreeChangeListenerRegistration<L>
-            setupContextWithoutSubshards(final YangInstanceIdentifier listenerPath,
-                    final DOMDataTreeListenerWithSubshards listener) {
-        LOG.debug("Registering root listener at {}", listenerPath);
-        final RegistrationTreeNode<AbstractDOMDataTreeChangeListenerRegistration<?>> node =
-                findNodeFor(listenerPath.getPathArguments());
-        @SuppressWarnings("unchecked")
-        final var registration = new AbstractDOMDataTreeChangeListenerRegistration<>((L) listener) {
-            @Override
-            protected void removeRegistration() {
-                listener.close();
-                AbstractDOMShardTreeChangePublisher.this.removeRegistration(node, this);
-                registrationRemoved(this);
-            }
-        };
-        addRegistration(node, registration);
-        return registration;
-    }
-
-    private Iterable<PathArgument> stripShardPath(final YangInstanceIdentifier listenerPath) {
-        if (shardPath.isEmpty()) {
-            return listenerPath.getPathArguments();
-        }
-
-        final List<PathArgument> listenerPathArgs = new ArrayList<>(listenerPath.getPathArguments());
-        final Iterator<PathArgument> shardIter = shardPath.getPathArguments().iterator();
-        final Iterator<PathArgument> listenerIter = listenerPathArgs.iterator();
-
-        while (shardIter.hasNext()) {
-            if (shardIter.next().equals(listenerIter.next())) {
-                listenerIter.remove();
-            } else {
-                break;
-            }
-        }
-
-        return listenerPathArgs;
-    }
-
-    private static final class DOMDataTreeListenerWithSubshards implements DOMDataTreeChangeListener {
-
-        private final DataTree dataTree;
-        private final YangInstanceIdentifier listenerPath;
-        private final DOMDataTreeChangeListener delegate;
-
-        private final Map<YangInstanceIdentifier, ListenerRegistration<DOMDataTreeChangeListener>> registrations =
-                new HashMap<>();
-
-        DOMDataTreeListenerWithSubshards(final DataTree dataTree, final YangInstanceIdentifier listenerPath,
-                final DOMDataTreeChangeListener delegate) {
-            this.dataTree = requireNonNull(dataTree);
-            this.listenerPath = requireNonNull(listenerPath);
-            this.delegate = requireNonNull(delegate);
-        }
-
-        @Override
-        public void onDataTreeChanged(final Collection<DataTreeCandidate> changes) {
-            LOG.debug("Received data changed {}", changes);
-            delegate.onDataTreeChanged(changes);
-        }
-
-        void onDataTreeChanged(final YangInstanceIdentifier rootPath, final Collection<DataTreeCandidate> changes) {
-            final List<DataTreeCandidate> newCandidates = changes.stream()
-                    .map(candidate -> DataTreeCandidates.newDataTreeCandidate(rootPath, candidate.getRootNode()))
-                    .collect(Collectors.toList());
-            delegate.onDataTreeChanged(Collections.singleton(applyChanges(newCandidates)));
-        }
-
-        void addSubshard(final ChildShardContext context) {
-            checkState(context.getShard() instanceof DOMStoreTreeChangePublisher,
-                    "All subshards that are initialDataChangeEvent part of ListenerContext need to be listenable");
-
-            final DOMStoreTreeChangePublisher listenableShard = (DOMStoreTreeChangePublisher) context.getShard();
-            // since this is going into subshard we want to listen for ALL changes in the subshard
-            registrations.put(context.getPrefix().getRootIdentifier(),
-                listenableShard.registerTreeChangeListener(
-                        context.getPrefix().getRootIdentifier(), changes -> onDataTreeChanged(
-                                context.getPrefix().getRootIdentifier(), changes)));
-        }
-
-        void close() {
-            for (final ListenerRegistration<DOMDataTreeChangeListener> registration : registrations.values()) {
-                registration.close();
-            }
-            registrations.clear();
-        }
-
-        private DataTreeCandidate applyChanges(final Collection<DataTreeCandidate> changes) {
-            final DataTreeModification modification = dataTree.takeSnapshot().newModification();
-            for (final DataTreeCandidate change : changes) {
-                DataTreeCandidates.applyToModification(modification, change);
-            }
-
-            modification.ready();
-            DataTreeCandidateNode modifiedChild;
-            try {
-                dataTree.validate(modification);
-                modifiedChild = dataTree.prepare(modification).getRootNode();
-            } catch (final DataValidationFailedException e) {
-                LOG.error("Validation failed for built modification", e);
-                throw new IllegalStateException("Notification validation failed", e);
-            }
-
-            // strip nodes we do not need since this listener doesn't have to be registered at the root of the DataTree
-            for (final PathArgument pathArgument : listenerPath.getPathArguments()) {
-                modifiedChild = modifiedChild.getModifiedChild(pathArgument).orElse(null);
-            }
-
-            if (modifiedChild == null) {
-                modifiedChild = DataTreeCandidateNodes.empty(listenerPath.getLastPathArgument());
-            }
-
-            return DataTreeCandidates.newDataTreeCandidate(listenerPath, modifiedChild);
-        }
-    }
-}
\ No newline at end of file