2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.ccsdk.sli.adaptors.aai;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.InputStreamReader;
27 import java.io.Reader;
28 import java.io.UnsupportedEncodingException;
29 import java.lang.reflect.Method;
30 import java.net.MalformedURLException;
31 import java.net.URISyntaxException;
33 import java.net.URLDecoder;
34 import java.net.URLEncoder;
35 import java.util.ArrayList;
36 import java.util.Arrays;
37 import java.util.BitSet;
38 import java.util.HashSet;
39 import java.util.HashMap;
40 import java.util.LinkedHashMap;
41 import java.util.List;
43 import java.util.Properties;
45 import java.util.TreeSet;
47 import org.apache.commons.lang.StringUtils;
48 import org.openecomp.aai.inventory.v11.GenericVnf;
49 import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
50 import org.osgi.framework.Bundle;
51 import org.osgi.framework.BundleContext;
52 import org.osgi.framework.FrameworkUtil;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
56 import com.fasterxml.jackson.core.JsonParseException;
57 import com.fasterxml.jackson.core.JsonProcessingException;
58 import com.fasterxml.jackson.databind.JsonMappingException;
59 import com.fasterxml.jackson.databind.ObjectMapper;
61 public abstract class AAIRequest {
62 protected static final Logger LOG = LoggerFactory.getLogger(AAIRequest.class);
64 protected static final String TARGET_URI = "org.onap.ccsdk.sli.adaptors.aai.uri";
66 protected static final String MASTER_REQUEST = "master-request";
68 public static final String RESOURCE_VERSION = "resource-version";
70 public static final String DEPTH = "depth";
72 protected static Properties configProperties;
73 protected final String targetUri;
74 protected static AAIService aaiService;
76 protected AAIDatum requestDatum;
78 protected final Properties requestProperties = new Properties();
81 public static AAIRequest createRequest(String resoourceName, Map<String, String> nameValues){
83 String resoource = resoourceName;
84 String masterResource = null;
89 if(resoource.contains(":")) {
90 String[] tokens = resoource.split(":");
91 if(tokens != null && tokens.length == 2) {
92 resoource = tokens[1];
93 masterResource = tokens[0];
95 Class<? extends AAIDatum> clazz = null;
97 clazz = getClassFromResource(resoource) ;
98 } catch (ClassNotFoundException e) {
99 LOG.warn("AAIRequest does not support class: " + e.getMessage());
109 if(nameValues.containsKey("selflink")){
110 Class<? extends AAIDatum> clazz = null;
112 clazz = getClassFromResource(resoource) ;
113 } catch (ClassNotFoundException e) {
114 LOG.warn("AAIRequest does not support class: " + e.getMessage());
119 return new SelfLinkRequest(clazz);
125 case "generic-query":
126 return new GenericQueryRequest();
128 return new NamedQueryRequest();
130 return new NodesQueryRequest();
132 case "formatted-query":
133 return new CustomQueryRequest();
136 return new EchoRequest();
139 case "l2-bridge-sbg":
140 case "l2-bridge-bgf":
142 resoource = "l-interface";
143 return getRequestFromResource("l-interface");
145 case "relationship-list":
146 return new RelationshipListRequest(AAIRequest.createRequest(masterResource, nameValues));
148 return new RelationshipRequest(AAIRequest.createRequest(masterResource, nameValues));
150 return getRequestFromResource(resoource);
156 * Map containing resource tag to its bit position in bitset mapping
158 private static Map<String, String> tagValues = new LinkedHashMap<>();
160 * Map containing bitset value of the path to its path mapping
162 private static Map<BitSet, String> bitsetPaths = new LinkedHashMap<>();
165 public static Set<String> getResourceNames() {
166 return tagValues.keySet();
170 public static void setProperties(Properties props, AAIService aaiService) {
171 AAIRequest.configProperties = props;
172 AAIRequest.aaiService = aaiService;
177 Bundle bundle = FrameworkUtil.getBundle(AAIServiceActivator.class);
179 BundleContext ctx = bundle.getBundleContext();
183 url = ctx.getBundle().getResource(AAIService.PATH_PROPERTIES);
185 url = aaiService.getClass().getResource("/aai-path.properties");
188 InputStream in = url.openStream();
189 Reader reader = new InputStreamReader(in, "UTF-8");
191 Properties properties = new Properties();
192 properties.load(reader);
193 LOG.info("loaded " + properties.size());
195 Set<String> keys = properties.stringPropertyNames();
198 Set<String> resourceNames = new TreeSet<>();
200 for(String key : keys) {
201 String[] tags = key.split("\\|");
202 for(String tag : tags) {
203 if(!resourceNames.contains(tag)) {
204 resourceNames.add(tag);
205 tagValues.put(tag, Integer.toString(++index));
208 BitSet bs = new BitSet(256);
209 for(String tag : tags) {
210 String value = tagValues.get(tag);
211 Integer bitIndex = Integer.parseInt(value) ;
214 String path = properties.getProperty(key);
215 LOG.info(String.format("bitset %s\t\t%s", bs.toString(), path));
216 bitsetPaths.put(bs, path);
218 LOG.info("loaded " + resourceNames.toString());
222 LOG.error("Caught exception", e);
226 public AAIRequest() {
227 targetUri = configProperties.getProperty(TARGET_URI);
230 public void addRequestProperty(String key, String value) {
231 requestProperties.put(key, value);
234 public final void setRequestObject(AAIDatum value) {
235 requestDatum = value;
238 public final AAIDatum getRequestObject() {
242 public final void addMasterRequest(AAIRequest masterRequest) {
243 requestProperties.put(MASTER_REQUEST, masterRequest);
246 protected static String encodeQuery(String param) throws UnsupportedEncodingException {
247 return URLEncoder.encode(param, "UTF-8").replace("+", "%20");
250 protected void handleException(AAIRequest lInterfaceRequest, JsonProcessingException exc) {
251 aaiService.getLogger().warn("Could not deserialize object of type " + lInterfaceRequest.getClass().getSimpleName(), exc) ;
254 public URL getRequestUrl(String method, String resourceVersion) throws UnsupportedEncodingException, MalformedURLException, URISyntaxException {
256 String request_url = null;
258 request_url = targetUri + updatePathDataValues(resourceVersion);
260 URL http_req_url = new URL(request_url);
262 aaiService.LOGwriteFirstTrace(method, http_req_url.toString());
267 public String updatePathDataValues(Object resourceVersion) throws UnsupportedEncodingException, MalformedURLException {
268 String request_url = getRequestPath();
270 Set<String> uniqueResources = extractUniqueResourceSetFromKeys(requestProperties.stringPropertyNames());
272 for(String resoourceName:uniqueResources) {
273 AAIRequest locRequest = AAIRequest.createRequest(resoourceName, new HashMap<String, String>());
274 if(locRequest != null) {
275 Class<?> clazz = locRequest.getClass();
276 Method function = null;
278 function = clazz.getMethod("processPathData", request_url.getClass(), requestProperties.getClass());
279 request_url = (String) function.invoke(null, request_url, requestProperties);
280 } catch (Exception e) {
286 if(resourceVersion != null) {
287 request_url = request_url +"?resource-version="+resourceVersion;
293 protected String getRequestPath() throws MalformedURLException {
294 return getRequestPath(null);
297 protected String getRequestPath(String resource) throws MalformedURLException {
298 if(requestProperties.containsKey("resource-path")) {
299 return requestProperties.getProperty("resource-path");
302 Set<String> uniqueResources = extractUniqueResourceSetFromKeys(requestProperties.stringPropertyNames());
303 if(resource != null) {
304 // for group search add itself, but remove singular version of itself
305 if(!uniqueResources.contains(resource)) {
306 boolean replaced = false;
307 Set<String> tmpUniqueResources = new HashSet<String>();
308 tmpUniqueResources.addAll(uniqueResources);
309 for(String item : tmpUniqueResources){
310 String plural = item +"s";
311 if(item.endsWith("y")){
312 plural = item.substring(0, item.length()-1)+ "ies";
314 if(plural.equals(resource)) {
315 uniqueResources.remove(item);
316 uniqueResources.add(resource);
322 if(!uniqueResources.contains(resource)) {
323 uniqueResources.add(resource);
328 BitSet bitset = new BitSet();
329 for(String key : uniqueResources) {
330 if(tagValues.containsKey(key)) {
331 Object tmpValue = tagValues.get(key);
332 if(tmpValue != null) {
333 String value = tmpValue.toString();
334 int bitIndex = Integer.parseInt(value);
335 bitset.set(bitIndex);
340 String path = bitsetPaths.get(bitset);
342 throw new MalformedURLException("PATH not found for key string containing valies :" +requestProperties.toString());
347 public abstract URL getRequestQueryUrl(String method) throws UnsupportedEncodingException, MalformedURLException, URISyntaxException;
349 public abstract String toJSONString();
351 public abstract String[] getArgsList();
353 public abstract Class<? extends AAIDatum> getModelClass() ;
355 public String getPrimaryResourceName(String resource) {
359 public String formatKey(String argument) {
363 public AAIDatum jsonStringToObject(String jsonData) throws JsonParseException, JsonMappingException, IOException {
364 if(jsonData == null) {
368 AAIDatum response = null;
369 ObjectMapper mapper = getObjectMapper();
370 response = mapper.readValue(jsonData, getModelClass());
374 protected static Set<String> extractUniqueResourceSetFromKeys(Set<String> keySet) {
375 Set<String> uniqueResources = new TreeSet<>();
376 List<String> keys = new ArrayList<>(keySet);
377 for(String resource : keys) {
378 if(resource.contains(".")) {
379 String [] split = resource.split("\\.");
380 uniqueResources.add(split[0].replaceAll("_", "-"));
383 return uniqueResources;
386 public void processRequestPathValues(Map<String, String> nameValues) {
387 Set<String> uniqueResources = extractUniqueResourceSetFromKeys(nameValues.keySet());
389 Set<String> tokens = new TreeSet<>();
391 tokens.addAll(Arrays.asList(this.getArgsList()));
393 for(String resoourceName:uniqueResources) {
394 AAIRequest locRequest = AAIRequest.createRequest(resoourceName, nameValues);
395 if(locRequest != null)
396 tokens.addAll(Arrays.asList(locRequest.getArgsList()));
399 String[] arguments = tokens.toArray(new String[0]);
400 for(String name : arguments) {
401 String tmpName = name.replaceAll("-", "_");
402 String value = nameValues.get(tmpName);
403 if(value != null && !value.isEmpty()) {
404 value = value.trim().replace("'", "").replace("$", "").replace("'", "");
405 this.addRequestProperty(name, value);
410 public static String processPathData(String request_url, Properties requestProperties) throws UnsupportedEncodingException {
414 public boolean isDeleteDataRequired() {
418 ObjectMapper getObjectMapper() {
419 return AAIService.getObjectMapper();
422 public static Class<? extends AAIDatum> getClassFromResource(String resoourceName) throws ClassNotFoundException {
423 String className = GenericVnf.class.getName();
424 String[] split = resoourceName.split("-");
425 for(int i = 0; i < split.length; i++) {
426 split[i] = StringUtils.capitalize(split[i]);
429 String caps = StringUtils.join(split);
430 className = className.replace("GenericVnf", caps);
431 Class<? extends AAIDatum> clazz = null;
433 clazz = (Class<? extends AAIDatum>)Class.forName(className);
434 } catch (ClassNotFoundException e) {
435 LOG.warn("AAIRequest does not support class: " + e.getMessage());
442 protected static AAIRequest getRequestFromResource(String resoourceName) {
444 Class<? extends AAIDatum> clazz = null;
446 clazz = getClassFromResource(resoourceName);
447 } catch (ClassNotFoundException e) {
448 LOG.warn("AAIRequest does not support class: " + e.getMessage());
454 GenericRequest request = new GenericRequest(clazz);
458 public static Map<String, String> splitQuery(String query) throws UnsupportedEncodingException {
459 Map<String, String> query_pairs = new LinkedHashMap<>();
461 if(query != null && !query.isEmpty()) {
462 String[] pairs = query.split("&");
463 for (String pair : pairs) {
464 int idx = pair.indexOf('=');
465 query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
471 public static Map<String, String> splitPath(String path) throws UnsupportedEncodingException {
472 Map<String, String> query_pairs = new LinkedHashMap<>();
474 if(path != null && !path.isEmpty()) {
475 String[] pairs = path.split("/");
476 for (String pair : pairs) {
477 int idx = pair.indexOf('=');
478 query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
484 protected boolean expectsDataFromPUTRequest() {
489 public String getTargetUri() {