Merge "Update context-instance xpath format according to latest changes in config...
authorEd Warnicke <eaw@cisco.com>
Tue, 26 Nov 2013 14:06:16 +0000 (14:06 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 26 Nov 2013 14:06:16 +0000 (14:06 +0000)
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/Rpcs.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpcElementResolved.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpc.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInner.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInnerInner.xml
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/rpcInnerInner_complex_output.xml

index 556541a..ef286ac 100644 (file)
@@ -24,8 +24,9 @@ public class Rpcs {
     public ModuleRpcs getRpcMapping(RuntimeRpcElementResolved id) {
         Map<String, ModuleRpcs> modules = mappedRpcs.get(id.getNamespace());
         Preconditions.checkState(modules != null, "No modules found for namespace %s", id.getNamespace());
-        ModuleRpcs rpcMapping = modules.get(id.getModuleName());
-        Preconditions.checkState(modules != null, "No module %s found for namespace %s", id.getModuleName(),
+        String moduleName = id.getModuleName();
+        ModuleRpcs rpcMapping = modules.get(moduleName);
+        Preconditions.checkState(rpcMapping != null, "No module %s found for namespace %s", moduleName,
                 id.getNamespace());
 
         return rpcMapping;
index 838e5d8..0f0b122 100644 (file)
@@ -33,11 +33,11 @@ public final class RuntimeRpcElementResolved {
 
     private RuntimeRpcElementResolved(String namespace, String moduleName, String instanceName, String runtimeBeanName,
             Map<String, String> additionalAttributes) {
-        this.moduleName = moduleName;
-        this.instanceName = instanceName;
+        this.moduleName = Preconditions.checkNotNull(moduleName, "Module name");
+        this.instanceName =  Preconditions.checkNotNull(instanceName, "Instance name");
         this.additionalAttributes = additionalAttributes;
-        this.namespace = namespace;
-        this.runtimeBeanName = runtimeBeanName;
+        this.namespace = Preconditions.checkNotNull(namespace, "Namespace");
+        this.runtimeBeanName = Preconditions.checkNotNull(runtimeBeanName, "Runtime bean name");
     }
 
     public String getModuleName() {
@@ -68,12 +68,22 @@ public final class RuntimeRpcElementResolved {
         return ObjectNameUtil.createRuntimeBeanName(moduleName, instanceName, additionalAttributesJavaNames);
     }
 
-    private static final String xpathPatternBlueprint = "/" + XmlNetconfConstants.DATA_KEY + "/"
-            + XmlNetconfConstants.MODULES_KEY + "/" + XmlNetconfConstants.MODULE_KEY + "\\["
-            + XmlNetconfConstants.NAME_KEY + "='(.+)'\\]/" + XmlNetconfConstants.INSTANCE_KEY + "\\["
-            + XmlNetconfConstants.NAME_KEY + "='([^']+)'\\](.*)";
+    private static final String xpathPatternBlueprint =
+            "/" + XmlNetconfConstants.MODULES_KEY
+            + "/" + XmlNetconfConstants.MODULE_KEY
+            + "\\["
+
+            + "(?<key1>type|name)"
+            + "='(?<value1>[^']+)'"
+            + "( and |\\]\\[)"
+            + "(?<key2>type|name)"
+            + "='(?<value2>[^']+)'"
+
+            + "\\]"
+            + "(?<additional>.*)";
+
     private static final Pattern xpathPattern = Pattern.compile(xpathPatternBlueprint);
-    private static final String additionalPatternBlueprint = "(.+)\\[(.+)='(.+)'\\]";
+    private static final String additionalPatternBlueprint = "(?<additionalKey>.+)\\[(.+)='(?<additionalValue>.+)'\\]";
     private static final Pattern additionalPattern = Pattern.compile(additionalPatternBlueprint);
 
     public static RuntimeRpcElementResolved fromXpath(String xpath, String elementName, String namespace) {
@@ -82,26 +92,65 @@ public final class RuntimeRpcElementResolved {
                 "Node %s with value '%s' not in required form on rpc element %s, required format is %s",
                 RuntimeRpc.CONTEXT_INSTANCE, xpath, elementName, xpathPatternBlueprint);
 
-        String moduleName = matcher.group(1);
-        String instanceName = matcher.group(2);
-        String additionalString = matcher.group(3);
-        HashMap<String, String> additionalAttributes = Maps.<String, String> newHashMap();
-        String runtimeBeanYangName = moduleName;
-        for (String additionalKeyValue : additionalString.split("/")) {
-            if (Strings.isNullOrEmpty(additionalKeyValue))
-                continue;
-            matcher = additionalPattern.matcher(additionalKeyValue);
-            Preconditions
-                    .checkState(
-                            matcher.matches(),
-                            "Attribute %s not in required form on rpc element %s, required format for additional attributes is  %s",
-                            additionalKeyValue, elementName, additionalPatternBlueprint);
-            String name = matcher.group(1);
-            runtimeBeanYangName = name;
-            additionalAttributes.put(name, matcher.group(3));
-        }
+        PatternGroupResolver groups = new PatternGroupResolver(matcher.group("key1"), matcher.group("value1"),
+                matcher.group("key2"), matcher.group("value2"), matcher.group("additional"));
+
+        String moduleName = groups.getModuleName();
+        String instanceName = groups.getInstanceName();
+
+        HashMap<String, String> additionalAttributes = groups.getAdditionalKeys(elementName, moduleName);
 
-        return new RuntimeRpcElementResolved(namespace, moduleName, instanceName, runtimeBeanYangName,
+        return new RuntimeRpcElementResolved(namespace, moduleName, instanceName, groups.getRuntimeBeanYangName(),
                 additionalAttributes);
     }
+
+    private static final class PatternGroupResolver {
+
+        private final String key1, key2, value1, value2;
+        private final String additional;
+        private String runtimeBeanYangName;
+
+        PatternGroupResolver(String key1, String value1, String key2, String value2, String additional) {
+            this.key1 = Preconditions.checkNotNull(key1);
+            this.value1 = Preconditions.checkNotNull(value1);
+
+            this.key2 = Preconditions.checkNotNull(key2);
+            this.value2 = Preconditions.checkNotNull(value2);
+
+            this.additional = Preconditions.checkNotNull(additional);
+        }
+
+        String getModuleName() {
+            return key1.equals(XmlNetconfConstants.TYPE_KEY) ? value1 : value2;
+        }
+
+        String getInstanceName() {
+            return key1.equals(XmlNetconfConstants.NAME_KEY) ? value1 : value2;
+        }
+
+        HashMap<String, String> getAdditionalKeys(String elementName, String moduleName) {
+            HashMap<String, String> additionalAttributes = Maps.newHashMap();
+
+            runtimeBeanYangName = moduleName;
+            for (String additionalKeyValue : additional.split("/")) {
+                if (Strings.isNullOrEmpty(additionalKeyValue))
+                    continue;
+                Matcher matcher = additionalPattern.matcher(additionalKeyValue);
+                Preconditions
+                        .checkState(
+                                matcher.matches(),
+                                "Attribute %s not in required form on rpc element %s, required format for additional attributes is  %s",
+                                additionalKeyValue, elementName, additionalPatternBlueprint);
+                String name = matcher.group("additionalKey");
+                runtimeBeanYangName = name;
+                additionalAttributes.put(name, matcher.group("additionalValue"));
+            }
+            return additionalAttributes;
+        }
+
+        private String getRuntimeBeanYangName() {
+            Preconditions.checkState(runtimeBeanYangName!=null);
+            return runtimeBeanYangName;
+        }
+    }
 }
index 54deb91..11b8dc6 100644 (file)
@@ -121,8 +121,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         String messageAsString = XmlUtil.toString(message);
 
         try {
-            netconfOperationExecution = getNetconfOperationWithHighestPriority(
-                    message, session);
+            netconfOperationExecution = getNetconfOperationWithHighestPriority(message, session);
         } catch (IllegalArgumentException | IllegalStateException e) {
             logger.warn("Unable to handle rpc {} on session {}", messageAsString, session, e);
 
@@ -140,8 +139,29 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
 
             throw new NetconfDocumentedException(errorMessage, e, NetconfDocumentedException.ErrorType.application,
                     tag, NetconfDocumentedException.ErrorSeverity.error, errorInfo);
+        } catch (RuntimeException e) {
+            throw handleUnexpectedEx("Unexpected exception during netconf operation sort", e);
         }
 
+        try {
+            return executeOperationWithHighestPriority(message, netconfOperationExecution, messageAsString);
+        } catch (RuntimeException e) {
+            throw handleUnexpectedEx("Unexpected exception during netconf operation execution", e);
+        }
+    }
+
+    private NetconfDocumentedException handleUnexpectedEx(String s, Exception e) throws NetconfDocumentedException {
+        logger.error(s, e);
+
+        Map<String, String> info = Maps.newHashMap();
+        info.put(NetconfDocumentedException.ErrorSeverity.error.toString(), e.toString());
+        return new NetconfDocumentedException("Unexpected error",
+                NetconfDocumentedException.ErrorType.application,
+                NetconfDocumentedException.ErrorTag.operation_failed,
+                NetconfDocumentedException.ErrorSeverity.error, info);
+    }
+
+    private Document executeOperationWithHighestPriority(Document message, NetconfOperationExecution netconfOperationExecution, String messageAsString) throws NetconfDocumentedException {
         logger.debug("Forwarding netconf message {} to {}", messageAsString,
                 netconfOperationExecution.operationWithHighestPriority);
 
index 5f6e046..c03254d 100644 (file)
@@ -275,7 +275,7 @@ public class NetconfITTest extends AbstractConfigTest {
                     + "<no-arg xmlns=\""
                     + expectedNamespace
                     + "\">    "
-                    + "<context-instance>/data/modules/module[name='impl-netconf']/instance[name='instance']</context-instance>"
+                    + "<context-instance>/modules/module[type='impl-netconf'][name='instance']</context-instance>"
                     + "<arg1>argument1</arg1>" + "</no-arg>" + "</rpc>";
             final Document doc = XmlUtil.readXmlToDocument(rpc);
             final NetconfMessage message = netconfClient.sendMessage(new NetconfMessage(doc));
index b2a2ee3..413b78c 100644 (file)
@@ -1,6 +1,6 @@
 <rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <no-arg xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
-        <context-instance>/data/modules/module[name='impl-netconf']/instance[name='instance']</context-instance>
+        <context-instance>/modules/module[type='impl-netconf' and name='instance']</context-instance>
         <arg1>
             testarg1
         </arg1>
index 8bc504a..cf15000 100644 (file)
@@ -1,7 +1,7 @@
 <rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <noArgInner xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
         <context-instance>
-            /data/modules/module[name='impl-netconf']/instance[name='instance2']/inner-running-data-additional[key='randomString_1003']
+            /modules/module[name='instance2'][type='impl-netconf']/inner-running-data-additional[key='randomString_1003']
         </context-instance>
     </noArgInner>
 </rpc>
index 2356398..31f417e 100644 (file)
@@ -2,7 +2,7 @@
     <noArgInnerInner
             xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
         <context-instance>
-            /data/modules/module[name='impl-netconf']/instance[name='instance2']/inner-running-data[key='1015']/inner-inner-running-data[key='1017']
+            /modules/module[type='impl-netconf'][name='instance2']/inner-running-data[key='1015']/inner-inner-running-data[key='1017']
         </context-instance>
 
         <arg1>
index 209c382..af0835b 100644 (file)
@@ -2,7 +2,7 @@
     <leaf-list-output
             xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
         <context-instance>
-            /data/modules/module[name='impl-netconf']/instance[name='instance2']/inner-running-data[key='1015']/inner-inner-running-data[key='1017']
+            /modules/module[type='impl-netconf'][name='instance2']/inner-running-data[key='1015']/inner-inner-running-data[key='1017']
         </context-instance>
     </leaf-list-output>
 </rpc>

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.