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.io.IOException;
30 import java.io.InputStream;
31 import java.io.InputStreamReader;
32 import java.io.Reader;
33 import java.io.UnsupportedEncodingException;
34 import java.lang.reflect.Method;
35 import java.net.MalformedURLException;
36 import java.net.URISyntaxException;
38 import java.net.URLDecoder;
39 import java.net.URLEncoder;
40 import java.nio.charset.StandardCharsets;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.BitSet;
44 import java.util.HashSet;
45 import java.util.HashMap;
46 import java.util.LinkedHashMap;
47 import java.util.List;
49 import java.util.Properties;
51 import java.util.TreeSet;
53 import org.apache.commons.lang.StringUtils;
54 import org.onap.aai.inventory.v21.GenericVnf;
55 import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
56 import org.osgi.framework.Bundle;
57 import org.osgi.framework.BundleContext;
58 import org.osgi.framework.FrameworkUtil;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
62 import com.fasterxml.jackson.core.JsonParseException;
63 import com.fasterxml.jackson.core.JsonProcessingException;
64 import com.fasterxml.jackson.databind.JsonMappingException;
65 import com.fasterxml.jackson.databind.ObjectMapper;
67 public abstract class AAIRequest {
68 protected static final Logger LOG = LoggerFactory.getLogger(AAIRequest.class);
70 protected static final String TARGET_URI = "org.onap.ccsdk.sli.adaptors.aai.uri";
72 protected static final String MASTER_REQUEST = "master-request";
74 public static final String RESOURCE_VERSION = "resource-version";
76 public static final String DEPTH = "depth";
78 protected static Properties configProperties;
79 protected final String targetUri;
80 protected static AAIService aaiService;
82 protected AAIDatum requestDatum;
84 protected final Properties requestProperties = new Properties();
87 public static AAIRequest createRequest(String resoourceName, Map<String, String> nameValues){
89 String resoource = resoourceName;
90 String masterResource = null;
95 if(resoource.contains(":")) {
96 String[] tokens = resoource.split(":");
97 if(tokens != null && tokens.length == 2) {
98 resoource = tokens[1];
99 masterResource = tokens[0];
100 Class<? extends AAIDatum> clazz = getClassFromResource(resoource) ;
108 if(nameValues.containsKey("selflink")){
109 Class<? extends AAIDatum> clazz = getClassFromResource(resoource) ;
112 return new SelfLinkRequest(clazz);
118 case "generic-query":
119 return new GenericQueryRequest();
121 return new NodesQueryRequest();
123 case "formatted-query":
124 return new CustomQueryRequest();
127 return new EchoRequest();
130 case "l2-bridge-sbg":
131 case "l2-bridge-bgf":
133 resoource = "l-interface";
134 return getRequestFromResource("l-interface");
136 case "relationship-list":
137 return new RelationshipListRequest(AAIRequest.createRequest(masterResource, nameValues));
139 return new RelationshipRequest(AAIRequest.createRequest(masterResource, nameValues));
141 return getRequestFromResource(resoource);
147 * Map containing resource tag to its bit position in bitset mapping
149 private static Map<String, String> tagValues = new LinkedHashMap<>();
151 * Map containing bitset value of the path to its path mapping
153 private static Map<BitSet, String> bitsetPaths = new LinkedHashMap<>();
156 public static Set<String> getResourceNames() {
157 return tagValues.keySet();
161 public static void setProperties(Properties props, AAIService aaiService) {
162 AAIRequest.configProperties = props;
163 AAIRequest.aaiService = aaiService;
165 InputStream in = null;
169 LOG.info("Loading aai-path.properties via OSGi");
171 Bundle bundle = FrameworkUtil.getBundle(AAIService.class);
173 BundleContext ctx = bundle.getBundleContext();
177 url = ctx.getBundle().getResource(AAIService.PATH_PROPERTIES);
179 url = aaiService.getClass().getResource("/aai-path.properties");
182 in = url.openStream();
184 catch (NoClassDefFoundError|Exception e) {
185 LOG.info("Loading aai-path.properties from jar");
186 in = AAIRequest.class.getResourceAsStream("/aai-path.properties");
195 Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
197 Properties properties = new Properties();
198 properties.load(reader);
199 LOG.info("loaded " + properties.size());
201 Set<String> keys = properties.stringPropertyNames();
204 Set<String> resourceNames = new TreeSet<>();
206 for(String key : keys) {
207 String[] tags = key.split("\\|");
208 for(String tag : tags) {
209 if(!resourceNames.contains(tag)) {
210 resourceNames.add(tag);
211 tagValues.put(tag, Integer.toString(++index));
214 BitSet bs = new BitSet(256);
215 for(String tag : tags) {
216 String value = tagValues.get(tag);
217 Integer bitIndex = Integer.parseInt(value) ;
220 String path = properties.getProperty(key);
221 LOG.trace(String.format("bitset %s\t\t%s", bs.toString(), path));
222 bitsetPaths.put(bs, path);
224 LOG.info("loaded " + resourceNames.toString());
228 LOG.error("Caught exception", e);
232 public AAIRequest() {
233 targetUri = configProperties.getProperty(TARGET_URI);
236 public void addRequestProperty(String key, String value) {
237 requestProperties.put(key, value);
240 public final void setRequestObject(AAIDatum value) {
241 requestDatum = value;
244 public final AAIDatum getRequestObject() {
248 public final void addMasterRequest(AAIRequest masterRequest) {
249 requestProperties.put(MASTER_REQUEST, masterRequest);
252 protected static String encodeQuery(String param) throws UnsupportedEncodingException {
253 return URLEncoder.encode(param, "UTF-8").replace("+", "%20");
256 protected void handleException(AAIRequest lInterfaceRequest, JsonProcessingException exc) {
257 aaiService.getLogger().warn("Could not deserialize object of type " + lInterfaceRequest.getClass().getSimpleName(), exc) ;
260 public URL getRequestUrl(String method, String resourceVersion) throws UnsupportedEncodingException, MalformedURLException, URISyntaxException {
262 String request_url = null;
264 request_url = targetUri + updatePathDataValues(resourceVersion);
266 URL http_req_url = new URL(request_url);
268 aaiService.LOGwriteFirstTrace(method, http_req_url.toString());
273 public String updatePathDataValues(Object resourceVersion) throws UnsupportedEncodingException, MalformedURLException {
274 String request_url = getRequestPath();
276 Set<String> uniqueResources = extractUniqueResourceSetFromKeys(requestProperties.stringPropertyNames());
278 for(String resoourceName:uniqueResources) {
279 AAIRequest locRequest = AAIRequest.createRequest(resoourceName, new HashMap<String, String>());
280 if(locRequest != null) {
281 Class<?> clazz = locRequest.getClass();
282 Method function = null;
284 function = clazz.getMethod("processPathData", request_url.getClass(), requestProperties.getClass());
285 request_url = (String) function.invoke(null, request_url, requestProperties);
286 } catch (Exception e) {
287 LOG.error("Caught exception", e);
292 if(resourceVersion != null) {
293 request_url = request_url +"?resource-version="+resourceVersion;
299 protected String getRequestPath() throws MalformedURLException {
300 return getRequestPath(null);
303 protected String getRequestPath(String resource) throws MalformedURLException {
304 if(requestProperties.containsKey("resource-path")) {
305 return requestProperties.getProperty("resource-path");
308 Set<String> uniqueResources = extractUniqueResourceSetFromKeys(requestProperties.stringPropertyNames());
309 if(resource != null) {
310 // for group search add itself, but remove singular version of itself
311 if(!uniqueResources.contains(resource)) {
312 boolean replaced = false;
313 Set<String> tmpUniqueResources = new HashSet<>();
314 tmpUniqueResources.addAll(uniqueResources);
315 for(String item : tmpUniqueResources){
316 String plural = item +"s";
317 if(item.endsWith("y")){
318 plural = item.substring(0, item.length()-1)+ "ies";
320 if(plural.equals(resource)) {
321 uniqueResources.remove(item);
322 uniqueResources.add(resource);
328 if(!uniqueResources.contains(resource)) {
329 uniqueResources.add(resource);
334 BitSet bitset = new BitSet();
335 for(String key : uniqueResources) {
336 if(tagValues.containsKey(key)) {
337 Object tmpValue = tagValues.get(key);
338 if(tmpValue != null) {
339 String value = tmpValue.toString();
340 int bitIndex = Integer.parseInt(value);
341 bitset.set(bitIndex);
346 String path = bitsetPaths.get(bitset);
348 throw new MalformedURLException("PATH not found for key string containing valies :" +requestProperties.toString());
353 public abstract URL getRequestQueryUrl(String method) throws UnsupportedEncodingException, MalformedURLException, URISyntaxException;
355 public abstract String toJSONString();
357 public abstract String[] getArgsList();
359 public abstract Class<? extends AAIDatum> getModelClass() ;
361 public String getPrimaryResourceName(String resource) {
365 public String formatKey(String argument) {
369 public AAIDatum jsonStringToObject(String jsonData) throws JsonParseException, JsonMappingException, IOException {
370 if(jsonData == null) {
374 AAIDatum response = null;
375 ObjectMapper mapper = getObjectMapper();
376 response = mapper.readValue(jsonData, getModelClass());
380 protected static Set<String> extractUniqueResourceSetFromKeys(Set<String> keySet) {
381 Set<String> uniqueResources = new TreeSet<>();
382 List<String> keys = new ArrayList<>(keySet);
383 for(String resource : keys) {
384 if(resource.contains(".")) {
385 String [] split = resource.split("\\.");
386 uniqueResources.add(split[0].replaceAll("_", "-"));
389 return uniqueResources;
392 public void processRequestPathValues(Map<String, String> nameValues) {
393 Set<String> uniqueResources = extractUniqueResourceSetFromKeys(nameValues.keySet());
395 Set<String> tokens = new TreeSet<>();
397 tokens.addAll(Arrays.asList(this.getArgsList()));
399 for(String resoourceName:uniqueResources) {
400 AAIRequest locRequest = AAIRequest.createRequest(resoourceName, nameValues);
401 if(locRequest != null)
402 tokens.addAll(Arrays.asList(locRequest.getArgsList()));
405 String[] arguments = tokens.toArray(new String[0]);
406 for(String name : arguments) {
407 String tmpName = name.replaceAll("-", "_");
408 String value = nameValues.get(tmpName);
409 if(value != null && !value.isEmpty()) {
410 value = value.trim().replace("'", "").replace("$", "").replace("'", "");
411 this.addRequestProperty(name, value);
416 public static String processPathData(String request_url, Properties requestProperties) throws UnsupportedEncodingException {
420 public boolean isDeleteDataRequired() {
424 ObjectMapper getObjectMapper() {
425 return AAIService.getObjectMapper();
428 public static Class<? extends AAIDatum> getClassFromResource(String resoourceName) {
429 String className = GenericVnf.class.getName();
430 String[] split = resoourceName.split("-");
431 for(int i = 0; i < split.length; i++) {
432 split[i] = StringUtils.capitalize(split[i]);
435 String caps = StringUtils.join(split);
436 className = className.replace("GenericVnf", caps);
438 return (Class<? extends AAIDatum>)Class.forName(className);
439 } catch (ClassNotFoundException e) {
440 LOG.warn("AAIRequest does not support class: " + e.getMessage());
445 protected static AAIRequest getRequestFromResource(String resoourceName) {
447 Class<? extends AAIDatum> clazz = getClassFromResource(resoourceName);
452 return new GenericRequest(clazz);
455 public static Map<String, String> splitQuery(String query) throws UnsupportedEncodingException {
456 Map<String, String> query_pairs = new LinkedHashMap<>();
458 if(query != null && !query.isEmpty()) {
459 String[] pairs = query.split("&");
460 for (String pair : pairs) {
461 int idx = pair.indexOf('=');
462 query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
468 public static Map<String, String> splitPath(String path) throws UnsupportedEncodingException {
469 Map<String, String> query_pairs = new LinkedHashMap<>();
471 if(path != null && !path.isEmpty()) {
472 String[] pairs = path.split("/");
473 for (String pair : pairs) {
474 int idx = pair.indexOf('=');
475 query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
481 protected boolean expectsDataFromPUTRequest() {
486 public String getTargetUri() {
490 public static final String getSupportedAAIVersion() {
491 return configProperties.getProperty(AAIDeclarations.AAI_VERSION, "/v21/");