Implement md-sal datastore into netconf test-tool 04/34904/2
authorTomas Cere <tcere@cisco.com>
Thu, 18 Feb 2016 12:26:32 +0000 (13:26 +0100)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 24 Feb 2016 09:18:27 +0000 (09:18 +0000)
Port of:
https://git.opendaylight.org/gerrit/#/c/26094/

Change-Id: Ia20302e1d6f6cbe6d40628e2af3ad5f14c39f55e
Signed-off-by: Tomas Cere <tcere@cisco.com>
opendaylight/netconf/netconf-testtool/pom.xml
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/Main.java
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/MdsalOperationProvider.java [new file with mode: 0644]
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/NetconfDeviceSimulator.java
opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedOperationProvider.java [new file with mode: 0644]

index ec7c88bee6f0230fd936fb7c42516b536c2ba675..92feb9d4919468d0cd1418e6fcaa2c8cb699e0b8 100644 (file)
             <groupId>${project.groupId}</groupId>
             <artifactId>netty-config-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>sal-inmemory-datastore</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>mdsal-netconf-connector</artifactId>
+        </dependency>
 
     </dependencies>
 
index e273254e0ed3bc8520cdcaf910957b982958f3b9..a6bbe40286421a52d7c9015d489b004e70c2d217 100644 (file)
@@ -80,6 +80,9 @@ public final class Main {
         @Arg(dest = "notification-file")
         public File notificationFile;
 
+        @Arg(dest = "md-sal")
+        public boolean mdSal;
+
         static ArgumentParser getParser() {
             final ArgumentParser parser = ArgumentParsers.newArgumentParser("netconf testool");
 
@@ -149,6 +152,12 @@ public final class Main {
                     .help("Whether to use debug log level instead of INFO")
                     .dest("debug");
 
+            parser.addArgument("--md-sal")
+                    .type(Boolean.class)
+                    .setDefault(false)
+                    .help("Whether to use md-sal datastore instead of default simulated datastore.")
+                    .dest("md-sal");
+
             return parser;
         }
 
diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/MdsalOperationProvider.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/MdsalOperationProvider.java
new file mode 100644 (file)
index 0000000..b487495
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2015 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.netconf.test.tool;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.util.concurrent.MoreExecutors;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.controller.md.sal.dom.broker.impl.SerializedDOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStoreFactory;
+import org.opendaylight.controller.netconf.api.Capability;
+import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener;
+import org.opendaylight.controller.netconf.impl.SessionIdProvider;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.mdsal.connector.CurrentSchemaContext;
+import org.opendaylight.controller.netconf.mdsal.connector.TransactionProvider;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.Commit;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.DiscardChanges;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.EditConfig;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.Lock;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.Unlock;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.get.Get;
+import org.opendaylight.controller.netconf.mdsal.connector.ops.get.GetConfig;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.spi.data.DOMStore;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.Yang;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class MdsalOperationProvider implements NetconfOperationServiceFactory {
+
+    private static final Logger LOG = LoggerFactory
+            .getLogger(MdsalOperationProvider.class);
+
+    private final Set<Capability> caps;
+    private final MdsalOperationService mdsalOperationService;
+
+    public MdsalOperationProvider(final SessionIdProvider idProvider,
+                                  final Set<Capability> caps,
+                                  final SchemaContext schemaContext) {
+        this.caps = caps;
+        mdsalOperationService = new MdsalOperationService(
+                idProvider.getCurrentSessionId(), schemaContext, caps);
+    }
+
+    @Override
+    public Set<Capability> getCapabilities() {
+        return caps;
+    }
+
+    @Override
+    public AutoCloseable registerCapabilityListener(
+            CapabilityListener listener) {
+        listener.onCapabilitiesAdded(caps);
+        return new AutoCloseable() {
+            @Override
+            public void close() throws Exception {
+            }
+        };
+    }
+
+    @Override
+    public NetconfOperationService createService(String netconfSessionIdForReporting) {
+        return mdsalOperationService;
+    }
+
+    static class MdsalOperationService implements NetconfOperationService {
+        private final long currentSessionId;
+        private final SchemaContext schemaContext;
+        private final Set<Capability> caps;
+
+        public MdsalOperationService(final long currentSessionId,
+                                     final SchemaContext schemaContext,
+                                     final Set<Capability> caps) {
+            this.currentSessionId = currentSessionId;
+            this.schemaContext = schemaContext;
+            this.caps = caps;
+        }
+
+        @Override
+        public Set<NetconfOperation> getNetconfOperations() {
+            final SchemaService schemaService = createSchemaService();
+
+            final DOMDataBroker db = createDataStore(schemaService);
+            TransactionProvider transactionProvider = new TransactionProvider(db, String.valueOf(currentSessionId));
+            CurrentSchemaContext currentSchemaContext = new CurrentSchemaContext(schemaService);
+
+            ContainerNode netconf = createNetconfState();
+
+            YangInstanceIdentifier yangInstanceIdentifier = YangInstanceIdentifier.builder().node(NetconfState.QNAME)
+                    .build();
+
+            final DOMDataWriteTransaction tx = db.newWriteOnlyTransaction();
+            tx.put(LogicalDatastoreType.OPERATIONAL, yangInstanceIdentifier, netconf);
+
+            try {
+                tx.submit().checkedGet();
+                LOG.debug("Netconf state updated successfully");
+            } catch (TransactionCommitFailedException e) {
+                LOG.warn("Unable to update netconf state", e);
+            }
+
+            final Get get = new Get(String.valueOf(currentSessionId), currentSchemaContext, transactionProvider);
+            final EditConfig editConfig = new EditConfig(String.valueOf(currentSessionId), currentSchemaContext,
+                    transactionProvider);
+            final GetConfig getConfig = new GetConfig(String.valueOf(currentSessionId), currentSchemaContext,
+                    transactionProvider);
+            final Commit commit = new Commit(String.valueOf(currentSessionId), transactionProvider);
+            final Lock lock = new Lock(String.valueOf(currentSessionId));
+            final Unlock unLock = new Unlock(String.valueOf(currentSessionId));
+            final DiscardChanges discardChanges = new DiscardChanges(String.valueOf(currentSessionId), transactionProvider);
+
+            return Sets.<NetconfOperation>newHashSet(get, getConfig,
+                    editConfig, commit, lock, unLock, discardChanges);
+        }
+
+        @Override
+        public void close() {
+        }
+
+        private ContainerNode createNetconfState() {
+            DummyMonitoringService monitor = new DummyMonitoringService(
+                    caps);
+
+            final QName identifier = QName.create(Schema.QNAME, "identifier");
+            final QName version = QName.create(Schema.QNAME, "version");
+            final QName format = QName.create(Schema.QNAME, "format");
+            final QName location = QName.create(Schema.QNAME, "location");
+            final QName namespace = QName.create(Schema.QNAME, "namespace");
+
+            CollectionNodeBuilder<MapEntryNode, MapNode> schemaMapEntryNodeMapNodeCollectionNodeBuilder = Builders
+                    .mapBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(Schema.QNAME));
+            LeafSetEntryNode locationLeafSetEntryNode = Builders.leafSetEntryBuilder().withNodeIdentifier(
+                    new YangInstanceIdentifier.NodeWithValue(location, "NETCONF")).withValue("NETCONF").build();
+
+            Map<QName, Object> keyValues = Maps.newHashMap();
+            for (final Schema schema : monitor.getSchemas().getSchema()) {
+                keyValues.put(identifier, schema.getIdentifier());
+                keyValues.put(version, schema.getVersion());
+                keyValues.put(format, Yang.QNAME);
+
+                MapEntryNode schemaMapEntryNode = Builders.mapEntryBuilder().withNodeIdentifier(
+                        new YangInstanceIdentifier.NodeIdentifierWithPredicates(Schema.QNAME, keyValues))
+                        .withChild(Builders.leafBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(
+                                identifier)).withValue(schema.getIdentifier()).build())
+                        .withChild(Builders.leafBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(
+                                version)).withValue(schema.getVersion()).build())
+                        .withChild(Builders.leafBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(
+                                format)).withValue(Yang.QNAME).build())
+                        .withChild(Builders.leafBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(
+                                namespace)).withValue(schema.getNamespace().getValue()).build())
+                        .withChild((DataContainerChild<?, ?>) Builders.leafSetBuilder().withNodeIdentifier(
+                                new YangInstanceIdentifier.NodeIdentifier(location))
+                                .withChild(locationLeafSetEntryNode).build())
+                        .build();
+
+                schemaMapEntryNodeMapNodeCollectionNodeBuilder.withChild(schemaMapEntryNode);
+            }
+
+            DataContainerChild<?, ?> schemaList = schemaMapEntryNodeMapNodeCollectionNodeBuilder.build();
+
+            ContainerNode schemasContainer = Builders.containerBuilder().withNodeIdentifier(
+                    new YangInstanceIdentifier.NodeIdentifier(Schemas.QNAME)).withChild(schemaList).build();
+            return (ContainerNode) Builders.containerBuilder().withNodeIdentifier(
+                    new YangInstanceIdentifier.NodeIdentifier(NetconfState.QNAME)).withChild(schemasContainer).build();
+        }
+
+        private DOMDataBroker createDataStore(SchemaService schemaService) {
+            final DOMStore operStore = InMemoryDOMDataStoreFactory
+                    .create("DOM-OPER", schemaService);
+            final DOMStore configStore = InMemoryDOMDataStoreFactory
+                    .create("DOM-CFG", schemaService);
+
+            ExecutorService listenableFutureExecutor = SpecialExecutors.newBlockingBoundedCachedThreadPool(
+                    16, 16, "CommitFutures");
+
+            final EnumMap<LogicalDatastoreType, DOMStore> datastores = new EnumMap<>(LogicalDatastoreType.class);
+            datastores.put(LogicalDatastoreType.CONFIGURATION, configStore);
+            datastores.put(LogicalDatastoreType.OPERATIONAL, operStore);
+
+            return new SerializedDOMDataBroker(datastores, MoreExecutors.listeningDecorator(listenableFutureExecutor));
+        }
+
+        private SchemaService createSchemaService() {
+            return new SchemaService() {
+
+                @Override
+                public void addModule(Module module) {
+                }
+
+                @Override
+                public void removeModule(Module module) {
+
+                }
+
+                @Override
+                public SchemaContext getSessionContext() {
+                    return schemaContext;
+                }
+
+                @Override
+                public SchemaContext getGlobalContext() {
+                    return schemaContext;
+                }
+
+                @Override
+                public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(
+                        final SchemaContextListener listener) {
+                    listener.onGlobalContextUpdated(getGlobalContext());
+                    return new ListenerRegistration<SchemaContextListener>() {
+                        @Override
+                        public void close() {
+
+                        }
+
+                        @Override
+                        public SchemaContextListener getInstance() {
+                            return listener;
+                        }
+                    };
+                }
+            };
+        }
+    }
+
+}
\ No newline at end of file
index 3476b11fbeaf6379c512ba8dbcc0ca3a3328330c..a833aab9c66ba29272ff8028d971fc0c42ada427 100644 (file)
@@ -56,7 +56,6 @@ import org.apache.sshd.server.PasswordAuthenticator;
 import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
 import org.apache.sshd.server.session.ServerSession;
 import org.opendaylight.controller.netconf.api.Capability;
-import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener;
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
@@ -64,24 +63,16 @@ import org.opendaylight.controller.netconf.impl.NetconfServerDispatcherImpl;
 import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
 import org.opendaylight.controller.netconf.impl.SessionIdProvider;
 import org.opendaylight.controller.netconf.impl.osgi.AggregatedNetconfOperationServiceFactory;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringActivator;
 import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOperationService;
 import org.opendaylight.controller.netconf.ssh.SshProxyServer;
 import org.opendaylight.controller.netconf.ssh.SshProxyServerConfiguration;
 import org.opendaylight.controller.netconf.ssh.SshProxyServerConfigurationBuilder;
-import org.opendaylight.controller.netconf.test.tool.rpc.DataList;
-import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedCommit;
-import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedCreateSubscription;
-import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedEditConfig;
-import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedGet;
-import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedGetConfig;
-import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedLock;
-import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedUnLock;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter;
 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
@@ -108,6 +99,7 @@ public class NetconfDeviceSimulator implements Closeable {
     private final List<SshProxyServer> sshWrappers = Lists.newArrayList();
     private final ScheduledExecutorService minaTimerExecutor;
     private final ExecutorService nioExecutor;
+    private SchemaContext schemaContext;
 
     private boolean sendFakeSchema = false;
 
@@ -125,7 +117,7 @@ public class NetconfDeviceSimulator implements Closeable {
         this.nioExecutor = nioExecutor;
     }
 
-    private NetconfServerDispatcherImpl createDispatcher(final Map<ModuleBuilder, String> moduleBuilders, final boolean exi, final int generateConfigsTimeout, final Optional<File> notificationsFile) {
+    private NetconfServerDispatcherImpl createDispatcher(final Map<ModuleBuilder, String> moduleBuilders, final boolean exi, final int generateConfigsTimeout, final Optional<File> notificationsFile, final boolean mdSal) {
 
         final Set<Capability> capabilities = Sets.newHashSet(Collections2.transform(moduleBuilders.keySet(), new Function<ModuleBuilder, Capability>() {
             @Override
@@ -142,14 +134,15 @@ public class NetconfDeviceSimulator implements Closeable {
         final SessionIdProvider idProvider = new SessionIdProvider();
 
         final AggregatedNetconfOperationServiceFactory aggregatedNetconfOperationServiceFactory = new AggregatedNetconfOperationServiceFactory();
-        final SimulatedOperationProvider simulatedOperationProvider = new SimulatedOperationProvider(idProvider, capabilities, notificationsFile);
+        final NetconfOperationServiceFactory operationProvider = mdSal ? new MdsalOperationProvider(idProvider, capabilities, schemaContext) :
+                new SimulatedOperationProvider(idProvider, capabilities, notificationsFile);
 
         final NetconfMonitoringService monitoringService1 = new DummyMonitoringService(capabilities);
 
         final NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory monitoringService =
                 new NetconfMonitoringActivator.NetconfMonitoringOperationServiceFactory(
                         new NetconfMonitoringOperationService(monitoringService1));
-        aggregatedNetconfOperationServiceFactory.onAddNetconfOperationServiceFactory(simulatedOperationProvider);
+        aggregatedNetconfOperationServiceFactory.onAddNetconfOperationServiceFactory(operationProvider);
         aggregatedNetconfOperationServiceFactory.onAddNetconfOperationServiceFactory(monitoringService);
 
         final DefaultCommitNotificationProducer commitNotifier = new DefaultCommitNotificationProducer(ManagementFactory.getPlatformMBeanServer());
@@ -199,7 +192,7 @@ public class NetconfDeviceSimulator implements Closeable {
 
         final Map<ModuleBuilder, String> moduleBuilders = parseSchemasToModuleBuilders(params);
 
-        final NetconfServerDispatcherImpl dispatcher = createDispatcher(moduleBuilders, params.exi, params.generateConfigsTimeout, Optional.fromNullable(params.notificationFile));
+        final NetconfServerDispatcherImpl dispatcher = createDispatcher(moduleBuilders, params.exi, params.generateConfigsTimeout, Optional.fromNullable(params.notificationFile), params.mdSal);
 
         int currentPort = params.startingPort;
 
@@ -336,6 +329,16 @@ public class NetconfDeviceSimulator implements Closeable {
         addDefaultSchemas(consumer);
 
         final Map<SourceIdentifier, Map.Entry<ASTSchemaSource, YangTextSchemaSource>> asts = Maps.newHashMap();
+
+        try {
+            //necessary for creating mdsal datastores and operations
+            schemaContext = consumer.createSchemaContextFactory(
+                SchemaSourceFilter.ALWAYS_ACCEPT)
+                .createSchemaContext(loadedSources).checkedGet();
+        } catch (final SchemaResolutionException e) {
+            throw new RuntimeException("Cannot parse schema context", e);
+        }
+
         for (final SourceIdentifier loadedSource : loadedSources) {
             try {
                 final CheckedFuture<ASTSchemaSource, SchemaSourceException> ast = consumer.getSchemaSource(loadedSource, ASTSchemaSource.class);
@@ -406,62 +409,4 @@ public class NetconfDeviceSimulator implements Closeable {
         // close Everything
     }
 
-    private static class SimulatedOperationProvider implements NetconfOperationServiceFactory {
-        private final Set<Capability> caps;
-        private final SimulatedOperationService simulatedOperationService;
-
-
-        public SimulatedOperationProvider(final SessionIdProvider idProvider, final Set<Capability> caps, final Optional<File> notificationsFile) {
-            this.caps = caps;
-            simulatedOperationService = new SimulatedOperationService(idProvider.getCurrentSessionId(), notificationsFile);
-        }
-
-        @Override
-        public Set<Capability> getCapabilities() {
-            return caps;
-        }
-
-        @Override
-        public AutoCloseable registerCapabilityListener(final CapabilityListener listener) {
-            listener.onCapabilitiesAdded(caps);
-            return new AutoCloseable() {
-                @Override
-                public void close() throws Exception {}
-            };
-        }
-
-        @Override
-        public NetconfOperationService createService(final String netconfSessionIdForReporting) {
-            return simulatedOperationService;
-        }
-
-        static class SimulatedOperationService implements NetconfOperationService {
-            private final long currentSessionId;
-            private final Optional<File> notificationsFile;
-
-            public SimulatedOperationService(final long currentSessionId, final Optional<File> notificationsFile) {
-                this.currentSessionId = currentSessionId;
-                this.notificationsFile = notificationsFile;
-            }
-
-            @Override
-            public Set<NetconfOperation> getNetconfOperations() {
-                final DataList storage = new DataList();
-                final SimulatedGet sGet = new SimulatedGet(String.valueOf(currentSessionId), storage);
-                final SimulatedEditConfig sEditConfig = new SimulatedEditConfig(String.valueOf(currentSessionId), storage);
-                final SimulatedGetConfig sGetConfig = new SimulatedGetConfig(String.valueOf(currentSessionId), storage);
-                final SimulatedCommit sCommit = new SimulatedCommit(String.valueOf(currentSessionId));
-                final SimulatedLock sLock = new SimulatedLock(String.valueOf(currentSessionId));
-                final SimulatedUnLock sUnlock = new SimulatedUnLock(String.valueOf(currentSessionId));
-                final SimulatedCreateSubscription sCreateSubs = new SimulatedCreateSubscription(String.valueOf(currentSessionId), notificationsFile);
-                return Sets.<NetconfOperation>newHashSet(sGet,  sGetConfig, sEditConfig, sCommit, sLock, sUnlock, sCreateSubs);
-            }
-
-            @Override
-            public void close() {
-            }
-
-        }
-    }
-
 }
diff --git a/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedOperationProvider.java b/opendaylight/netconf/netconf-testtool/src/main/java/org/opendaylight/controller/netconf/test/tool/SimulatedOperationProvider.java
new file mode 100644 (file)
index 0000000..5f4af7e
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015 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.netconf.test.tool;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+import java.io.File;
+import java.util.Set;
+import org.opendaylight.controller.netconf.api.Capability;
+import org.opendaylight.controller.netconf.api.monitoring.CapabilityListener;
+import org.opendaylight.controller.netconf.impl.SessionIdProvider;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.test.tool.rpc.DataList;
+import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedCommit;
+import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedCreateSubscription;
+import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedEditConfig;
+import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedGet;
+import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedGetConfig;
+import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedLock;
+import org.opendaylight.controller.netconf.test.tool.rpc.SimulatedUnLock;
+
+class SimulatedOperationProvider implements NetconfOperationServiceFactory {
+    private final Set<Capability> caps;
+    private final SimulatedOperationService simulatedOperationService;
+
+    public SimulatedOperationProvider(final SessionIdProvider idProvider,
+                                      final Set<Capability> caps,
+                                      final Optional<File> notificationsFile) {
+        this.caps = caps;
+        simulatedOperationService = new SimulatedOperationService(idProvider.getCurrentSessionId(), notificationsFile);
+    }
+
+    @Override
+    public Set<Capability> getCapabilities() {
+        return caps;
+    }
+
+    @Override
+    public AutoCloseable registerCapabilityListener(
+            final CapabilityListener listener) {
+        listener.onCapabilitiesAdded(caps);
+        return new AutoCloseable() {
+            @Override
+            public void close() throws Exception {
+            }
+        };
+    }
+
+    @Override
+    public NetconfOperationService createService(
+            final String netconfSessionIdForReporting) {
+        return simulatedOperationService;
+    }
+
+    static class SimulatedOperationService implements NetconfOperationService {
+        private final long currentSessionId;
+        private final Optional<File> notificationsFile;
+
+        public SimulatedOperationService(final long currentSessionId, final Optional<File> notificationsFile) {
+            this.currentSessionId = currentSessionId;
+            this.notificationsFile = notificationsFile;
+        }
+
+        @Override
+        public Set<NetconfOperation> getNetconfOperations() {
+            final DataList storage = new DataList();
+            final SimulatedGet sGet = new SimulatedGet(String.valueOf(currentSessionId), storage);
+            final SimulatedEditConfig sEditConfig = new SimulatedEditConfig(String.valueOf(currentSessionId), storage);
+            final SimulatedGetConfig sGetConfig = new SimulatedGetConfig(String.valueOf(currentSessionId), storage);
+            final SimulatedCommit sCommit = new SimulatedCommit(String.valueOf(currentSessionId));
+            final SimulatedLock sLock = new SimulatedLock(String.valueOf(currentSessionId));
+            final SimulatedUnLock sUnlock = new SimulatedUnLock(String.valueOf(currentSessionId));
+            final SimulatedCreateSubscription sCreateSubs = new SimulatedCreateSubscription(
+                    String.valueOf(currentSessionId), notificationsFile);
+            return Sets.<NetconfOperation>newHashSet(sGet, sGetConfig, sEditConfig, sCommit, sLock, sUnlock, sCreateSubs);
+        }
+
+        @Override
+        public void close() {
+        }
+
+    }
+}