Merge "fix oauth code"
[ccsdk/features.git] / sdnr / wt / netconfnode-state-service / model / src / main / java / org / onap / ccsdk / features / sdnr / wt / netconfnodestateservice / Capabilities.java
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.eclipse.jdt.annotation.NonNull;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev221225.connection.oper.AvailableCapabilities;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev221225.connection.oper.UnavailableCapabilities;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev221225.connection.oper.available.capabilities.AvailableCapability;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev221225.connection.oper.unavailable.capabilities.UnavailableCapability;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNode;
37 import org.opendaylight.yangtools.yang.common.QName;
38 import org.opendaylight.yangtools.yang.common.QNameModule;
39 import org.opendaylight.yangtools.yang.common.Revision;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 /**
44  * Wrapper class for capabilites for Boron and later releases. Uses generics because yang model was changed from Boron
45  * to later version. Interface class:
46  * org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability
47  */
48 public class Capabilities {
49
50     private static final Logger LOG = LoggerFactory.getLogger(Capabilities.class);
51
52     private static final String UNSUPPORTED = "Unsupported";
53     private static final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
54
55     private final List<String> capabilities = new ArrayList<>();
56
57     private Capabilities() {}
58
59     public static Capabilities getAvailableCapabilities(@Nullable NetconfNode nnode) {
60         LOG.debug("GetAvailableCapabilities for node");
61         Capabilities capabilities = new Capabilities();
62         if (nnode != null) {
63             AvailableCapabilities availableCapabilites = nnode.getAvailableCapabilities();
64             if (availableCapabilites != null) {
65                 capabilities.constructor(availableCapabilites.getAvailableCapability());
66             } else {
67                 LOG.debug("empty capabilites");
68             }
69         } else {
70             LOG.debug("No node provided");
71         }
72         return capabilities;
73     }
74
75     public static Capabilities getUnavailableCapabilities(NetconfNode nnode) {
76         LOG.debug("GetUnavailableCapabilities for node");
77         Capabilities capabilities = new Capabilities();
78         if (nnode != null) {
79             UnavailableCapabilities availableCapabilites = nnode.getUnavailableCapabilities();
80             if (availableCapabilites != null) {
81                 capabilities.constructor2(availableCapabilites.getUnavailableCapability());
82             } else {
83                 LOG.debug("empty capabilites");
84             }
85         } else {
86             LOG.debug("No node provided");
87         }
88         return capabilities;
89     }
90
91
92     /**
93      * Does all construction steps
94      *
95      * @param pcapabilities with a list of capabilities.
96      */
97     private void constructor(List<AvailableCapability> pcapabilities) {
98         if (pcapabilities != null) {
99             for (AvailableCapability capability : pcapabilities) {
100                 this.capabilities.add(capability.getCapability());
101             }
102         }
103     }
104
105     private void constructor2(List<UnavailableCapability> pcapabilities) {
106         if (pcapabilities != null) {
107             for (UnavailableCapability capability : pcapabilities) {
108                 this.capabilities.add(capability.getCapability());
109             }
110         }
111     }
112
113     /**
114      * Get Capabilites
115      *
116      * @return List<String> with capabilites
117      */
118     public List<String> getCapabilities() {
119         return capabilities;
120     }
121
122     /**
123      * Verify if the namespace is supported
124      *
125      * @param qCapability from model
126      * @return true if namespace is supported
127      */
128     public boolean isSupportingNamespace(QName qCapability) {
129         String namespace = qCapability.getNamespace().toString();
130         return isSupportingNamespaceAndRevision(namespace, null);
131     }
132
133     /**
134      * Verify if the namespace is supported
135      *
136      * @param namespace
137      * @return
138      */
139     public boolean isSupportingNamespace(String namespace) {
140         return isSupportingNamespaceAndRevision(namespace, null);
141     }
142
143     /**
144      * check if the namespace and its revision are supported by the given capabilities
145      *
146      * @param qCapability capability from the model
147      * @return true if supporting the model AND revision<br>
148      *         false if revision not available or both not found.
149      */
150     public boolean isSupportingNamespaceAndRevision(QName qCapability) {
151         String namespace = qCapability.getNamespace().toString();
152         String revision = getRevisionString(qCapability);
153         return revision == null ? false : isSupportingNamespaceAndRevision(namespace, revision);
154     }
155
156     /**
157      * check if the namespace and its revision of module are supported by the given capabilities
158      *
159      * @param module
160      * @return true if supporting the model AND revision<br>
161      *         false if revision not available or both not found.
162      */
163     public boolean isSupportingNamespaceAndRevision(QNameModule module) {
164         String namespace = module.getNamespace().toString();
165         @NonNull Optional<Revision> revision = module.getRevision();
166         return revision.isEmpty() ? false : isSupportingNamespaceAndRevision(namespace, revision.get().toString());
167     }
168
169     /**
170      * Provide namespace and its revision as String.
171      *
172      * @param qCapability capability from the model
173      * @return String
174      */
175     public static String getNamespaceAndRevisionAsString(QName qCapability) {
176         StringBuffer res = new StringBuffer();
177         res.append(qCapability.getNamespace().toString());
178
179         String revisionString = getRevisionString(qCapability);
180         if (revisionString != null) {
181             res.append("?");
182             res.append(revisionString);
183         }
184
185         return res.toString();
186     }
187
188     /**
189      *
190      * @param namespace requested
191      * @param revision request or null for any revision
192      * @return true if existing
193      */
194     public boolean isSupportingNamespaceAndRevision(String namespace, @Nullable String revision) {
195         LOG.trace("isSupportingNamespaceAndRevision: Model namespace {}?[revision {}]", namespace, revision);
196
197         final String nsAndRev = String.format("%s?revision=%s", namespace, revision);
198         for (String capability : capabilities) {
199             //if (capability.contains(namespace) && (revision == null || capability.contains(revision))) {
200             if (capability.contains(revision != null ? nsAndRev : namespace)) {
201                 LOG.trace("Verify true with: {}", capability);
202                 return true;
203             } else {
204                 LOG.trace("Verify false with: {}", capability);
205             }
206         }
207         return false;
208     }
209
210     /**
211      * Provide revision as String from QName, considering older formats.
212      *
213      * @param qCapability that specifies the revision
214      * @return String with revisiondate or null
215      */
216     private static String getRevisionString(QName qCapability) {
217         Object revisionObject = qCapability.getRevision();
218         String revision = null;
219         if (revisionObject instanceof Optional) {
220             if (((Optional<?>) revisionObject).isPresent()) {
221                 revisionObject = ((Optional<?>) revisionObject).get();
222                 LOG.debug("Unwrapp Optional: {}", revisionObject != null ? revisionObject.getClass() : null);
223             }
224         }
225         if (revisionObject == null) {
226             // Cover null case
227         } else if (revisionObject instanceof String) {
228             revision = (String) revisionObject;
229         } else if (revisionObject instanceof Date) {
230             revision = formatter.format((Date) revisionObject);
231         } else {
232             revision = revisionObject.toString();
233             LOG.debug("Revision number type not supported. Use toString().String:{} Class:{} ", revisionObject,
234                     revisionObject.getClass().getName());
235         }
236         return revision;
237     }
238
239     /**
240      * Get revision of first entry of related capability
241      *
242      * @param qCapability that specifies the namespace
243      * @return String with date or
244      */
245     public String getRevisionForNamespace(QName qCapability) {
246         String namespace = qCapability.getNamespace().toString();
247         for (String capability : capabilities) {
248             if (capability.contains(namespace)) {
249                 Optional<Revision> revisionOpt = QName.create(capability).getRevision();
250                 if (revisionOpt.isPresent()) {
251                     return revisionOpt.get().toString();
252                 }
253             }
254         }
255         return UNSUPPORTED;
256     }
257
258     /**
259      * Verify if QName namespace is supported by capabilities
260      *
261      * @param revision result of getRevisionForNamespace()
262      * @return true if namespace is supported.
263      */
264     static public boolean isNamespaceSupported(String revision) {
265         return !UNSUPPORTED.equals(revision);
266     }
267
268     @Override
269     public String toString() {
270         return "Capabilities [capabilities=" + capabilities + "]";
271     }
272
273 }