import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
Preconditions.checkNotNull(rpcName);
Preconditions.checkNotNull(schemaContext);
- final NodeContainerProxy rpcBodyProxy = new NodeContainerProxy(rpcName, schemaContext.getChildNodes());
- return new NodeContainerProxy(NETCONF_RPC_QNAME, Sets.<DataSchemaNode>newHashSet(rpcBodyProxy));
+ for (final RpcDefinition rpcDefinition : schemaContext.getOperations()) {
+ if(rpcDefinition.getQName().equals(rpcName)) {
+ final NodeContainerProxy rpcBodyProxy = new NodeContainerProxy(rpcName, rpcDefinition.getInput().getChildNodes());
+ return new NodeContainerProxy(NETCONF_RPC_QNAME, Sets.<DataSchemaNode>newHashSet(rpcBodyProxy));
+ }
+ }
+ throw new IllegalArgumentException("Rpc " + rpcName + " not found in schema context " + schemaContext + ". Unable to invoke Rpc");
}
public static CompositeNodeTOImpl wrap(final QName name, final Node<?> node) {
assertEquals(streamName.getLocalName(), "stream-name");
}
- @Test
- public void testNoSchemaContextToRpcRequest() throws Exception {
- final String exampleNamespace = "http://example.net/me/my-own/1.0";
- final String exampleRevision = "2014-07-22";
- final QName myOwnMethodRpcQName = QName.create(exampleNamespace, exampleRevision, "my-own-method");
-
- final CompositeNodeBuilder<ImmutableCompositeNode> rootBuilder = ImmutableCompositeNode.builder();
- rootBuilder.setQName(myOwnMethodRpcQName);
-
- final CompositeNodeBuilder<ImmutableCompositeNode> inputBuilder = ImmutableCompositeNode.builder();
- inputBuilder.setQName(QName.create(exampleNamespace, exampleRevision, "input"));
- inputBuilder.addLeaf(QName.create(exampleNamespace, exampleRevision, "my-first-parameter"), "14");
- inputBuilder.addLeaf(QName.create(exampleNamespace, exampleRevision, "another-parameter"), "fred");
-
- rootBuilder.add(inputBuilder.toInstance());
- final ImmutableCompositeNode root = rootBuilder.toInstance();
-
- final NetconfMessage message = messageTransformer.toRpcRequest(myOwnMethodRpcQName, root);
- assertNotNull(message);
-
- final Document xmlDoc = message.getDocument();
- final org.w3c.dom.Node rpcChild = xmlDoc.getFirstChild();
- assertEquals(rpcChild.getLocalName(), "rpc");
-
- final org.w3c.dom.Node myOwnMethodNode = rpcChild.getFirstChild();
- assertEquals(myOwnMethodNode.getLocalName(), "my-own-method");
-
- final org.w3c.dom.Node firstParamNode = myOwnMethodNode.getFirstChild();
- assertEquals(firstParamNode.getLocalName(), "my-first-parameter");
-
- final org.w3c.dom.Node secParamNode = firstParamNode.getNextSibling();
- assertEquals(secParamNode.getLocalName(), "another-parameter");
- }
}
org.opendaylight.controller.netconf.confignetconfconnector.util,
org.opendaylight.controller.netconf.confignetconfconnector.osgi,
org.opendaylight.controller.netconf.confignetconfconnector.exception,</Private-Package>
- <Import-Package>com.google.common.base,
- com.google.common.collect,
- javax.annotation,
- javax.management,
- javax.management.openmbean,
- org.opendaylight.controller.config.api,
- org.opendaylight.controller.config.api.jmx,
- org.opendaylight.controller.config.yangjmxgenerator,
- org.opendaylight.controller.config.yangjmxgenerator.attribute,
- org.opendaylight.controller.netconf.api,
- org.opendaylight.controller.netconf.mapping.api,
- org.opendaylight.controller.netconf.util.mapping,
- org.opendaylight.controller.netconf.util.xml,
- org.opendaylight.controller.netconf.util.exception,
- org.opendaylight.yangtools.yang.common,
- org.opendaylight.yangtools.yang.model.api,
- org.osgi.framework,
- org.osgi.util.tracker,
- org.slf4j,
- org.w3c.dom,
- com.google.common.io,
- org.opendaylight.yangtools.yang.model.api.type,
- org.opendaylight.yangtools.sal.binding.generator.spi,
- org.opendaylight.yangtools.sal.binding.yang.types,
- org.opendaylight.controller.config.util
- </Import-Package>
+ <Import-Package>*</Import-Package>
<Export-Package></Export-Package>
</instructions>
</configuration>
package org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
-import com.google.common.collect.Maps;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.management.ObjectName;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc.ModuleRpcs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.Modules;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.Module;
-import javax.management.ObjectName;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.Maps;
/**
* Represents parsed xpath to runtime bean instance
return moduleName;
}
+ @VisibleForTesting
+ Map<String, String> getAdditionalAttributes() {
+ return additionalAttributes;
+ }
+
public String getInstanceName() {
return instanceName;
}
return ObjectNameUtil.createRuntimeBeanName(moduleName, instanceName, additionalAttributesJavaNames);
}
+ /**
+ * Pattern for an absolute instance identifier xpath pointing to a runtime bean instance e.g:
+ * <pre>
+ * /modules/module[name=instanceName][type=moduleType]
+ * </pre>
+ * or
+ * <pre>
+ * /a:modules/a:module[a:name=instanceName][a:type=moduleType]
+ * </pre>
+ */
private static final String xpathPatternBlueprint =
- "/" + XmlNetconfConstants.MODULES_KEY
- + "/" + XmlNetconfConstants.MODULE_KEY
- + "\\["
-
- + "(?<key1>type|name)"
- + "='(?<value1>[^']+)'"
- + "( and |\\]\\[)"
- + "(?<key2>type|name)"
- + "='(?<value2>[^']+)'"
-
- + "\\]"
- + "(?<additional>.*)";
+ "/" + getRegExForPrefixedName(Modules.QNAME.getLocalName())+ "/" + getRegExForPrefixedName(Module.QNAME.getLocalName())
+
+ + "\\["
+ + "(?<key1>" + getRegExForPrefixedName(XmlNetconfConstants.TYPE_KEY) + "|" + getRegExForPrefixedName(XmlNetconfConstants.NAME_KEY) + ")"
+ + "=('|\")?(?<value1>[^'\"\\]]+)('|\")?"
+ + "( and |\\]\\[)"
+ + "(?<key2>" + getRegExForPrefixedName(XmlNetconfConstants.TYPE_KEY) + "|" + getRegExForPrefixedName(XmlNetconfConstants.NAME_KEY) + ")"
+ + "=('|\")?(?<value2>[^'\"\\]]+)('|\")?"
+ + "\\]"
+
+ + "(?<additional>.*)";
+
+ /**
+ * Return reg ex that matches either the name with or without a prefix
+ */
+ private static String getRegExForPrefixedName(final String name) {
+ return "([^:]+:)?" + name;
+ }
private static final Pattern xpathPattern = Pattern.compile(xpathPatternBlueprint);
- private static final String additionalPatternBlueprint = "(?<additionalKey>.+)\\[(.+)='(?<additionalValue>.+)'\\]";
+
+ /**
+ * Pattern for additional path elements inside xpath for instance identifier pointing to an inner runtime bean e.g:
+ * <pre>
+ * /modules/module[name=instanceName and type=moduleType]/inner[key=b]
+ * </pre>
+ */
+ private static final String additionalPatternBlueprint = getRegExForPrefixedName("(?<additionalKey>.+)") + "\\[(?<prefixedKey>" + getRegExForPrefixedName("(.+)") + ")=('|\")?(?<additionalValue>[^'\"\\]]+)('|\")?\\]";
private static final Pattern additionalPattern = Pattern.compile(additionalPatternBlueprint);
public static RuntimeRpcElementResolved fromXpath(String xpath, String elementName, String namespace) {
PatternGroupResolver(String key1, String value1, String value2, String additional) {
this.key1 = Preconditions.checkNotNull(key1);
this.value1 = Preconditions.checkNotNull(value1);
-
this.value2 = Preconditions.checkNotNull(value2);
-
this.additional = Preconditions.checkNotNull(additional);
}
String getModuleName() {
- return key1.equals(XmlNetconfConstants.TYPE_KEY) ? value1 : value2;
+ return key1.contains(XmlNetconfConstants.TYPE_KEY) ? value1 : value2;
}
String getInstanceName() {
- return key1.equals(XmlNetconfConstants.NAME_KEY) ? value1 : value2;
+ return key1.contains(XmlNetconfConstants.NAME_KEY) ? value1 : value2;
}
+
Map<String, String> getAdditionalKeys(String elementName, String moduleName) {
HashMap<String, String> additionalAttributes = Maps.newHashMap();
Preconditions
.checkState(
matcher.matches(),
- "Attribute %s not in required form on rpc element %s, required format for additional attributes is %s",
+ "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;
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class RuntimeRpcElementResolvedTest {
+
+ private static final String MODULE_TYPE = "moduleType";
+ private static final String INSTANCE_NAME = "instanceName";
+ @Parameterized.Parameter(0)
+ public String xpath;
+ @Parameterized.Parameter(1)
+ public Map<String, String> additional;
+
+ @Parameterized.Parameters(name = "{index}: parsed({0}) contains moduleName:{1} and instanceName:{2}")
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][] {
+ // With namespaces
+ { "/a:modules/a:module[a:name='instanceName'][a:type='moduleType']/b:listener-state[b:peer-id='127.0.0.1']",
+ new HashMap<String, String>() {{
+ put("listener-state", "127.0.0.1");
+ }}},
+ { "/a:modules/a:module[a:name='instanceName'][a:type='moduleType']",
+ null},
+
+ // Without namespaces
+ { "/modules/module[name=instanceName][type=moduleType]", null},
+ { "/modules/module[type=moduleType][name='instanceName']", null},
+ { "/modules/module[name=\'instanceName\'][type=\"moduleType\"]", null},
+ { "/modules/module[type=moduleType and name=instanceName]", null},
+ { "/modules/module[name=\"instanceName\" and type=moduleType]", null},
+ { "/modules/module[type=\"moduleType\" and name=instanceName]", null},
+ { "/modules/module[name=\'instanceName\' and type=\"moduleType\"]", null},
+
+ // With inner beans
+ { "/modules/module[name=instanceName and type=\"moduleType\"]/inner[key=b]", Collections.singletonMap("inner", "b")},
+ { "/modules/module[name=instanceName and type=moduleType]/inner[key=b]", Collections.singletonMap("inner", "b")},
+ { "/modules/module[name=instanceName and type=moduleType]/inner[key=\'b\']", Collections.singletonMap("inner", "b")},
+ { "/modules/module[name=instanceName and type=moduleType]/inner[key=\"b\"]", Collections.singletonMap("inner", "b")},
+
+ { "/modules/module[name=instanceName and type=\"moduleType\"]/inner[key2=a]/inner2[key=b]",
+ new HashMap<String, String>() {{
+ put("inner", "a");
+ put("inner2", "b");
+ }}
+ },
+ });
+ }
+
+ @Test
+ public void testFromXpath() throws Exception {
+ final RuntimeRpcElementResolved resolved = RuntimeRpcElementResolved.fromXpath(xpath, "element", "namespace");
+ assertEquals(MODULE_TYPE, resolved.getModuleName());
+ assertEquals(INSTANCE_NAME, resolved.getInstanceName());
+ if (additional != null) {
+ assertEquals(additional, resolved.getAdditionalAttributes());
+ }
+ }
+}