82232b2d59f795209a9180c28c30ecd12e8e189e
[ccsdk/features.git] /
1 /*
2  * ============LICENSE_START========================================================================
3  * ONAP : ccsdk feature sdnr wt
4  * =================================================================================================
5  * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
6  * =================================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software distributed under the License
13  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
14  * or implied. See the License for the specific language governing permissions and limitations under
15  * the License.
16  * ============LICENSE_END==========================================================================
17  */
18 /**
19  * Convert capabilities of netconfnode into internal format. Boron and Carbon are providing
20  * different versions
21  */
22 package org.onap.ccsdk.features.sdnr.wt.netconfnodestateservice;
23
24 import java.text.DateFormat;
25 import java.text.SimpleDateFormat;
26 import java.util.ArrayList;
27 import java.util.Date;
28 import java.util.List;
29 import java.util.Optional;
30 import javax.annotation.Nullable;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.AvailableCapabilities;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.UnavailableCapabilities;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.unavailable.capabilities.UnavailableCapability;
36 import org.opendaylight.yangtools.yang.common.QName;
37 import org.opendaylight.yangtools.yang.common.Revision;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * Wrapper class for capabilites for Boron and later releases. Uses generics because yang model was changed from Boron
43  * to later version. Interface class:
44  * org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability
45  */
46 public class Capabilities {
47
48     private static final Logger LOG = LoggerFactory.getLogger(Capabilities.class);
49
50     private static final String UNSUPPORTED = "Unsupported";
51     private static final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
52
53     private final List<String> capabilities = new ArrayList<>();
54
55     private Capabilities() {}
56
57     public static Capabilities getAvailableCapabilities(@Nullable NetconfNode nnode) {
58         LOG.info("GetAvailableCapabilities for node");
59         Capabilities capabilities = new Capabilities();
60         if (nnode != null) {
61             AvailableCapabilities availableCapabilites = nnode.getAvailableCapabilities();
62             if (availableCapabilites != null) {
63                 capabilities.constructor(availableCapabilites.getAvailableCapability());
64             } else {
65                 LOG.debug("empty capabilites");
66             }
67         } else {
68             LOG.debug("No node provided");
69         }
70         return capabilities;
71     }
72
73     public static Capabilities getUnavailableCapabilities(NetconfNode nnode) {
74         LOG.info("GetUnavailableCapabilities for node");
75         Capabilities capabilities = new Capabilities();
76         if (nnode != null) {
77             UnavailableCapabilities availableCapabilites = nnode.getUnavailableCapabilities();
78             if (availableCapabilites != null) {
79                 capabilities.constructor2(availableCapabilites.getUnavailableCapability());
80             } else {
81                 LOG.debug("empty capabilites");
82             }
83         } else {
84             LOG.debug("No node provided");
85         }
86         return capabilities;
87     }
88
89
90     /**
91      * Does all construction steps
92      *
93      * @param pcapabilities with a list of capabilities.
94      */
95     private void constructor(List<AvailableCapability> pcapabilities) {
96         if (pcapabilities != null) {
97             for (AvailableCapability capability : pcapabilities) {
98                 this.capabilities.add(capability.getCapability());
99             }
100         }
101     }
102
103     private void constructor2(List<UnavailableCapability> pcapabilities) {
104         if (pcapabilities != null) {
105             for (UnavailableCapability capability : pcapabilities) {
106                 this.capabilities.add(capability.getCapability());
107             }
108         }
109     }
110
111     /**
112      * Get Capabilites
113      *
114      * @return List<String> with capabilites
115      */
116     public List<String> getCapabilities() {
117         return capabilities;
118     }
119
120     /**
121      * Verify if the namespace is supported
122      *
123      * @param qCapability from model
124      * @return true if namespace is supported
125      */
126     public boolean isSupportingNamespace(QName qCapability) {
127         String namespace = qCapability.getNamespace().toString();
128         return isSupportingNamespaceAndRevision(namespace, null);
129     }
130
131     /**
132      * Verify if the namespace is supported
133      *
134      * @param namespace
135      * @return
136      */
137     public boolean isSupportingNamespace(String namespace) {
138         return isSupportingNamespaceAndRevision(namespace, null);
139     }
140
141     /**
142      * check if the namespace and its revision are supported by the given capabilities
143      *
144      * @param qCapability capability from the model
145      * @return true if supporting the model AND revision<br>
146      *         false if revision not available or both not found.
147      */
148     public boolean isSupportingNamespaceAndRevision(QName qCapability) {
149         String namespace = qCapability.getNamespace().toString();
150         String revision = getRevisionString(qCapability);
151         return revision == null ? false : isSupportingNamespaceAndRevision(namespace, revision);
152     }
153
154     /**
155      * Provide namespace and its revision as String.
156      *
157      * @param qCapability capability from the model
158      * @return String
159      */
160     public static String getNamespaceAndRevisionAsString(QName qCapability) {
161         StringBuffer res = new StringBuffer();
162         res.append(qCapability.getNamespace().toString());
163
164         String revisionString = getRevisionString(qCapability);
165         if (revisionString != null) {
166             res.append("?");
167             res.append(revisionString);
168         }
169
170         return res.toString();
171     }
172
173     /**
174      *
175      * @param namespace requested
176      * @param revision request or null for any revision
177      * @return true if existing
178      */
179     public boolean isSupportingNamespaceAndRevision(String namespace, @Nullable String revision) {
180         LOG.trace("isSupportingNamespaceAndRevision: Model namespace {}?[revision {}]", namespace, revision);
181
182         final String nsAndRev = String.format("%s?revision=%s", namespace, revision);
183         for (String capability : capabilities) {
184             //if (capability.contains(namespace) && (revision == null || capability.contains(revision))) {
185             if (capability.contains(revision != null ? nsAndRev : namespace)) {
186                 LOG.trace("Verify true with: {}", capability);
187                 return true;
188             } else {
189                 LOG.trace("Verify false with: {}", capability);
190             }
191         }
192         return false;
193     }
194
195     /**
196      * Provide revision as String from QName, considering older formats.
197      *
198      * @param qCapability that specifies the revision
199      * @return String with revisiondate or null
200      */
201     private static String getRevisionString(QName qCapability) {
202         Object revisionObject = qCapability.getRevision();
203         String revision = null;
204         if (revisionObject instanceof Optional) {
205             if (((Optional<?>) revisionObject).isPresent()) {
206                 revisionObject = ((Optional<?>) revisionObject).get();
207                 LOG.info("Unwrapp Optional: {}", revisionObject != null ? revisionObject.getClass() : null);
208             }
209         }
210         if (revisionObject == null) {
211             // Cover null case
212         } else if (revisionObject instanceof String) {
213             revision = (String) revisionObject;
214         } else if (revisionObject instanceof Date) {
215             revision = formatter.format((Date) revisionObject);
216         } else {
217             revision = revisionObject.toString();
218             LOG.debug("Revision number type not supported. Use toString().String:{} Class:{} ", revisionObject,
219                     revisionObject.getClass().getName());
220         }
221         return revision;
222     }
223
224     /**
225      * Get revision of first entry of related capability
226      *
227      * @param qCapability that specifies the namespace
228      * @return String with date or
229      */
230     public String getRevisionForNamespace(QName qCapability) {
231         String namespace = qCapability.getNamespace().toString();
232         for (String capability : capabilities) {
233             if (capability.contains(namespace)) {
234                 Optional<Revision> revisionOpt = QName.create(capability).getRevision();
235                 if (revisionOpt.isPresent()) {
236                     return revisionOpt.get().toString();
237                 }
238             }
239         }
240         return UNSUPPORTED;
241     }
242
243     /**
244      * Verify if QName namespace is supported by capabilities
245      *
246      * @param revision result of getRevisionForNamespace()
247      * @return true if namespace is supported.
248      */
249     static public boolean isNamespaceSupported(String revision) {
250         return !UNSUPPORTED.equals(revision);
251     }
252
253     @Override
254     public String toString() {
255         return "Capabilities [capabilities=" + capabilities + "]";
256     }
257
258 }