1 package org.opendaylight.controller.sal.connect.netconf.listener;
3 import java.util.Arrays;
4 import java.util.Collection;
7 import org.opendaylight.controller.netconf.client.NetconfClientSession;
8 import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
9 import org.opendaylight.yangtools.yang.common.QName;
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
13 import com.google.common.base.Objects;
14 import com.google.common.base.Optional;
15 import com.google.common.base.Predicate;
16 import com.google.common.collect.FluentIterable;
17 import com.google.common.collect.Iterables;
18 import com.google.common.collect.Sets;
20 public final class NetconfSessionCapabilities {
22 private static final Logger logger = LoggerFactory.getLogger(NetconfSessionCapabilities.class);
24 private final Set<String> capabilities;
26 private final Set<QName> moduleBasedCaps;
28 private NetconfSessionCapabilities(final Set<String> capabilities, final Set<QName> moduleBasedCaps) {
29 this.capabilities = capabilities;
30 this.moduleBasedCaps = moduleBasedCaps;
33 public Set<QName> getModuleBasedCaps() {
34 return moduleBasedCaps;
37 public boolean containsCapability(final String capability) {
38 return capabilities.contains(capability);
41 public boolean containsCapability(final QName capability) {
42 return moduleBasedCaps.contains(capability);
46 public String toString() {
47 return Objects.toStringHelper(this)
48 .add("capabilities", capabilities)
49 .add("rollback", isRollbackSupported())
50 .add("monitoring", isMonitoringSupported())
54 public boolean isRollbackSupported() {
55 return containsCapability(NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString());
58 public boolean isMonitoringSupported() {
59 return containsCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING)
60 || containsCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString());
63 public static NetconfSessionCapabilities fromNetconfSession(final NetconfClientSession session) {
64 return fromStrings(session.getServerCapabilities());
67 public static NetconfSessionCapabilities fromStrings(final Collection<String> capabilities) {
68 final Set<QName> moduleBasedCaps = Sets.newHashSet();
70 for (final String capability : capabilities) {
71 if(isModuleBasedCapability(capability)) {
72 final String[] parts = capability.split("\\?");
73 final String namespace = parts[0];
74 final FluentIterable<String> queryParams = FluentIterable.from(Arrays.asList(parts[1].split("&")));
76 String revision = getStringAndTransform(queryParams, "revision=", "revision=");
78 final String moduleName = getStringAndTransform(queryParams, "module=", "module=");
80 if (revision == null) {
81 logger.debug("Netconf device was not reporting revision correctly, trying to get amp;revision=");
82 revision = getStringAndTransform(queryParams, "amp;revision=", "amp;revision=");
84 if (revision == null) {
85 logger.warn("Netconf device returned revision incorrectly escaped for {}", capability);
88 moduleBasedCaps.add(QName.create(namespace, revision, moduleName));
92 return new NetconfSessionCapabilities(Sets.newHashSet(capabilities), moduleBasedCaps);
95 private static boolean isModuleBasedCapability(final String capability) {
96 return capability.contains("?") && capability.contains("module=") && capability.contains("revision=");
99 private static String getStringAndTransform(final Iterable<String> queryParams, final String match,
100 final String substringToRemove) {
101 final Optional<String> found = Iterables.tryFind(queryParams, new Predicate<String>() {
103 public boolean apply(final String input) {
104 return input.startsWith(match);
108 return found.isPresent() ? found.get().replaceAll(substringToRemove, "") : null;