2 * Copyright (c) 2015, 2017 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.config.facade.xml.rpc;
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Preconditions;
13 import com.google.common.base.Strings;
14 import com.google.common.collect.Maps;
15 import java.util.HashMap;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
19 import javax.management.ObjectName;
20 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
21 import org.opendaylight.controller.config.util.xml.XmlMappingConstants;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.Modules;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.rev130405.modules.Module;
26 * Represents parsed xpath to runtime bean instance.
28 public final class RuntimeRpcElementResolved {
29 private final String moduleName;
30 private final String instanceName;
31 private final String namespace;
32 private final String runtimeBeanName;
33 private final Map<String, String> additionalAttributes;
35 private RuntimeRpcElementResolved(String namespace, String moduleName, String instanceName, String runtimeBeanName,
36 Map<String, String> additionalAttributes) {
37 this.moduleName = Preconditions.checkNotNull(moduleName, "Module name");
38 this.instanceName = Preconditions.checkNotNull(instanceName, "Instance name");
39 this.additionalAttributes = additionalAttributes;
40 this.namespace = Preconditions.checkNotNull(namespace, "Namespace");
41 this.runtimeBeanName = Preconditions.checkNotNull(runtimeBeanName, "Runtime bean name");
44 public String getModuleName() {
49 Map<String, String> getAdditionalAttributes() {
50 return additionalAttributes;
53 public String getInstanceName() {
57 public String getNamespace() {
61 public String getRuntimeBeanName() {
62 return runtimeBeanName;
65 public ObjectName getObjectName(ModuleRpcs rpcMapping) {
66 Map<String, String> additionalAttributesJavaNames = Maps
67 .newHashMapWithExpectedSize(additionalAttributes.size());
68 for (String attributeYangName : additionalAttributes.keySet()) {
69 String attributeJavaName = rpcMapping.getRbeJavaName(attributeYangName);
70 Preconditions.checkState(attributeJavaName != null,
71 "Cannot find java name for runtime bean wtih yang name %s", attributeYangName);
72 additionalAttributesJavaNames.put(attributeJavaName, additionalAttributes.get(attributeYangName));
74 return ObjectNameUtil.createRuntimeBeanName(moduleName, instanceName, additionalAttributesJavaNames);
78 * Pattern for an absolute instance identifier xpath pointing to a runtime bean.
82 * /modules/module[name=instanceName][type=moduleType]
89 * /a:modules/a:module[a:name=instanceName][a:type=moduleType]
92 private static final String XPATH_PATTERN_BLUEPRINT = "/" + getRegExForPrefixedName(Modules.QNAME.getLocalName())
93 + "/" + getRegExForPrefixedName(Module.QNAME.getLocalName())
95 + "\\[" + "(?<key1>" + getRegExForPrefixedName(XmlMappingConstants.TYPE_KEY) + "|"
96 + getRegExForPrefixedName(XmlMappingConstants.NAME_KEY) + ")" + "=('|\")?(?<value1>[^'\"\\]]+)('|\")?"
97 + "( and |\\]\\[)" + "(?<key2>" + getRegExForPrefixedName(XmlMappingConstants.TYPE_KEY) + "|"
98 + getRegExForPrefixedName(XmlMappingConstants.NAME_KEY) + ")" + "=('|\")?(?<value2>[^'\"\\]]+)('|\")?"
101 + "(?<additional>.*)";
104 * Return reg ex that matches either the name with or without a prefix.
106 private static String getRegExForPrefixedName(final String name) {
107 return "([^:]+:)?" + name;
110 private static final Pattern XPATH_PATTERN = Pattern.compile(XPATH_PATTERN_BLUEPRINT);
113 * Pattern for additional path elements inside xpath for instance identifier
114 * pointing to an inner runtime bean. E.g:
117 * /modules/module[name=instanceName and type=moduleType]/inner[key=b]
120 private static final String ADDITIONAL_PATTERN_BLUEPRINT = getRegExForPrefixedName("(?<additionalKey>.+)")
121 + "\\[(?<prefixedKey>" + getRegExForPrefixedName("(.+)")
122 + ")=('|\")?(?<additionalValue>[^'\"\\]]+)('|\")?\\]";
123 private static final Pattern ADDITIONAL_PATTERN = Pattern.compile(ADDITIONAL_PATTERN_BLUEPRINT);
125 public static RuntimeRpcElementResolved fromXpath(String xpath, String elementName, String namespace) {
126 Matcher matcher = XPATH_PATTERN.matcher(xpath);
127 Preconditions.checkState(matcher.matches(),
128 "Node %s with value '%s' not in required form on rpc element %s, required format is %s",
129 // TODO refactor this string, and/or unify with RPR.CONTEXT_INSTANCE from
131 "context-instance", xpath, elementName, XPATH_PATTERN_BLUEPRINT);
133 PatternGroupResolver groups = new PatternGroupResolver(matcher.group("key1"), matcher.group("value1"),
134 matcher.group("value2"), matcher.group("additional"));
136 String moduleName = groups.getModuleName();
137 String instanceName = groups.getInstanceName();
139 Map<String, String> additionalAttributes = groups.getAdditionalKeys(elementName, moduleName);
141 return new RuntimeRpcElementResolved(namespace, moduleName, instanceName, groups.getRuntimeBeanYangName(),
142 additionalAttributes);
145 private static final class PatternGroupResolver {
147 private final String key1;
148 private final String value1;
149 private final String value2;
150 private final String additional;
151 private String runtimeBeanYangName;
153 PatternGroupResolver(String key1, String value1, String value2, String additional) {
154 this.key1 = Preconditions.checkNotNull(key1);
155 this.value1 = Preconditions.checkNotNull(value1);
156 this.value2 = Preconditions.checkNotNull(value2);
157 this.additional = Preconditions.checkNotNull(additional);
160 String getModuleName() {
161 return key1.contains(XmlMappingConstants.TYPE_KEY) ? value1 : value2;
164 String getInstanceName() {
165 return key1.contains(XmlMappingConstants.NAME_KEY) ? value1 : value2;
168 Map<String, String> getAdditionalKeys(String elementName, String moduleName) {
169 HashMap<String, String> additionalAttributes = Maps.newHashMap();
171 runtimeBeanYangName = moduleName;
172 for (String additionalKeyValue : additional.split("/")) {
173 if (Strings.isNullOrEmpty(additionalKeyValue)) {
176 Matcher matcher = ADDITIONAL_PATTERN.matcher(additionalKeyValue);
177 Preconditions.checkState(matcher.matches(),
178 "Attribute %s not in required form on rpc element %s,"
179 + " required format for additional attributes is: %s",
180 additionalKeyValue, elementName, ADDITIONAL_PATTERN_BLUEPRINT);
181 String name = matcher.group("additionalKey");
182 runtimeBeanYangName = name;
183 additionalAttributes.put(name, matcher.group("additionalValue"));
185 return additionalAttributes;
188 private String getRuntimeBeanYangName() {
189 Preconditions.checkState(runtimeBeanYangName != null);
190 return runtimeBeanYangName;