Get rid of netconf operation filters 22/5522/1
authorMaros Marsalek <mmarsale@cisco.com>
Tue, 4 Mar 2014 10:20:26 +0000 (11:20 +0100)
committerMaros Marsalek <mmarsale@cisco.com>
Tue, 4 Mar 2014 14:15:09 +0000 (15:15 +0100)
Merge NetconfOperationFilter interface into NetconfOperation
Execute all operations that can handle a certain request in chained execution (ordered by priority)
Reimplement all current filters as chained operations
Remove NetconfOperationRouter parameter from NetconfOperation
NetconfOperations handling the same request must have different priorities

Change-Id: Iab9c680e6eceab4059feb77616a9d006fb613711
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
32 files changed:
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/AbstractConfigNetconfOperation.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Commit.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/DiscardChanges.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/Validate.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/ValidateTest.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/HandlingPriority.java
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperation.java
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationChainedExecution.java [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java [deleted file]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilterChain.java [deleted file]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationService.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/Get.java
opendaylight/netconf/netconf-monitoring/src/main/java/org/opendaylight/controller/netconf/monitoring/osgi/NetconfMonitoringOperationService.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperation.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractSingletonNetconfOperation.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java

index 6689759..cd99ac4 100644 (file)
@@ -9,15 +9,9 @@
 package org.opendaylight.controller.netconf.confignetconfconnector.operations;
 
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
-import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
-import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
-import org.opendaylight.controller.netconf.util.xml.XmlElement;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
+import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
 
-public abstract class AbstractConfigNetconfOperation extends AbstractNetconfOperation {
+public abstract class AbstractConfigNetconfOperation extends AbstractLastNetconfOperation {
 
     protected final ConfigRegistryClient configRegistryClient;
 
@@ -26,21 +20,4 @@ public abstract class AbstractConfigNetconfOperation extends AbstractNetconfOper
         super(netconfSessionIdForReporting);
         this.configRegistryClient = configRegistryClient;
     }
-
-    @Override
-    protected HandlingPriority canHandle(String operationName, String operationNamespace) {
-        // TODO check namespace
-        return operationName.equals(getOperationName()) ? HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY
-                : HandlingPriority.CANNOT_HANDLE;
-    }
-
-    protected abstract String getOperationName();
-
-    @Override
-    protected Element handle(Document document, XmlElement operationElement, NetconfOperationRouter opRouter)
-            throws NetconfDocumentedException {
-        return handle(document, operationElement);
-    }
-
-    protected abstract Element handle(Document document, XmlElement operationElement) throws NetconfDocumentedException;
 }
index b3327f5..57e3567 100644 (file)
@@ -8,6 +8,9 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
@@ -24,9 +27,6 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import java.util.HashMap;
-import java.util.Map;
-
 public class Commit extends AbstractConfigNetconfOperation {
 
     private static final Logger logger = LoggerFactory.getLogger(Commit.class);
@@ -50,7 +50,7 @@ public class Commit extends AbstractConfigNetconfOperation {
     }
 
     @Override
-    protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+    protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
         checkXml(xml);
 
         CommitStatus status;
index 8965deb..2f72612 100644 (file)
@@ -8,6 +8,9 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException.ErrorSeverity;
@@ -21,9 +24,6 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import java.util.HashMap;
-import java.util.Map;
-
 public class DiscardChanges extends AbstractConfigNetconfOperation {
 
     public static final String DISCARD = "discard-changes";
@@ -49,7 +49,7 @@ public class DiscardChanges extends AbstractConfigNetconfOperation {
     }
 
     @Override
-    protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+    protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
         try {
             fromXml(xml);
         } catch (final IllegalArgumentException e) {
index 017b5e6..33432e4 100644 (file)
@@ -8,7 +8,9 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations;
 
-import com.google.common.base.Preconditions;
+import java.util.HashMap;
+import java.util.Map;
+
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
@@ -23,8 +25,7 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import java.util.HashMap;
-import java.util.Map;
+import com.google.common.base.Preconditions;
 
 public class Validate extends AbstractConfigNetconfOperation {
 
@@ -62,7 +63,7 @@ public class Validate extends AbstractConfigNetconfOperation {
     }
 
     @Override
-    protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+    protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
         try {
             checkXml(xml);
         } catch (IllegalStateException e) {
index bd85f94..bb19dc2 100644 (file)
@@ -8,10 +8,15 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
@@ -40,13 +45,10 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
 
 public class EditConfig extends AbstractConfigNetconfOperation {
 
@@ -312,7 +314,7 @@ public class EditConfig extends AbstractConfigNetconfOperation {
     }
 
     @Override
-    protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+    protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
 
         EditConfigXmlParser.EditConfigExecution editConfigExecution;
         Config cfg = getConfigMapping(configRegistryClient, yangStoreSnapshot);
index dd9a071..73f9ecd 100644 (file)
@@ -8,7 +8,13 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.get;
 
-import com.google.common.collect.Maps;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.ObjectName;
+
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
@@ -35,11 +41,7 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.management.ObjectName;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import com.google.common.collect.Maps;
 
 public class Get extends AbstractConfigNetconfOperation {
 
@@ -119,7 +121,7 @@ public class Get extends AbstractConfigNetconfOperation {
     }
 
     @Override
-    protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+    protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
         try {
             checkXml(xml);
         } catch (final IllegalArgumentException e) {
index 297f789..7cf6e17 100644 (file)
@@ -8,7 +8,12 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig;
 
-import com.google.common.base.Optional;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.ObjectName;
+
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.util.ConfigTransactionClient;
 import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
@@ -29,10 +34,7 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.management.ObjectName;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
+import com.google.common.base.Optional;
 
 public class GetConfig extends AbstractConfigNetconfOperation {
 
@@ -101,7 +103,7 @@ public class GetConfig extends AbstractConfigNetconfOperation {
     }
 
     @Override
-    public Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+    public Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
         Datastore source;
         try {
             source = fromXml(xml);
index e7f9772..b33eb1d 100644 (file)
@@ -8,9 +8,11 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
+import java.util.Map;
+
+import javax.management.ObjectName;
+import javax.management.openmbean.OpenType;
+
 import org.opendaylight.controller.config.util.ConfigRegistryClient;
 import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
@@ -36,9 +38,9 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import javax.management.ObjectName;
-import javax.management.openmbean.OpenType;
-import java.util.Map;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
 
 public class RuntimeRpc extends AbstractConfigNetconfOperation {
 
@@ -161,7 +163,7 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation {
     }
 
     @Override
-    protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
+    protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
 
         // TODO exception handling
         // TODO check for namespaces and unknown elements
index 6eabbe6..444500d 100644 (file)
@@ -8,10 +8,11 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector.osgi;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import org.opendaylight.controller.config.api.LookupRegistry;
 import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
 import org.opendaylight.controller.config.yang.store.api.YangStoreException;
@@ -22,15 +23,13 @@ import org.opendaylight.controller.netconf.confignetconfconnector.transactions.T
 import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
 import org.opendaylight.controller.netconf.mapping.api.Capability;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.yangtools.yang.model.api.Module;
 
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
 
 /**
  * Manages life cycle of {@link YangStoreSnapshot}.
@@ -94,11 +93,6 @@ public class NetconfOperationServiceImpl implements NetconfOperationService {
         return operationProvider.getOperations();
     }
 
-    @Override
-    public Set<NetconfOperationFilter> getFilters() {
-        return Collections.emptySet();
-    }
-
     private static Set<Capability> setupCapabilities(YangStoreSnapshot yangStoreSnapshot) {
         Set<Capability> capabilities = new HashSet<>();
         // [RFC6241] 8.3.  Candidate Configuration Capability
index 0a4f82f..41d9181 100644 (file)
@@ -8,11 +8,33 @@
 
 package org.opendaylight.controller.netconf.confignetconfconnector;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import javax.xml.parsers.ParserConfigurationException;
+
 import org.apache.commons.lang3.StringUtils;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -52,6 +74,8 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.get
 import org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc.RuntimeRpc;
 import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
 import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshot;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
@@ -72,31 +96,11 @@ import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 
 
 public class NetconfMappingTest extends AbstractConfigTest {
@@ -112,6 +116,8 @@ public class NetconfMappingTest extends AbstractConfigTest {
     YangStoreSnapshot yangStoreSnapshot;
     @Mock
     NetconfOperationRouter netconfOperationRouter;
+    @Mock
+    NetconfOperationServiceSnapshot netconfOperationServiceSnapshot;
 
     private TransactionProvider transactionProvider;
 
@@ -120,6 +126,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
         MockitoAnnotations.initMocks(this);
         doReturn(getMbes()).when(this.yangStoreSnapshot).getModuleMXBeanEntryMap();
         doReturn(getModules()).when(this.yangStoreSnapshot).getModules();
+        doNothing().when(netconfOperationServiceSnapshot).close();
 
         this.factory = new NetconfTestImplModuleFactory();
         this.factory2 = new DepTestImplModuleFactory();
@@ -305,10 +312,10 @@ public class NetconfMappingTest extends AbstractConfigTest {
         assertEquals(expectedResult, responseFromCandidate);
 
         edit("netconfMessages/editConfig_none.xml");
-        doNothing().when(netconfOperationRouter).close();
         closeSession();
-        verify(netconfOperationRouter).close();
+        verify(netconfOperationServiceSnapshot).close();
         verifyNoMoreInteractions(netconfOperationRouter);
+        verifyNoMoreInteractions(netconfOperationServiceSnapshot);
     }
 
     private void checkBigDecimal(Element response) {
@@ -322,7 +329,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
 
     private void closeSession() throws NetconfDocumentedException, ParserConfigurationException, SAXException,
             IOException {
-        DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID);
+        DefaultCloseSession closeOp = new DefaultCloseSession(NETCONF_SESSION_ID, netconfOperationServiceSnapshot);
         executeOp(closeOp, "netconfMessages/closeSession.xml");
     }
 
@@ -665,7 +672,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
 
         Preconditions.checkState(priority != HandlingPriority.CANNOT_HANDLE);
 
-        final Document response = op.handle(request, netconfOperationRouter);
+        final Document response = op.handle(request, NetconfOperationRouterImpl.EXECUTION_TERMINATION_POINT);
         logger.debug("Got response\n{}", XmlUtil.toString(response));
         return response.getDocumentElement();
     }
index de1ab71..d393121 100644 (file)
@@ -30,7 +30,7 @@ public class ValidateTest {
     public void test() throws Exception {
         final XmlElement xml = XmlElement.fromString("<abc></abc>");
         final Validate validate = new Validate(null, null, NETCONF_SESSION_ID_FOR_REPORTING);
-        validate.handle(null, xml);
+        validate.handleWithNoSubsequentOperations(null, xml);
     }
 
     @Test(expected = NetconfDocumentedException.class)
@@ -38,14 +38,14 @@ public class ValidateTest {
         final XmlElement xml = XmlElement.fromString("<validate xmlns=\""
                 + XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0 + "\"/>");
         final Validate validate = new Validate(null, null, NETCONF_SESSION_ID_FOR_REPORTING);
-        validate.handle(null, xml);
+        validate.handleWithNoSubsequentOperations(null, xml);
     }
 
     @Test(expected = NetconfDocumentedException.class)
     public void testNoNamespace() throws Exception {
         final XmlElement xml = XmlElement.fromString("<validate/>");
         final Validate validate = new Validate(null, null, NETCONF_SESSION_ID_FOR_REPORTING);
-        validate.handle(null, xml);
+        validate.handleWithNoSubsequentOperations(null, xml);
     }
 
     @Test(expected = NetconfDocumentedException.class)
@@ -55,7 +55,7 @@ public class ValidateTest {
                 + XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0
                 + "\"><source><running></running></source></validate>");
         final Validate validate = new Validate(null, null, NETCONF_SESSION_ID_FOR_REPORTING);
-        validate.handle(null, xml);
+        validate.handleWithNoSubsequentOperations(null, xml);
     }
 
     @Test(expected = NetconfDocumentedException.class)
@@ -66,7 +66,7 @@ public class ValidateTest {
         final TransactionProvider transactionProvider = mock(TransactionProvider.class);
         doThrow(IllegalStateException.class).when(transactionProvider).validateTransaction();
         final Validate validate = new Validate(transactionProvider, null, NETCONF_SESSION_ID_FOR_REPORTING);
-        validate.handle(null, xml);
+        validate.handleWithNoSubsequentOperations(null, xml);
     }
 
     @Test(expected = NetconfDocumentedException.class)
@@ -77,7 +77,7 @@ public class ValidateTest {
         final TransactionProvider transactionProvider = mock(TransactionProvider.class);
         doThrow(ValidationException.class).when(transactionProvider).validateTransaction();
         final Validate validate = new Validate(transactionProvider, null, NETCONF_SESSION_ID_FOR_REPORTING);
-        validate.handle(null, xml);
+        validate.handleWithNoSubsequentOperations(null, xml);
     }
 
     @Test
@@ -89,7 +89,7 @@ public class ValidateTest {
         final Element okElement = XmlUtil.readXmlToElement("<ok/>");
         doNothing().when(transactionProvider).validateTransaction();
         final Validate validate = new Validate(transactionProvider, null, NETCONF_SESSION_ID_FOR_REPORTING);
-        Element ok = validate.handle(XmlUtil.newDocument(), xml);
+        Element ok = validate.handleWithNoSubsequentOperations(XmlUtil.newDocument(), xml);
         assertEquals(XmlUtil.toString(okElement), XmlUtil.toString(ok));
     }
 
index 460288f..f8d9a45 100644 (file)
@@ -12,9 +12,9 @@ import static com.google.common.base.Preconditions.checkState;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.api.NetconfSessionListener;
 import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
-import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl;
 import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
 import org.opendaylight.controller.netconf.util.messages.SendErrorExceptionUtil;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
@@ -33,9 +33,9 @@ public class NetconfServerSessionListener implements NetconfSessionListener<Netc
 
     static final Logger logger = LoggerFactory.getLogger(NetconfServerSessionListener.class);
     private final SessionMonitoringService monitoringService;
-    private final NetconfOperationRouterImpl operationRouter;
+    private final NetconfOperationRouter operationRouter;
 
-    public NetconfServerSessionListener(NetconfOperationRouterImpl operationRouter, SessionMonitoringService monitoringService) {
+    public NetconfServerSessionListener(NetconfOperationRouter operationRouter, SessionMonitoringService monitoringService) {
         this.operationRouter = operationRouter;
         this.monitoringService = monitoringService;
     }
index e25eaac..7e047b1 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.controller.netconf.impl;
 
+import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListener;
@@ -41,7 +42,7 @@ public class NetconfServerSessionListenerFactory implements SessionListenerFacto
 
         CapabilityProvider capabilityProvider = new CapabilityProviderImpl(netconfOperationServiceSnapshot);
 
-        NetconfOperationRouterImpl operationRouter = new NetconfOperationRouterImpl(
+        NetconfOperationRouter operationRouter = NetconfOperationRouterImpl.createOperationRouter(
                 netconfOperationServiceSnapshot, capabilityProvider,
                 commitNotifier);
 
index 1438515..8bc93e0 100644 (file)
@@ -8,30 +8,27 @@
 
 package org.opendaylight.controller.netconf.impl.mapping.operations;
 
+import java.util.Collections;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
-import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
-import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
+import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-public class DefaultCloseSession extends AbstractNetconfOperation {
+public class DefaultCloseSession extends AbstractSingletonNetconfOperation {
     public static final String CLOSE_SESSION = "close-session";
+    private final AutoCloseable sessionResources;
 
-    public DefaultCloseSession(String netconfSessionIdForReporting) {
+    public DefaultCloseSession(String netconfSessionIdForReporting, AutoCloseable sessionResources) {
         super(netconfSessionIdForReporting);
+        this.sessionResources = sessionResources;
     }
 
     @Override
-    protected HandlingPriority canHandle(String operationName, String netconfOperationNamespace) {
-        if (operationName.equals(CLOSE_SESSION) == false)
-            return HandlingPriority.CANNOT_HANDLE;
-        if (netconfOperationNamespace.equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false)
-            return HandlingPriority.CANNOT_HANDLE;
-
-        return HandlingPriority.HANDLE_WITH_MAX_PRIORITY;
+    protected String getOperationName() {
+        return CLOSE_SESSION;
     }
 
     /**
@@ -40,9 +37,17 @@ public class DefaultCloseSession extends AbstractNetconfOperation {
      * instances
      */
     @Override
-    protected Element handle(Document document, XmlElement operationElement, NetconfOperationRouter opRouter)
+    protected Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement)
             throws NetconfDocumentedException {
-        opRouter.close();
+        try {
+            sessionResources.close();
+        } catch (Exception e) {
+            throw new NetconfDocumentedException("Unable to properly close session "
+                    + getNetconfSessionIdForReporting(), NetconfDocumentedException.ErrorType.application,
+                    NetconfDocumentedException.ErrorTag.operation_failed,
+                    NetconfDocumentedException.ErrorSeverity.error, Collections.singletonMap(
+                    NetconfDocumentedException.ErrorSeverity.error.toString(), e.getMessage()));
+        }
         return document.createElement(XmlNetconfConstants.OK);
     }
 }
index 9069e87..ee0c6ce 100644 (file)
@@ -15,9 +15,9 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilterChain;
-import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation.OperationNameAndNamespace;
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
+import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
@@ -26,9 +26,10 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 
-public class DefaultCommit implements NetconfOperationFilter {
+public class DefaultCommit extends AbstractNetconfOperation {
 
     private static final Logger logger = LoggerFactory.getLogger(DefaultCommit.class);
 
@@ -36,13 +37,14 @@ public class DefaultCommit implements NetconfOperationFilter {
 
     private final DefaultCommitNotificationProducer notificationProducer;
     private final CapabilityProvider cap;
-    private final String netconfSessionIdForReporting;
+    private final NetconfOperationRouter operationRouter;
 
     public DefaultCommit(DefaultCommitNotificationProducer notifier, CapabilityProvider cap,
-            String netconfSessionIdForReporting) {
+                         String netconfSessionIdForReporting, NetconfOperationRouter netconfOperationRouter) {
+        super(netconfSessionIdForReporting);
         this.notificationProducer = notifier;
         this.cap = cap;
-        this.netconfSessionIdForReporting = netconfSessionIdForReporting;
+        this.operationRouter = netconfOperationRouter;
         this.getConfigMessage = loadGetConfigMessage();
     }
 
@@ -59,40 +61,36 @@ public class DefaultCommit implements NetconfOperationFilter {
     }
 
     @Override
-    public Document doFilter(Document message, NetconfOperationRouter operationRouter,
-            NetconfOperationFilterChain filterChain) throws NetconfDocumentedException {
-        OperationNameAndNamespace operationNameAndNamespace = new OperationNameAndNamespace(message);
-        if (canHandle(operationNameAndNamespace)) {
-            if (isCommitWithoutNotification(message)) {
-                message = removePersisterAttributes(message);
-                logger.debug("Skipping commit notification");
-                // fall back to filter chain
-            } else {
-                Document innerResult = filterChain.execute(message, operationRouter);
-                Element cfgSnapshot = getConfigSnapshot(operationRouter);
-                logger.debug("Config snapshot retrieved successfully {}", cfgSnapshot);
-                notificationProducer.sendCommitNotification("ok", cfgSnapshot, cap.getCapabilities());
-                return innerResult;
-            }
-        }
-        return filterChain.execute(message, operationRouter);
+    protected String getOperationName() {
+        return XmlNetconfConstants.COMMIT;
     }
 
     @Override
-    public int getSortingOrder() {
-        return 0;
+    public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
+        Preconditions.checkArgument(subsequentOperation.isExecutionTermination() == false,
+                "Subsequent netconf operation expected by %s", this);
+
+        if (isCommitWithoutNotification(requestMessage)) {
+            logger.debug("Skipping commit notification");
+        } else {
+            // Send commit notification if commit was not issued by persister
+            requestMessage = removePersisterAttributes(requestMessage);
+            Element cfgSnapshot = getConfigSnapshot(operationRouter);
+            logger.debug("Config snapshot retrieved successfully {}", cfgSnapshot);
+            notificationProducer.sendCommitNotification("ok", cfgSnapshot, cap.getCapabilities());
+        }
+
+        return subsequentOperation.execute(requestMessage);
     }
 
     @Override
-    public int compareTo(NetconfOperationFilter o) {
-        return Integer.compare(getSortingOrder(), o.getSortingOrder());
+    protected Element handle(Document document, XmlElement message, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
+        throw new UnsupportedOperationException("Never gets called");
     }
 
-    private boolean canHandle(OperationNameAndNamespace operationNameAndNamespace) {
-        if (operationNameAndNamespace.getOperationName().equals("commit") == false)
-            return false;
-        return operationNameAndNamespace.getNamespace().equals(
-                XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
+    @Override
+    protected HandlingPriority getHandlingPriority() {
+        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY.increasePriority(1);
     }
 
     private Document removePersisterAttributes(Document message) {
@@ -139,8 +137,4 @@ public class DefaultCommit implements NetconfOperationFilter {
         return dataElement.getDomElement();
     }
 
-    @Override
-    public String toString() {
-        return "DefaultCommit{" + netconfSessionIdForReporting + '}';
-    }
 }
index 904f3f6..a81bbd6 100644 (file)
@@ -12,10 +12,8 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider;
-import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
-import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
+import org.opendaylight.controller.netconf.util.mapping.AbstractLastNetconfOperation;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
@@ -27,7 +25,7 @@ import org.w3c.dom.Element;
 import com.google.common.base.Optional;
 import com.google.common.collect.Maps;
 
-public final class DefaultGetSchema extends AbstractNetconfOperation {
+public final class DefaultGetSchema extends AbstractLastNetconfOperation {
     public static final String GET_SCHEMA = "get-schema";
     public static final String IDENTIFIER = "identifier";
     public static final String VERSION = "version";
@@ -41,18 +39,17 @@ public final class DefaultGetSchema extends AbstractNetconfOperation {
     }
 
     @Override
-    protected HandlingPriority canHandle(String netconfOperationName, String namespace) {
-        if (netconfOperationName.equals("get-schema") == false)
-            return HandlingPriority.CANNOT_HANDLE;
-        if (namespace.equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING) == false)
-            return HandlingPriority.CANNOT_HANDLE;
+    protected String getOperationName() {
+        return GET_SCHEMA;
+    }
 
-        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;
+    @Override
+    protected String getOperationNamespace() {
+        return XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING;
     }
 
     @Override
-    protected Element handle(Document document, XmlElement xml, NetconfOperationRouter router)
-            throws NetconfDocumentedException {
+    protected Element handleWithNoSubsequentOperations(Document document, XmlElement xml) throws NetconfDocumentedException {
         GetSchemaEntry entry;
 
         try {
index 38c1a44..31a7d32 100644 (file)
@@ -7,12 +7,10 @@
  */\r
 package org.opendaylight.controller.netconf.impl.mapping.operations;\r
 \r
-import org.opendaylight.controller.netconf.api.NetconfSession;\r
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;\r
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
 import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;\r
-import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;\r
-import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;\r
+import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation;\r
 import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;\r
@@ -21,7 +19,7 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;\r
 import org.w3c.dom.Element;\r
 \r
-public class DefaultStartExi extends AbstractNetconfOperation implements DefaultNetconfOperation {\r
+public class DefaultStartExi extends AbstractSingletonNetconfOperation implements DefaultNetconfOperation {\r
 \r
     public static final String START_EXI = "start-exi";\r
 \r
@@ -34,20 +32,12 @@ public class DefaultStartExi extends AbstractNetconfOperation implements Default
     }\r
 \r
     @Override\r
-    protected HandlingPriority canHandle(String operationName,\r
-            String netconfOperationNamespace) {\r
-        if (operationName.equals(START_EXI) == false)\r
-            return HandlingPriority.CANNOT_HANDLE;\r
-        if (netconfOperationNamespace\r
-                .equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false)\r
-            return HandlingPriority.CANNOT_HANDLE;\r
-\r
-        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;\r
+    protected String getOperationName() {\r
+        return START_EXI;\r
     }\r
 \r
     @Override\r
-    protected Element handle(Document document, XmlElement operationElement,\r
-            NetconfOperationRouter opRouter) throws NetconfDocumentedException {\r
+    protected Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement) throws NetconfDocumentedException {\r
 \r
 \r
         Element getSchemaResult = document\r
index 6ea5deb..ae3b00b 100644 (file)
@@ -7,20 +7,17 @@
  */\r
 package org.opendaylight.controller.netconf.impl.mapping.operations;\r
 \r
-import org.opendaylight.controller.netconf.api.NetconfSession;\r
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;\r
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
 import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;\r
-import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;\r
-import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;\r
+import org.opendaylight.controller.netconf.util.mapping.AbstractSingletonNetconfOperation;\r
 import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
-import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 import org.w3c.dom.Document;\r
 import org.w3c.dom.Element;\r
 \r
-public class DefaultStopExi extends AbstractNetconfOperation implements DefaultNetconfOperation {\r
+public class DefaultStopExi extends AbstractSingletonNetconfOperation implements DefaultNetconfOperation {\r
 \r
     public static final String STOP_EXI = "stop-exi";\r
     private NetconfSession netconfSession;\r
@@ -33,20 +30,13 @@ public class DefaultStopExi extends AbstractNetconfOperation implements DefaultN
     }\r
 \r
     @Override\r
-    protected HandlingPriority canHandle(String operationName,\r
-            String netconfOperationNamespace) {\r
-        if (operationName.equals(STOP_EXI) == false)\r
-            return HandlingPriority.CANNOT_HANDLE;\r
-        if (netconfOperationNamespace\r
-                .equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false)\r
-            return HandlingPriority.CANNOT_HANDLE;\r
-\r
-        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;\r
+    protected String getOperationName() {\r
+        return STOP_EXI;\r
     }\r
 \r
     @Override\r
-    protected Element handle(Document document, XmlElement operationElement,\r
-            NetconfOperationRouter opRouter) throws NetconfDocumentedException {\r
+    protected Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement)\r
+            throws NetconfDocumentedException {\r
         throw new UnsupportedOperationException("Not implemented");\r
         /*\r
         netconfSession.remove(ExiDecoderHandler.class);\r
index ece9d47..8d532d4 100644 (file)
@@ -9,12 +9,9 @@ package org.opendaylight.controller.netconf.impl.osgi;
 
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
-import java.util.TreeSet;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
@@ -29,8 +26,7 @@ import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStopEx
 import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilterChain;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
@@ -46,31 +42,38 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
     private static final Logger logger = LoggerFactory.getLogger(NetconfOperationRouterImpl.class);
 
     private final NetconfOperationServiceSnapshot netconfOperationServiceSnapshot;
+    private Set<NetconfOperation> allNetconfOperations;
 
-    private final Set<NetconfOperation> allNetconfOperations;
-    private final TreeSet<NetconfOperationFilter> allSortedFilters;
-
-    private final CapabilityProvider capabilityProvider;
+    private NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
+        this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot;
+    }
 
+    private void initNetconfOperations(Set<NetconfOperation> allOperations) {
+        allNetconfOperations = allOperations;
+    }
 
-    public NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
-            CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) {
+    /**
+     * Factory method to produce instance of NetconfOperationRouter
+     */
+    public static NetconfOperationRouter createOperationRouter(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot,
+                                                               CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) {
+        NetconfOperationRouterImpl router = new NetconfOperationRouterImpl(netconfOperationServiceSnapshot);
 
-        this.netconfOperationServiceSnapshot = Preconditions.checkNotNull(netconfOperationServiceSnapshot);
-        this.capabilityProvider = Preconditions.checkNotNull(capabilityProvider);
+        Preconditions.checkNotNull(netconfOperationServiceSnapshot);
+        Preconditions.checkNotNull(capabilityProvider);
 
         final String sessionId = netconfOperationServiceSnapshot.getNetconfSessionIdForReporting();
+
         final Set<NetconfOperation> defaultNetconfOperations = Sets.newHashSet();
         defaultNetconfOperations.add(new DefaultGetSchema(capabilityProvider, sessionId));
-        defaultNetconfOperations.add(new DefaultCloseSession(sessionId));
+        defaultNetconfOperations.add(new DefaultCloseSession(sessionId, router));
         defaultNetconfOperations.add(new DefaultStartExi(sessionId));
         defaultNetconfOperations.add(new DefaultStopExi(sessionId));
+        defaultNetconfOperations.add(new DefaultCommit(commitNotifier, capabilityProvider, sessionId, router));
 
-        allNetconfOperations = getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot);
+        router.initNetconfOperations(getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot));
 
-        DefaultCommit defaultCommit = new DefaultCommit(commitNotifier, capabilityProvider, sessionId);
-        Set<NetconfOperationFilter> defaultFilters = Sets.<NetconfOperationFilter> newHashSet(defaultCommit);
-        allSortedFilters = getAllNetconfFilters(defaultFilters, netconfOperationServiceSnapshot);
+        return router;
     }
 
     private static Set<NetconfOperation> getAllNetconfOperations(Set<NetconfOperation> defaultNetconfOperations,
@@ -89,29 +92,12 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return Collections.unmodifiableSet(result);
     }
 
-    private static TreeSet<NetconfOperationFilter> getAllNetconfFilters(Set<NetconfOperationFilter> defaultFilters,
-            NetconfOperationServiceSnapshot netconfOperationServiceSnapshot) {
-        TreeSet<NetconfOperationFilter> result = new TreeSet<>(defaultFilters);
-        for (NetconfOperationService netconfOperationService : netconfOperationServiceSnapshot.getServices()) {
-            final Set<NetconfOperationFilter> filtersFromService = netconfOperationService.getFilters();
-            for (NetconfOperationFilter filter : filtersFromService) {
-                Preconditions.checkState(result.contains(filter) == false,
-                        "Filter %s already present, all filters so far: %s", filter, result);
-                result.add(filter);
-            }
-        }
-        return result;
-    }
-
-    public CapabilityProvider getCapabilityProvider() {
-        return capabilityProvider;
-    }
-
     @Override
     public synchronized Document onNetconfMessage(Document message,
             NetconfSession session) throws NetconfDocumentedException {
-        NetconfOperationExecution netconfOperationExecution;
+        Preconditions.checkNotNull(allNetconfOperations, "Operation router was not initialized properly");
 
+        NetconfOperationExecution netconfOperationExecution;
         String messageAsString = XmlUtil.toString(message);
 
         try {
@@ -144,6 +130,11 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         }
     }
 
+    @Override
+    public void close() {
+        netconfOperationServiceSnapshot.close();
+    }
+
     private NetconfDocumentedException handleUnexpectedEx(String s, Exception e) throws NetconfDocumentedException {
         logger.error(s, e);
 
@@ -155,94 +146,91 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
                 NetconfDocumentedException.ErrorSeverity.error, info);
     }
 
-    private Document executeOperationWithHighestPriority(Document message, NetconfOperationExecution netconfOperationExecution, String messageAsString) throws NetconfDocumentedException {
-        logger.debug("Forwarding netconf message {} to {}", messageAsString,
-                netconfOperationExecution.operationWithHighestPriority);
-
-        final LinkedList<NetconfOperationFilterChain> chain = new LinkedList<>();
-        chain.push(netconfOperationExecution);
-
-        for (Iterator<NetconfOperationFilter> it = allSortedFilters.descendingIterator(); it.hasNext();) {
-            final NetconfOperationFilter filter = it.next();
-            final NetconfOperationFilterChain prevItem = chain.getFirst();
-            NetconfOperationFilterChain currentItem = new NetconfOperationFilterChain() {
-                @Override
-                public Document execute(Document message, NetconfOperationRouter operationRouter)
-                        throws NetconfDocumentedException {
-                    logger.trace("Entering {}", filter);
-                    return filter.doFilter(message, operationRouter, prevItem);
-                }
-            };
-            chain.push(currentItem);
-        }
-        return chain.getFirst().execute(message, this);
+    private Document executeOperationWithHighestPriority(Document message,
+            NetconfOperationExecution netconfOperationExecution, String messageAsString)
+            throws NetconfDocumentedException {
+        logger.debug("Forwarding netconf message {} to {}", messageAsString, netconfOperationExecution.netconfOperation);
+        return netconfOperationExecution.execute(message);
     }
 
     private NetconfOperationExecution getNetconfOperationWithHighestPriority(
             Document message, NetconfSession session) {
 
-        TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(
+        TreeMap<HandlingPriority, NetconfOperation> sortedByPriority = getSortedNetconfOperationsWithCanHandle(
                 message, session);
 
-        Preconditions.checkArgument(sortedPriority.isEmpty() == false, "No %s available to handle message %s",
-                NetconfOperation.class.getName(), XmlUtil.toString(message));
-
-        HandlingPriority highestFoundPriority = sortedPriority.lastKey();
-
-        int netconfOperationsWithHighestPriority = sortedPriority.get(highestFoundPriority).size();
-
-        Preconditions.checkState(netconfOperationsWithHighestPriority == 1,
-                "Multiple %s available to handle message %s", NetconfOperation.class.getName(), message);
+        Preconditions.checkArgument(sortedByPriority.isEmpty() == false,
+                "No %s available to handleWithNoSubsequentOperations message %s", NetconfOperation.class.getName(),
+                XmlUtil.toString(message));
 
-        return new NetconfOperationExecution(sortedPriority, highestFoundPriority);
+        return NetconfOperationExecution.createExecutionChain(sortedByPriority, sortedByPriority.lastKey());
     }
 
-    private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(
-            Document message, NetconfSession session) {
-        TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority = Maps.newTreeMap();
+    private TreeMap<HandlingPriority, NetconfOperation> getSortedNetconfOperationsWithCanHandle(Document message,
+            NetconfSession session) {
+        TreeMap<HandlingPriority, NetconfOperation> sortedPriority = Maps.newTreeMap();
 
         for (NetconfOperation netconfOperation : allNetconfOperations) {
             final HandlingPriority handlingPriority = netconfOperation.canHandle(message);
             if (netconfOperation instanceof DefaultNetconfOperation) {
-                ((DefaultNetconfOperation) netconfOperation)
-                        .setNetconfSession(session);
+                ((DefaultNetconfOperation) netconfOperation).setNetconfSession(session);
             }
             if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) {
-                Set<NetconfOperation> netconfOperations = sortedPriority.get(handlingPriority);
-                netconfOperations = checkIfNoOperationsOnPriority(sortedPriority, handlingPriority, netconfOperations);
-                netconfOperations.add(netconfOperation);
+
+                Preconditions.checkState(sortedPriority.containsKey(handlingPriority) == false,
+                        "Multiple %s available to handle message %s with priority %s",
+                        NetconfOperation.class.getName(), message, handlingPriority);
+                sortedPriority.put(handlingPriority, netconfOperation);
             }
         }
         return sortedPriority;
     }
 
-    private Set<NetconfOperation> checkIfNoOperationsOnPriority(
-            TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority, HandlingPriority handlingPriority,
-            Set<NetconfOperation> netconfOperations) {
-        if (netconfOperations == null) {
-            netconfOperations = Sets.newHashSet();
-            sortedPriority.put(handlingPriority, netconfOperations);
+    public static final NetconfOperationChainedExecution EXECUTION_TERMINATION_POINT = new NetconfOperationChainedExecution() {
+        @Override
+        public boolean isExecutionTermination() {
+            return true;
         }
-        return netconfOperations;
-    }
 
-    @Override
-    public void close() {
-        netconfOperationServiceSnapshot.close();
-    }
+        @Override
+        public Document execute(Document requestMessage) throws NetconfDocumentedException {
+            throw new IllegalStateException("This execution represents the termination point in operation execution and cannot be executed itself");
+        }
+    };
+
+    private static class NetconfOperationExecution implements NetconfOperationChainedExecution {
+        private final NetconfOperation netconfOperation;
+        private NetconfOperationChainedExecution subsequentExecution;
 
-    private class NetconfOperationExecution implements NetconfOperationFilterChain {
-        private final NetconfOperation operationWithHighestPriority;
+        private NetconfOperationExecution(NetconfOperation netconfOperation, NetconfOperationChainedExecution subsequentExecution) {
+            this.netconfOperation = netconfOperation;
+            this.subsequentExecution = subsequentExecution;
+        }
 
-        public NetconfOperationExecution(TreeMap<HandlingPriority, Set<NetconfOperation>> sortedPriority,
-                HandlingPriority highestFoundPriority) {
-            operationWithHighestPriority = sortedPriority.get(highestFoundPriority).iterator().next();
-            sortedPriority.remove(highestFoundPriority);
+        @Override
+        public boolean isExecutionTermination() {
+            return false;
         }
 
         @Override
-        public Document execute(Document message, NetconfOperationRouter router) throws NetconfDocumentedException {
-            return operationWithHighestPriority.handle(message, router);
+        public Document execute(Document message) throws NetconfDocumentedException {
+            return netconfOperation.handle(message, subsequentExecution);
+        }
+
+        public static NetconfOperationExecution createExecutionChain(
+                TreeMap<HandlingPriority, NetconfOperation> sortedByPriority, HandlingPriority handlingPriority) {
+            NetconfOperation netconfOperation = sortedByPriority.get(handlingPriority);
+            HandlingPriority subsequentHandlingPriority = sortedByPriority.lowerKey(handlingPriority);
+
+            NetconfOperationChainedExecution subsequentExecution = null;
+
+            if (subsequentHandlingPriority != null) {
+                subsequentExecution = createExecutionChain(sortedByPriority, subsequentHandlingPriority);
+            } else {
+                subsequentExecution = EXECUTION_TERMINATION_POINT;
+            }
+
+            return new NetconfOperationExecution(netconfOperation, subsequentExecution);
         }
     }
 
@@ -251,7 +239,4 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return "NetconfOperationRouterImpl{" + "netconfOperationServiceSnapshot=" + netconfOperationServiceSnapshot
                 + '}';
     }
-
-
-
 }
index c0d52ad..4385437 100644 (file)
@@ -8,12 +8,26 @@
 
 package org.opendaylight.controller.netconf.impl;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.EventLoopGroup;
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.util.HashedWheelTimer;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import java.io.DataOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.management.ManagementFactory;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import javax.management.ObjectName;
+
 import org.apache.commons.io.IOUtils;
 import org.junit.After;
 import org.junit.Before;
@@ -26,7 +40,6 @@ import org.opendaylight.controller.config.yang.store.api.YangStoreService;
 import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.client.NetconfClient;
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
@@ -34,7 +47,7 @@ import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
 import org.opendaylight.controller.netconf.mapping.api.Capability;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
@@ -44,24 +57,13 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
-import javax.management.ObjectName;
-import java.io.DataOutputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.management.ManagementFactory;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
 
 public class ConcurrentClientsTest {
 
@@ -151,8 +153,7 @@ public class ConcurrentClientsTest {
                             }
 
                             @Override
-                            public Document handle(Document message, NetconfOperationRouter operationRouter)
-                                    throws NetconfDocumentedException {
+                            public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
                                 try {
                                     return XmlUtil.readXmlToDocument("<test/>");
                                 } catch (Exception e) {
@@ -162,11 +163,6 @@ public class ConcurrentClientsTest {
                         });
                     }
 
-                    @Override
-                    public Set<NetconfOperationFilter> getFilters() {
-                        return Collections.emptySet();
-                    }
-
                     @Override
                     public void close() {
                     }
index 176cf2d..1236138 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.controller.netconf.mapping.api;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
 public class HandlingPriority implements Comparable<HandlingPriority> {
 
@@ -33,7 +34,15 @@ public class HandlingPriority implements Comparable<HandlingPriority> {
      * @return priority number or Optional.absent otherwise
      */
     public Optional<Integer> getPriority() {
-        return Optional.of(priority).or(Optional.<Integer> absent());
+        return Optional.fromNullable(priority);
+    }
+
+    public HandlingPriority increasePriority(int priorityIncrease) {
+        Preconditions.checkState(priority!=null, "Unable to increase priority for %s", this);
+        Preconditions.checkArgument(priorityIncrease > 0, "Negative increase");
+        Preconditions.checkArgument(Long.valueOf(priority) + priorityIncrease < Integer.MAX_VALUE,
+                "Resulting priority cannot be higher than %s", Integer.MAX_VALUE);
+        return getHandlingPriority(priority + priorityIncrease);
     }
 
     @Override
index 58857b4..b70f8db 100644 (file)
@@ -9,12 +9,45 @@
 package org.opendaylight.controller.netconf.mapping.api;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.w3c.dom.Document;
 
+/**
+ * NetconfOperation handles netconf requests. Multiple operations might be
+ * capable of handling one request at the same time. In such case, these
+ * operations are chained (ordered by HandlingPriority returned by canHandle
+ * method) and executed.
+ *
+ * Operation can be declared as singleton or last in chain (see abstract
+ * implementations in netconf-util). If the operation is not singleton or last,
+ * it is responsible for the execution of subsequent operation and for merging
+ * the results.
+ *
+ */
 public interface NetconfOperation {
 
-    HandlingPriority canHandle(Document message);
+    /**
+     * Singleton operations should return
+     * HandlingPriority.HANDLE_WITH_MAX_PRIORITY, last operations
+     * HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY.
+     *
+     * @param requestMessage
+     * @return
+     */
+    HandlingPriority canHandle(Document requestMessage);
 
-    Document handle(Document message, NetconfOperationRouter operationRouter) throws NetconfDocumentedException;
+    /**
+     * Execute current netconf operation and trigger execution of subsequent
+     * operations. subsequentOperation parameter will provide information, if
+     * current operation is the termination point in execution. In case of
+     * last/singleton operation, subsequentOperation must indicate termination
+     * point.
+     *
+     * @param requestMessage
+     * @param subsequentOperation
+     *            execution of subsequent netconf operation
+     * @return
+     * @throws NetconfDocumentedException
+     */
+    Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation)
+            throws NetconfDocumentedException;
 }
diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationChainedExecution.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationChainedExecution.java
new file mode 100644 (file)
index 0000000..2298153
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 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.mapping.api;
+
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.w3c.dom.Document;
+
+/**
+ * Single link in netconf operation execution chain.
+ * Wraps the execution of a single netconf operation.
+ */
+public interface NetconfOperationChainedExecution {
+
+    /**
+     * @return true if this is termination point in operation execution, false
+     *         if there is a subsequent operation present that needs to be
+     *         executed
+     */
+    boolean isExecutionTermination();
+
+    /**
+     * Do not execute if this is termination point
+     */
+    Document execute(Document requestMessage) throws NetconfDocumentedException;
+}
diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java
deleted file mode 100644 (file)
index c9e04e3..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2013 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.mapping.api;
-
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
-import org.w3c.dom.Document;
-
-/**
- * Filters wrap each netconf operation, if there is one found. Filters are
- * sorted and applied from the greatest to smallest sorting order.
- */
-public interface NetconfOperationFilter extends Comparable<NetconfOperationFilter> {
-
-    Document doFilter(Document message, NetconfOperationRouter operationRouter, NetconfOperationFilterChain filterChain)
-            throws NetconfDocumentedException;
-
-    int getSortingOrder();
-
-}
diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilterChain.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilterChain.java
deleted file mode 100644 (file)
index 7a0eb91..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 2013 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.mapping.api;
-
-import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
-import org.w3c.dom.Document;
-
-public interface NetconfOperationFilterChain {
-
-    Document execute(Document message, NetconfOperationRouter operationRouter) throws NetconfDocumentedException;
-
-}
index 0b923f6..1b32b52 100644 (file)
@@ -7,12 +7,12 @@
  */
 package org.opendaylight.controller.netconf.monitoring;
 
-import com.google.common.collect.Maps;
+import java.util.Map;
+
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilterChain;
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.monitoring.xml.JaxBSerializer;
 import org.opendaylight.controller.netconf.monitoring.xml.model.NetconfState;
 import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;
@@ -24,32 +24,50 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import java.util.Map;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
 
-public class Get implements NetconfOperationFilter {
+public class Get extends AbstractNetconfOperation {
 
     private static final Logger logger = LoggerFactory.getLogger(Get.class);
     private final NetconfMonitoringService netconfMonitor;
 
     public Get(NetconfMonitoringService netconfMonitor) {
+        super(MonitoringConstants.MODULE_NAME);
         this.netconfMonitor = netconfMonitor;
     }
 
-    @Override
-    public Document doFilter(Document message, NetconfOperationRouter operationRouter,
-            NetconfOperationFilterChain filterChain) throws NetconfDocumentedException {
-        AbstractNetconfOperation.OperationNameAndNamespace operationNameAndNamespace = new AbstractNetconfOperation.OperationNameAndNamespace(
-                message);
-        if (canHandle(operationNameAndNamespace)) {
-            return handle(message, operationRouter, filterChain);
+    private Element getPlaceholder(Document innerResult) {
+        try {
+            XmlElement rootElement = XmlElement.fromDomElementWithExpected(innerResult.getDocumentElement(),
+                    XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.RFC4741_TARGET_NAMESPACE);
+            return rootElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY).getDomElement();
+        } catch (RuntimeException e) {
+            throw new IllegalArgumentException(String.format(
+                    "Input xml in wrong format, Expecting root element %s with child element %s, but was %s",
+                    XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.DATA_KEY,
+                    XmlUtil.toString(innerResult.getDocumentElement())), e);
         }
-        return filterChain.execute(message, operationRouter);
     }
 
-    private Document handle(Document message, NetconfOperationRouter operationRouter,
-            NetconfOperationFilterChain filterChain) throws NetconfDocumentedException {
+    @Override
+    protected String getOperationName() {
+        return XmlNetconfConstants.GET;
+    }
+
+    @Override
+    protected HandlingPriority getHandlingPriority() {
+        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY.increasePriority(1);
+    }
+
+    @Override
+    public Document handle(Document requestMessage, NetconfOperationChainedExecution subsequentOperation)
+            throws NetconfDocumentedException {
+        Preconditions.checkArgument(subsequentOperation.isExecutionTermination() == false,
+                "Subsequent netconf operation expected by %s", this);
+
         try {
-            Document innerResult = filterChain.execute(message, operationRouter);
+            Document innerResult = subsequentOperation.execute(requestMessage);
 
             NetconfState netconfMonitoring = new NetconfState(netconfMonitor);
             Element monitoringXmlElement = new JaxBSerializer().toXml(netconfMonitoring);
@@ -70,35 +88,9 @@ public class Get implements NetconfOperationFilter {
         }
     }
 
-    private Element getPlaceholder(Document innerResult) {
-        try {
-            XmlElement rootElement = XmlElement.fromDomElementWithExpected(innerResult.getDocumentElement(),
-                    XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.RFC4741_TARGET_NAMESPACE);
-            return rootElement.getOnlyChildElement(XmlNetconfConstants.DATA_KEY).getDomElement();
-        } catch (RuntimeException e) {
-            throw new IllegalArgumentException(String.format(
-                    "Input xml in wrong format, Expecting root element %s with child element %s, but was %s",
-                    XmlNetconfConstants.RPC_REPLY_KEY, XmlNetconfConstants.DATA_KEY,
-                    XmlUtil.toString(innerResult.getDocumentElement())), e);
-        }
-    }
-
-    private boolean canHandle(AbstractNetconfOperation.OperationNameAndNamespace operationNameAndNamespace) {
-        if (operationNameAndNamespace.getOperationName().equals(XmlNetconfConstants.GET) == false)
-            return false;
-        return operationNameAndNamespace.getNamespace().equals(
-                XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
-    }
-
     @Override
-    public int getSortingOrder() {
-        // FIXME filters for different operations cannot have same order
-        return 1;
+    protected Element handle(Document document, XmlElement message, NetconfOperationChainedExecution subsequentOperation)
+            throws NetconfDocumentedException {
+        throw new UnsupportedOperationException("Never gets called");
     }
-
-    @Override
-    public int compareTo(NetconfOperationFilter o) {
-        return Integer.compare(getSortingOrder(), o.getSortingOrder());
-    }
-
 }
index fe01847..a42bc09 100644 (file)
@@ -7,27 +7,26 @@
 */
 package org.opendaylight.controller.netconf.monitoring.osgi;
 
-import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Sets;
-import com.google.common.io.Files;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
 import org.opendaylight.controller.netconf.api.monitoring.NetconfMonitoringService;
 import org.opendaylight.controller.netconf.mapping.api.Capability;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
-import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
 import org.opendaylight.controller.netconf.monitoring.Get;
 import org.opendaylight.controller.netconf.monitoring.MonitoringConstants;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.Schemas;
 
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import com.google.common.io.Files;
 
 public class NetconfMonitoringOperationService implements NetconfOperationService {
 
@@ -89,12 +88,7 @@ public class NetconfMonitoringOperationService implements NetconfOperationServic
 
     @Override
     public Set<NetconfOperation> getNetconfOperations() {
-        return Collections.emptySet();
-    }
-
-    @Override
-    public Set<NetconfOperationFilter> getFilters() {
-        return Sets.<NetconfOperationFilter>newHashSet(new Get(monitor));
+        return Sets.<NetconfOperation>newHashSet(new Get(monitor));
     }
 
     @Override
diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperation.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractLastNetconfOperation.java
new file mode 100644 (file)
index 0000000..d6d57c5
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013 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.util.mapping;
+
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractLastNetconfOperation extends AbstractNetconfOperation {
+
+    protected AbstractLastNetconfOperation(String netconfSessionIdForReporting) {
+        super(netconfSessionIdForReporting);
+    }
+
+    @Override
+    protected Element handle(Document document, XmlElement operationElement,
+            NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
+        Preconditions.checkArgument(subsequentOperation.isExecutionTermination(),
+                "No netconf operation expected to be subsequent to %s, but is %s", this, subsequentOperation);
+
+        return handleWithNoSubsequentOperations(document, operationElement);
+    }
+
+    @Override
+    protected HandlingPriority getHandlingPriority() {
+        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;
+    }
+
+    protected abstract Element handleWithNoSubsequentOperations(Document document, XmlElement operationElement) throws NetconfDocumentedException;
+}
index ba63646..2e3100f 100644 (file)
@@ -11,9 +11,9 @@ package org.opendaylight.controller.netconf.util.mapping;
 import java.util.Map;
 
 import org.opendaylight.controller.netconf.api.NetconfDocumentedException;
-import org.opendaylight.controller.netconf.api.NetconfOperationRouter;
 import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
 import org.opendaylight.controller.netconf.mapping.api.NetconfOperation;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationChainedExecution;
 import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
@@ -64,19 +64,34 @@ public abstract class AbstractNetconfOperation implements NetconfOperation {
                 XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);
     }
 
-    protected abstract HandlingPriority canHandle(String operationName, String netconfOperationNamespace);
+    protected HandlingPriority canHandle(String operationName, String operationNamespace) {
+        return operationName.equals(getOperationName()) && operationNamespace.equals(getOperationNamespace())
+                ? getHandlingPriority()
+                : HandlingPriority.CANNOT_HANDLE;
+    }
+
+    protected HandlingPriority getHandlingPriority() {
+        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;
+    }
+
+    protected String getOperationNamespace() {
+        return XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0;
+    }
+
+    protected abstract String getOperationName();
 
     @Override
-    public final Document handle(Document message, NetconfOperationRouter opRouter) throws NetconfDocumentedException {
+    public Document handle(Document requestMessage,
+            NetconfOperationChainedExecution subsequentOperation) throws NetconfDocumentedException {
 
-        XmlElement requestElement = getRequestElementWithCheck(message);
+        XmlElement requestElement = getRequestElementWithCheck(requestMessage);
 
         Document document = XmlUtil.newDocument();
 
         XmlElement operationElement = requestElement.getOnlyChildElement();
         Map<String, Attr> attributes = requestElement.getAttributes();
 
-        Element response = handle(document, operationElement, opRouter);
+        Element response = handle(document, operationElement, subsequentOperation);
         Element rpcReply = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0,
                 XmlNetconfConstants.RPC_REPLY_KEY);
 
@@ -98,11 +113,16 @@ public abstract class AbstractNetconfOperation implements NetconfOperation {
         return document;
     }
 
-    protected abstract Element handle(Document document, XmlElement operationElement, NetconfOperationRouter opRouter)
+    protected abstract Element handle(Document document, XmlElement message, NetconfOperationChainedExecution subsequentOperation)
             throws NetconfDocumentedException;
 
     @Override
     public String toString() {
-        return getClass() + "{" + netconfSessionIdForReporting + '}';
+        final StringBuffer sb = new StringBuffer("AbstractConfigNetconfOperation{");
+        sb.append("name=").append(getOperationName());
+        sb.append(", namespace=").append(getOperationNamespace());
+        sb.append(", session=").append(netconfSessionIdForReporting);
+        sb.append('}');
+        return sb.toString();
     }
 }
diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractSingletonNetconfOperation.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractSingletonNetconfOperation.java
new file mode 100644 (file)
index 0000000..4491e76
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013 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.util.mapping;
+
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;
+
+public abstract class AbstractSingletonNetconfOperation extends AbstractLastNetconfOperation {
+
+    protected AbstractSingletonNetconfOperation(String netconfSessionIdForReporting) {
+        super(netconfSessionIdForReporting);
+    }
+
+    @Override
+    protected HandlingPriority getHandlingPriority() {
+        return HandlingPriority.HANDLE_WITH_MAX_PRIORITY;
+    }
+
+}
index 4a6586c..f32179a 100644 (file)
@@ -38,7 +38,7 @@ public final class XmlNetconfConstants {
     public static final String PREFIX = "prefix";
 
     //
-    //
+    // TODO duplicate
     public static final String RFC4741_TARGET_NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0";
     public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0 = "urn:ietf:params:xml:ns:netconf:base:1.0";