Finish support for notifying BI data change listeners in backwards compatible broker.
Change-Id: I221a1e6937c8f9c493444afd0756e6c23fd4b18f
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
package org.opendaylight.controller.md.sal.dom.broker.impl.compat;
import org.opendaylight.controller.md.sal.common.api.RegistrationListener;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
-import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
import org.opendaylight.controller.md.sal.common.api.data.DataReader;
import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
-import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
import org.opendaylight.controller.sal.common.DataStoreIdentifier;
import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
import org.opendaylight.controller.sal.core.api.data.DataProviderService;
import org.opendaylight.controller.sal.core.api.data.DataValidator;
import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
-import org.opendaylight.yangtools.concepts.Delegator;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
public class BackwardsCompatibleDataBroker implements DataProviderService, SchemaContextListener {
- DOMDataBroker backingBroker;
- DataNormalizer normalizer;
- private final ListenerRegistry<DataChangeListener> fakeRegistry = ListenerRegistry.create();
-
+ private final DOMDataBroker backingBroker;
+ private DataNormalizer normalizer;
public BackwardsCompatibleDataBroker(final DOMDataBroker newBiDataImpl) {
backingBroker = newBiDataImpl;
@Override
public CompositeNode readConfigurationData(final InstanceIdentifier legacyPath) {
- BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
+ final BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
try {
return tx.readConfigurationData(legacyPath);
} finally {
@Override
public CompositeNode readOperationalData(final InstanceIdentifier legacyPath) {
- BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
+ final BackwardsCompatibleTransaction<?> tx = BackwardsCompatibleTransaction.readOnlyTransaction(backingBroker.newReadOnlyTransaction(),normalizer);
try {
return tx.readOperationalData(legacyPath);
} finally {
}
@Override
- public ListenerRegistration<DataChangeListener> registerDataChangeListener(final InstanceIdentifier path,
+ public ListenerRegistration<DataChangeListener> registerDataChangeListener(final InstanceIdentifier legacyPath,
final DataChangeListener listener) {
- return fakeRegistry .register(listener);
+ final InstanceIdentifier normalizedPath = normalizer.toNormalized(legacyPath);
+
+ final TranslatingListenerInvoker translatingCfgListener =
+ TranslatingListenerInvoker.createConfig(listener, normalizer);
+ translatingCfgListener.register(backingBroker, normalizedPath);
+
+ final TranslatingListenerInvoker translatingOpListener =
+ TranslatingListenerInvoker.createOperational(listener, normalizer);
+ translatingOpListener.register(backingBroker, normalizedPath);
+
+ return new DelegateListenerRegistration(translatingCfgListener, translatingOpListener, listener);
}
@Override
return null;
}
- // Obsolote functionality
+ // Obsolete functionality
@Override
public void addValidator(final DataStoreIdentifier store, final DataValidator validator) {
throw new UnsupportedOperationException("Data Reader contract is not supported.");
}
- private final class TranslatingListenerInvoker implements DOMDataChangeListener, Delegator<DataChangeListener> {
-
+ private static class DelegateListenerRegistration implements ListenerRegistration<DataChangeListener> {
+ private final TranslatingListenerInvoker translatingCfgListener;
+ private final TranslatingListenerInvoker translatingOpListener;
+ private final DataChangeListener listener;
- private DataChangeListener delegate;
+ public DelegateListenerRegistration(final TranslatingListenerInvoker translatingCfgListener, final TranslatingListenerInvoker translatingOpListener, final DataChangeListener listener) {
+ this.translatingCfgListener = translatingCfgListener;
+ this.translatingOpListener = translatingOpListener;
+ this.listener = listener;
+ }
@Override
- public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
-
- DataChangeEvent<InstanceIdentifier, CompositeNode> legacyChange = null;
- delegate.onDataChanged(legacyChange);
+ public void close() {
+ translatingCfgListener.close();
+ translatingOpListener.close();
}
@Override
- public DataChangeListener getDelegate() {
-
- return delegate;
+ public DataChangeListener getInstance() {
+ return listener;
}
-
-
}
-
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.controller.md.sal.dom.broker.impl.compat;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.collect.Maps;
+
+public abstract class TranslatingDataChangeEvent implements
+ DataChangeEvent<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> {
+
+ private TranslatingDataChangeEvent() {
+ }
+
+ public static DataChangeEvent<InstanceIdentifier, CompositeNode> createOperational(
+ final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change, final DataNormalizer normalizer) {
+ return new OperationalChangeEvent(change, normalizer);
+ }
+
+ public static DataChangeEvent<InstanceIdentifier, CompositeNode> createConfiguration(
+ final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change, final DataNormalizer normalizer) {
+ return new ConfigurationChangeEvent(change, normalizer);
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedOperationalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedConfigurationData() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedOperationalData() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalOperationalData() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public CompositeNode getOriginalConfigurationSubtree() {
+ return null;
+ }
+
+ @Override
+ public CompositeNode getOriginalOperationalSubtree() {
+ return null;
+ }
+
+ @Override
+ public CompositeNode getUpdatedConfigurationSubtree() {
+ return null;
+ }
+
+ @Override
+ public CompositeNode getUpdatedOperationalSubtree() {
+ return null;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private final static class OperationalChangeEvent extends TranslatingDataChangeEvent {
+
+ private final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> delegate;
+ private final DataNormalizer normalizer;
+ private Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedCache;
+
+ public OperationalChangeEvent(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change,
+ final DataNormalizer normalizer) {
+ this.delegate = change;
+ this.normalizer = normalizer;
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedOperationalData() {
+ return transformToLegacy(normalizer, delegate.getCreatedData());
+ }
+
+
+ @Override
+ public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedOperationalData() {
+ return delegate.getRemovedPaths();
+ }
+
+ @Override
+ public CompositeNode getOriginalOperationalSubtree() {
+ // first argument is unused
+ return normalizer.toLegacy(null, delegate.getOriginalSubtree());
+ }
+
+ @Override
+ public CompositeNode getUpdatedOperationalSubtree() {
+ // first argument is unused
+ return normalizer.toLegacy(null, delegate.getUpdatedSubtree());
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalOperationalData() {
+ return transformToLegacy(normalizer, delegate.getOriginalData());
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedOperationalData() {
+ if(updatedCache == null) {
+ final Map<InstanceIdentifier, CompositeNode> updated = transformToLegacy(normalizer, delegate.getUpdatedData());
+ final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> created = getCreatedConfigurationData();
+ final HashMap<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedComposite = new HashMap<>(created.size() + updated.size());
+ updatedComposite.putAll(created);
+ updatedComposite.putAll(updated);
+ updatedCache = Collections.unmodifiableMap(updatedComposite);
+ }
+ return updatedCache;
+ }
+
+ @Override
+ public String toString() {
+ return "OperationalChangeEvent [delegate=" + delegate + "]";
+ }
+
+ }
+
+ private static Map<InstanceIdentifier, CompositeNode> transformToLegacy(final DataNormalizer normalizer, final Map<InstanceIdentifier, ? extends NormalizedNode<?, ?>> nodes) {
+ final Map<InstanceIdentifier, CompositeNode> legacy = Maps.newHashMap();
+
+ for (final Map.Entry<InstanceIdentifier, ? extends NormalizedNode<?, ?>> entry : nodes.entrySet()) {
+ try {
+ legacy.put(normalizer.toLegacy(entry.getKey()), normalizer.toLegacy(entry.getKey(), entry.getValue()));
+ } catch (final DataNormalizationException e) {
+ throw new IllegalStateException("Unable to transform data change event to legacy format", e);
+ }
+ }
+ return legacy;
+ }
+
+ private final static class ConfigurationChangeEvent extends TranslatingDataChangeEvent {
+
+ private final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> delegate;
+ private final DataNormalizer normalizer;
+ private Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedCache;
+
+ public ConfigurationChangeEvent(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> change,
+ final DataNormalizer normalizer) {
+ this.delegate = change;
+ this.normalizer = normalizer;
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getCreatedConfigurationData() {
+ return transformToLegacy(normalizer, delegate.getCreatedData());
+ }
+
+
+ @Override
+ public Set<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier> getRemovedConfigurationData() {
+ return delegate.getRemovedPaths();
+ }
+
+ @Override
+ public CompositeNode getOriginalConfigurationSubtree() {
+ // first argument is unused
+ return normalizer.toLegacy(null, delegate.getOriginalSubtree());
+ }
+
+ @Override
+ public CompositeNode getUpdatedConfigurationSubtree() {
+ // first argument is unused
+ return normalizer.toLegacy(null, delegate.getUpdatedSubtree());
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getOriginalConfigurationData() {
+ return transformToLegacy(normalizer, delegate.getOriginalData());
+ }
+
+ @Override
+ public Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> getUpdatedConfigurationData() {
+ if(updatedCache == null) {
+ final Map<InstanceIdentifier, CompositeNode> updated = transformToLegacy(normalizer, delegate.getUpdatedData());
+ final Map<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> created = getCreatedConfigurationData();
+ final HashMap<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> updatedComposite = new HashMap<>(created.size() + updated.size());
+ updatedComposite.putAll(created);
+ updatedComposite.putAll(updated);
+ updatedCache = Collections.unmodifiableMap(updatedComposite);
+ }
+ return updatedCache;
+ }
+
+ @Override
+ public String toString() {
+ return "ConfigurationChangeEvent [delegate=" + delegate + "]";
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.controller.md.sal.dom.broker.impl.compat;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+abstract class TranslatingListenerInvoker implements AutoCloseable, DOMDataChangeListener, Delegator<DataChangeListener> {
+
+ private final DataChangeListener delegate;
+ private final DataNormalizer normalizer;
+ protected ListenerRegistration<DOMDataChangeListener> reg;
+
+ protected TranslatingListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
+ this.delegate = listener;
+ this.normalizer = normalizer;
+ }
+
+ static TranslatingListenerInvoker createConfig(final DataChangeListener listener, final DataNormalizer normalizer) {
+ return new TranslatingConfigListenerInvoker(listener, normalizer);
+ }
+
+ static TranslatingListenerInvoker createOperational(final DataChangeListener listener, final DataNormalizer normalizer) {
+ return new TranslatingOperationalListenerInvoker(listener, normalizer);
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
+ delegate.onDataChanged(getLegacyEvent(normalizer, normalizedChange));
+ }
+
+ abstract DataChangeEvent<InstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer,
+ final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange);
+
+ @Override
+ public DataChangeListener getDelegate() {
+ return delegate;
+ }
+
+ abstract void register(final DOMDataBroker backingBroker, final InstanceIdentifier normalizedPath);
+
+ @Override
+ public void close() {
+ if (reg != null) {
+ reg.close();
+ }
+ }
+
+ static final class TranslatingConfigListenerInvoker extends TranslatingListenerInvoker {
+
+ public TranslatingConfigListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
+ super(listener, normalizer);
+ }
+
+ DataChangeEvent<InstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer, final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
+ return TranslatingDataChangeEvent.createConfiguration(normalizedChange, normalizer);
+ }
+
+ @Override
+ void register(final DOMDataBroker backingBroker, final InstanceIdentifier normalizedPath) {
+ reg = backingBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, normalizedPath, this,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ }
+ }
+
+ static final class TranslatingOperationalListenerInvoker extends TranslatingListenerInvoker {
+
+ public TranslatingOperationalListenerInvoker(final DataChangeListener listener, final DataNormalizer normalizer) {
+ super(listener, normalizer);
+ }
+
+ DataChangeEvent<InstanceIdentifier, CompositeNode> getLegacyEvent(final DataNormalizer normalizer, final AsyncDataChangeEvent<InstanceIdentifier, NormalizedNode<?, ?>> normalizedChange) {
+ return TranslatingDataChangeEvent.createOperational(normalizedChange, normalizer);
+ }
+
+ @Override
+ void register(final DOMDataBroker backingBroker, final InstanceIdentifier normalizedPath) {
+ reg = backingBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, normalizedPath, this,
+ AsyncDataBroker.DataChangeScope.SUBTREE);
+ }
+ }
+
+}
import java.io.InputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
+import java.net.URI;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import org.opendaylight.controller.md.sal.common.api.data.DataChangeEvent;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
import org.opendaylight.controller.netconf.util.handler.ssh.authentication.LoginPassword;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.connect.netconf.InventoryUtils;
import org.opendaylight.controller.sal.connect.netconf.NetconfDevice;
import org.opendaylight.controller.sal.connect.netconf.NetconfDeviceListener;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
import org.opendaylight.protocol.framework.ReconnectStrategy;
import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
import org.opendaylight.protocol.framework.TimedReconnectStrategy;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.inventory.rev140108.NetconfNode;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.model.util.repo.AbstractCachingSchemaSourceProvider;
import org.opendaylight.yangtools.yang.model.util.repo.FilesystemSchemaCachingProvider;
import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;