e773da52b48e5b4bcfad58136e32e2d9f686059f
[ccsdk/sli/adaptors.git] / aai-service / provider / src / main / java / org / onap / ccsdk / sli / adaptors / aai / AAIServiceUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : SDN-C
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *             reserved.
7  * ================================================================================
8  * Modifications Copyright (C) 2018 IBM.
9  * ================================================================================
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  * ============LICENSE_END=========================================================
22  */
23 /**
24  * @author Rich Tabedzki
25  *
26  */
27 package org.onap.ccsdk.sli.adaptors.aai;
28
29 import java.lang.annotation.Annotation;
30 import java.lang.reflect.Method;
31 import java.net.MalformedURLException;
32 import java.net.URI;
33 import java.net.URISyntaxException;
34 import java.util.Arrays;
35 import java.util.HashMap;
36 import java.util.Map;
37 import java.util.HashSet;
38 import java.util.Iterator;
39 import java.util.LinkedList;
40 import java.util.List;
41 import java.util.Set;
42
43 import javax.xml.bind.annotation.XmlType;
44
45 import org.apache.commons.lang.StringUtils;
46 import org.onap.aai.inventory.v14.Relationship;
47 import org.onap.aai.inventory.v14.RelationshipData;
48 import org.onap.aai.inventory.v14.RelationshipList;
49 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
50 import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 public class AAIServiceUtils {
55
56     private static final String VERSION_PATTERN = "/v$/";
57
58     private static final Logger LOG = LoggerFactory.getLogger(AAIService.class);
59
60     private AAIServiceUtils() {
61     }
62
63     public static String getPrimaryIdFromClass(Class<? extends AAIDatum> resourceClass){
64         // 1. find class
65         getLogger().debug(resourceClass.getName());
66
67         try {
68             Annotation[] annotations = resourceClass.getAnnotations();
69             for(Annotation annotation : annotations) {
70                 Class<? extends Annotation> anotationType = annotation.annotationType();
71                 String annotationName = anotationType.getName();
72
73                 // 2. find string property setters and getters for the lists
74                 if("javax.xml.bind.annotation.XmlType".equals(annotationName)){
75                     XmlType order = (XmlType)annotation;
76                     String[]  values = order.propOrder();
77                     for(String value : values) {
78                         String id = camelCaseToDashedString(value);
79                         return id;
80                     }
81                 }
82             }
83         } catch(Exception exc) {
84             getLogger().warn("getPrimaryIdFromClass failed", exc);
85         }
86         return null;
87     }
88
89     public static String getSecondaryIdFromClass(Class<? extends AAIDatum> resourceClass){
90         getLogger().debug(resourceClass.getName());
91
92         try {
93             Annotation[] annotations = resourceClass.getAnnotations();
94             for(Annotation annotation : annotations) {
95                 Class<? extends Annotation> anotationType = annotation.annotationType();
96                 String annotationName = anotationType.getName();
97
98                 // 2. find string property setters and getters for the lists
99                 if("javax.xml.bind.annotation.XmlType".equals(annotationName)){
100                     boolean primaryIdFound = false;
101                     XmlType order = (XmlType)annotation;
102                     String[]  values = order.propOrder();
103                     for(String value : values) {
104                         String id = camelCaseToDashedString(value);
105                         if(primaryIdFound) {
106                             return id;
107                         } else {
108                             primaryIdFound = true;
109                         }
110                     }
111                 }
112             }
113         } catch(Exception exc) {
114
115         }
116         return null;
117     }
118
119     public static Method getRelationshipListGetterMethodFromClassDefinition(Class resourceClass) {
120         Method getRelationshipListMethod = null;
121
122         try {
123              getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
124         } catch(Exception exc) {
125             getLogger().debug("Retrofiting relationship data: " + exc.getMessage());
126         }
127         return getRelationshipListMethod;
128     }
129
130     private static Logger getLogger() {
131         return LOG;
132     }
133
134
135     private static final String regex = "([A-Z][a-z,0-9]+)";
136     private static final String replacement = "-$1";
137
138     public static String camelCaseToDashedString(String propOrder) {
139         return propOrder.replaceAll(regex, replacement).toLowerCase();
140     }
141
142     public static HashMap<String,String> keyToHashMap(String key,    SvcLogicContext ctx) {
143         if (key == null) {
144             return (null);
145         }
146
147         getLogger().debug("Converting key [" + key + "] to where clause");
148
149         if (key.startsWith("'") && key.endsWith("'")) {
150             key = key.substring(1, key.length() - 1);
151
152             getLogger().debug("Stripped outer single quotes - key is now [" + key + "]");
153         }
154
155         String[] keyTerms = key.split("\\s+");
156
157         StringBuffer whereBuff = new StringBuffer();
158         String term1 = null;
159         String op = null;
160         String term2 = null;
161         HashMap<String, String> results = new HashMap<>();
162
163         for (int i = 0; i < keyTerms.length; i++) {
164             if (term1 == null) {
165                 if ("and".equalsIgnoreCase(keyTerms[i])
166                         || "or".equalsIgnoreCase(keyTerms[i])) {
167                     // Skip over ADD/OR
168                 } else {
169                     term1 = resolveTerm(keyTerms[i], ctx);
170                 }
171             } else if (op == null) {
172                 if ("==".equals(keyTerms[i])) {
173                     op = "=";
174                 } else {
175                     op = keyTerms[i];
176                 }
177             } else {
178                 term2 = resolveTerm(keyTerms[i], ctx);
179                 term2 = term2.trim().replace("'", "").replace("$", "").replace("'", "");
180                 results.put(term1,  term2);
181
182                 term1 = null;
183                 op = null;
184                 term2 = null;
185             }
186         }
187
188         return (results);
189     }
190
191     private static String resolveTerm(String term, SvcLogicContext ctx) {
192         if (term == null) {
193             return (null);
194         }
195
196         getLogger().debug("resolveTerm: term is " + term);
197
198         if (term.startsWith("$") && (ctx != null)) {
199             // Resolve any index variables.
200
201             term = ("'" + resolveCtxVariable(term.substring(1), ctx) + "'");
202             if (term.contains(VERSION_PATTERN) && (ctx != null)) {
203                 return term.replace(VERSION_PATTERN, AAIRequest.getSupportedAAIVersion());
204             }
205             return term;
206         } else if (term.contains(VERSION_PATTERN) && (ctx != null)) {
207             return term.replace(VERSION_PATTERN, AAIRequest.getSupportedAAIVersion());
208         } else if (term.startsWith("'") || term.startsWith("\"")) {
209             return (term);
210         } else {
211             return (term.replaceAll("-", "_"));
212
213         }
214     }
215
216     private static String resolveCtxVariable(String ctxVarName, SvcLogicContext ctx) {
217
218         if (ctxVarName.indexOf('[') == -1) {
219             // Ctx variable contains no arrays
220             return (ctx.getAttribute(ctxVarName));
221         }
222
223         // Resolve any array references
224         StringBuffer sbuff = new StringBuffer();
225         String[] ctxVarParts = ctxVarName.split("\\[");
226         sbuff.append(ctxVarParts[0]);
227         for (int i = 1; i < ctxVarParts.length; i++) {
228             if (ctxVarParts[i].startsWith("$")) {
229                 int endBracketLoc = ctxVarParts[i].indexOf("]");
230                 if (endBracketLoc == -1) {
231                     // Missing end bracket ... give up parsing
232                     getLogger().warn("Variable reference " + ctxVarName
233                             + " seems to be missing a ']'");
234                     return (ctx.getAttribute(ctxVarName));
235                 }
236
237                 String idxVarName = ctxVarParts[i].substring(1, endBracketLoc);
238                 String remainder = ctxVarParts[i].substring(endBracketLoc);
239
240                 sbuff.append("[");
241                 sbuff.append(ctx.getAttribute(idxVarName));
242                 sbuff.append(remainder);
243
244             } else {
245                 // Index is not a variable reference
246                 sbuff.append("[");
247                 sbuff.append(ctxVarParts[i]);
248             }
249         }
250
251         return (ctx.getAttribute(sbuff.toString()));
252     }
253
254     public static void populateRelationshipDataFromPath(RelationshipList rl) throws URISyntaxException {
255         List<Relationship> list =  rl.getRelationship();
256         if(list != null && !list.isEmpty()) {
257             for(Relationship relationship : list) {
258                 if(relationship.getRelationshipData().isEmpty()){
259                     String link = relationship.getRelatedLink();
260                     URI uri = new URI(link);
261                         link = uri.getPath();
262                     HashMap<String,String> contributors = pathToHashMap(link);
263                     for(String key : contributors.keySet()) {
264                         RelationshipData rd = new RelationshipData();
265                         rd.setRelationshipKey(key);
266                         rd.setRelationshipValue(contributors.get(key));
267                         relationship.getRelationshipData().add(rd);
268                     }
269                 }
270             }
271         }
272     }
273
274     protected static HashMap<String,String> pathToHashMap(String path) {
275         HashMap<String, String> nameValues = new  HashMap<>();
276
277         String[] split = path.split("/");
278
279         LinkedList<String> list = new LinkedList<String>( Arrays.asList(split));
280         Iterator<String> it = list.iterator();
281
282         while(it.hasNext()) {
283             String tag = it.next();
284             if(!tag.isEmpty()) {
285                 if(AAIRequest.getResourceNames().contains(tag)){
286                     LOG.info(tag);
287                     // get the class from tag
288                     Class<? extends AAIDatum> clazz = AAIRequest.getClassFromResource(tag);
289                     String fieldName = AAIServiceUtils.getPrimaryIdFromClass(clazz);
290
291                     String value = it.next();
292                     if(!StringUtils.isEmpty(value)){
293                         nameValues.put(String.format("%s.%s", tag, fieldName), value);
294                         switch(tag) {
295                         case "cloud-region":
296                         case "entitlement":
297                         case "license":
298                         case "route-target":
299                         case "service-capability":
300                         case "ctag-pool":
301                             String secondaryFieldName = AAIServiceUtils.getSecondaryIdFromClass(clazz);
302                             if(secondaryFieldName != null) {
303                                 value = it.next();
304                                 nameValues.put(String.format("%s.%s", tag, secondaryFieldName), value);
305                             }
306                             break;
307                         default:
308                             break;
309                         }
310                     }
311                 }
312             }
313         }
314         return nameValues;
315     }
316
317     public static String getPathForResource(String resource, String key, SvcLogicContext ctx ) throws MalformedURLException{
318         HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
319         AAIRequest request = AAIRequest.createRequest(resource, nameValues);
320
321         for(String name : nameValues.keySet()) {
322             request.addRequestProperty(name, nameValues.get(name));
323         }
324         return request.getRequestPath();
325     }
326
327     public static boolean isValidFormat(String resource, Map<String, String> nameValues) {
328
329         switch(resource){
330     case "custom-query":
331         case "formatted-query":
332         case "generic-query":
333         case "nodes-query":
334         case "linterface":
335         case "l2-bridge-sbg":
336         case "l2-bridge-bgf":
337         case "echo":
338         case "test":
339             return true;
340         }
341         if(resource.contains(":")) {
342             resource = resource.substring(0, resource.indexOf(":"));
343         }
344
345         Set<String> keys = nameValues.keySet();
346         for(String key : keys) {
347             if(!key.contains(".")) {
348                 if("depth".equals(key) || "related-to".equals(key) || "related_to".equals(key) || "related-link".equals(key) || "related_link".equals(key) || "selflink".equals(key) || "resource_path".equals(key))
349                     continue;
350                 else {
351                     getLogger().warn(String.format("key '%s' is incompatible with resource type '%s'", key, resource));
352                 }
353             }
354         }
355         return true;
356     }
357
358     public static boolean containsResource(String resource, HashMap<String, String> nameValues) {
359         if(resource.contains(":")) {
360             return true;
361         }
362
363         switch(resource){
364         case "custom-query":
365         case "formatted-query":
366         case "generic-query":
367         case "nodes-query":
368         case "linterface":
369         case "l2-bridge-sbg":
370         case "l2-bridge-bgf":
371         case "echo":
372         case "test":
373             return true;
374
375         default:
376             if(nameValues.containsKey("selflink")) {
377                 return true;
378             }
379         }
380
381         Set<String> tags = new HashSet<>();
382
383         for(String key : nameValues.keySet()) {
384             key = key.replace("_", "-");
385             if(key.contains(".")) {
386                 String[] split = key.split("\\.");
387                 tags.add(split[0]);
388             } else {
389                 tags.add(key);
390             }
391         }
392         return tags.contains(resource);
393     }
394 }