Merge "BUG-832 Refactor netconf connector"
[controller.git] / opendaylight / md-sal / sal-netconf-connector / src / main / java / org / opendaylight / controller / sal / connect / netconf / listener / NetconfSessionCapabilities.java
1 package org.opendaylight.controller.sal.connect.netconf.listener;
2
3 import java.util.Arrays;
4 import java.util.Collection;
5 import java.util.Set;
6
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;
12
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;
19
20 public final class NetconfSessionCapabilities {
21
22     private static final Logger logger = LoggerFactory.getLogger(NetconfSessionCapabilities.class);
23
24     private final Set<String> capabilities;
25
26     private final Set<QName> moduleBasedCaps;
27
28     private NetconfSessionCapabilities(final Set<String> capabilities, final Set<QName> moduleBasedCaps) {
29         this.capabilities = capabilities;
30         this.moduleBasedCaps = moduleBasedCaps;
31     }
32
33     public Set<QName> getModuleBasedCaps() {
34         return moduleBasedCaps;
35     }
36
37     public boolean containsCapability(final String capability) {
38         return capabilities.contains(capability);
39     }
40
41     public boolean containsCapability(final QName capability) {
42         return moduleBasedCaps.contains(capability);
43     }
44
45     @Override
46     public String toString() {
47         return Objects.toStringHelper(this)
48                 .add("capabilities", capabilities)
49                 .add("rollback", isRollbackSupported())
50                 .add("monitoring", isMonitoringSupported())
51                 .toString();
52     }
53
54     public boolean isRollbackSupported() {
55         return containsCapability(NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString());
56     }
57
58     public boolean isMonitoringSupported() {
59         return containsCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING)
60                 || containsCapability(NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString());
61     }
62
63     public static NetconfSessionCapabilities fromNetconfSession(final NetconfClientSession session) {
64         return fromStrings(session.getServerCapabilities());
65     }
66
67     public static NetconfSessionCapabilities fromStrings(final Collection<String> capabilities) {
68         final Set<QName> moduleBasedCaps = Sets.newHashSet();
69
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("&")));
75
76                 String revision = getStringAndTransform(queryParams, "revision=", "revision=");
77
78                 final String moduleName = getStringAndTransform(queryParams, "module=", "module=");
79
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=");
83
84                     if (revision == null) {
85                         logger.warn("Netconf device returned revision incorrectly escaped for {}", capability);
86                     }
87                 }
88                 moduleBasedCaps.add(QName.create(namespace, revision, moduleName));
89             }
90         }
91
92         return new NetconfSessionCapabilities(Sets.newHashSet(capabilities), moduleBasedCaps);
93     }
94
95     private static boolean isModuleBasedCapability(final String capability) {
96         return capability.contains("?") && capability.contains("module=") && capability.contains("revision=");
97     }
98
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>() {
102             @Override
103             public boolean apply(final String input) {
104                 return input.startsWith(match);
105             }
106         });
107
108         return found.isPresent() ? found.get().replaceAll(substringToRemove, "") : null;
109     }
110
111 }