2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
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
14 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
24 * @author Rich Tabedzki
27 package org.onap.ccsdk.sli.adaptors.aai;
29 import java.lang.annotation.Annotation;
30 import java.lang.reflect.Method;
31 import java.net.MalformedURLException;
33 import java.net.URISyntaxException;
34 import java.util.Arrays;
35 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.Iterator;
39 import java.util.LinkedList;
40 import java.util.List;
43 import javax.xml.bind.annotation.XmlType;
45 import org.apache.commons.lang.StringUtils;
46 import org.onap.aai.inventory.v16.Relationship;
47 import org.onap.aai.inventory.v16.RelationshipData;
48 import org.onap.aai.inventory.v16.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;
54 public class AAIServiceUtils {
56 private static final String VERSION_PATTERN = "/v$/";
58 private static final Logger LOG = LoggerFactory.getLogger(AAIService.class);
60 private AAIServiceUtils() {
63 public static String getPrimaryIdFromClass(Class<? extends AAIDatum> resourceClass){
65 getLogger().debug(resourceClass.getName());
68 Annotation[] annotations = resourceClass.getAnnotations();
69 for(Annotation annotation : annotations) {
70 Class<? extends Annotation> anotationType = annotation.annotationType();
71 String annotationName = anotationType.getName();
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);
83 } catch(Exception exc) {
84 getLogger().warn("getPrimaryIdFromClass failed", exc);
89 public static String getSecondaryIdFromClass(Class<? extends AAIDatum> resourceClass){
90 getLogger().debug(resourceClass.getName());
93 Annotation[] annotations = resourceClass.getAnnotations();
94 for(Annotation annotation : annotations) {
95 Class<? extends Annotation> anotationType = annotation.annotationType();
96 String annotationName = anotationType.getName();
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);
108 primaryIdFound = true;
113 } catch(Exception exc) {
119 public static Method getRelationshipListGetterMethodFromClassDefinition(Class resourceClass) {
120 Method getRelationshipListMethod = null;
123 getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
124 } catch(Exception exc) {
125 getLogger().debug("Retrofiting relationship data: " + exc.getMessage());
127 return getRelationshipListMethod;
130 private static Logger getLogger() {
135 private static final String regex = "([A-Z][a-z,0-9]+)";
136 private static final String replacement = "-$1";
138 public static String camelCaseToDashedString(String propOrder) {
139 return propOrder.replaceAll(regex, replacement).toLowerCase();
142 public static HashMap<String,String> keyToHashMap(String key, SvcLogicContext ctx) {
147 getLogger().debug("Converting key [" + key + "] to where clause");
149 if (key.startsWith("'") && key.endsWith("'")) {
150 key = key.substring(1, key.length() - 1);
152 getLogger().debug("Stripped outer single quotes - key is now [" + key + "]");
155 String[] keyTerms = key.split("\\s+");
157 StringBuffer whereBuff = new StringBuffer();
161 HashMap<String, String> results = new HashMap<>();
163 for (int i = 0; i < keyTerms.length; i++) {
165 if ("and".equalsIgnoreCase(keyTerms[i])
166 || "or".equalsIgnoreCase(keyTerms[i])) {
169 term1 = resolveTerm(keyTerms[i], ctx);
171 } else if (op == null) {
172 if ("==".equals(keyTerms[i])) {
178 term2 = resolveTerm(keyTerms[i], ctx);
179 term2 = term2.trim().replace("'", "").replace("$", "").replace("'", "");
180 results.put(term1, term2);
191 private static String resolveTerm(String term, SvcLogicContext ctx) {
196 getLogger().debug("resolveTerm: term is " + term);
198 if (term.startsWith("$") && (ctx != null)) {
199 // Resolve any index variables.
201 term = ("'" + resolveCtxVariable(term.substring(1), ctx) + "'");
202 if (term.contains(VERSION_PATTERN) && (ctx != null)) {
203 return term.replace(VERSION_PATTERN, AAIRequest.getSupportedAAIVersion());
206 } else if (term.contains(VERSION_PATTERN) && (ctx != null)) {
207 return term.replace(VERSION_PATTERN, AAIRequest.getSupportedAAIVersion());
208 } else if (term.startsWith("'") || term.startsWith("\"")) {
211 return (term.replaceAll("-", "_"));
216 private static String resolveCtxVariable(String ctxVarName, SvcLogicContext ctx) {
218 if (ctxVarName.indexOf('[') == -1) {
219 // Ctx variable contains no arrays
220 return (ctx.getAttribute(ctxVarName));
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));
237 String idxVarName = ctxVarParts[i].substring(1, endBracketLoc);
238 String remainder = ctxVarParts[i].substring(endBracketLoc);
241 sbuff.append(ctx.getAttribute(idxVarName));
242 sbuff.append(remainder);
245 // Index is not a variable reference
247 sbuff.append(ctxVarParts[i]);
251 return (ctx.getAttribute(sbuff.toString()));
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);
274 protected static HashMap<String,String> pathToHashMap(String path) {
275 HashMap<String, String> nameValues = new HashMap<>();
277 String[] split = path.split("/");
279 LinkedList<String> list = new LinkedList<String>( Arrays.asList(split));
280 Iterator<String> it = list.iterator();
282 while(it.hasNext()) {
283 String tag = it.next();
285 if(AAIRequest.getResourceNames().contains(tag)){
287 // get the class from tag
288 Class<? extends AAIDatum> clazz = AAIRequest.getClassFromResource(tag);
289 String fieldName = AAIServiceUtils.getPrimaryIdFromClass(clazz);
291 String value = it.next();
292 if(!StringUtils.isEmpty(value)){
293 nameValues.put(String.format("%s.%s", tag, fieldName), value);
299 case "service-capability":
301 String secondaryFieldName = AAIServiceUtils.getSecondaryIdFromClass(clazz);
302 if(secondaryFieldName != null) {
304 nameValues.put(String.format("%s.%s", tag, secondaryFieldName), value);
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);
321 for(String name : nameValues.keySet()) {
322 request.addRequestProperty(name, nameValues.get(name));
324 return request.getRequestPath();
327 public static boolean isValidFormat(String resource, Map<String, String> nameValues) {
331 case "formatted-query":
332 case "generic-query":
335 case "l2-bridge-sbg":
336 case "l2-bridge-bgf":
341 if(resource.contains(":")) {
342 resource = resource.substring(0, resource.indexOf(":"));
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))
351 getLogger().warn(String.format("key '%s' is incompatible with resource type '%s'", key, resource));
358 public static boolean containsResource(String resource, HashMap<String, String> nameValues) {
359 if(resource.contains(":")) {
365 case "formatted-query":
366 case "generic-query":
369 case "l2-bridge-sbg":
370 case "l2-bridge-bgf":
376 if(nameValues.containsKey("selflink")) {
381 Set<String> tags = new HashSet<>();
383 for(String key : nameValues.keySet()) {
384 key = key.replace("_", "-");
385 if(key.contains(".")) {
386 String[] split = key.split("\\.");
392 return tags.contains(resource);