add junit coverage for SvnfmService
[so.git] / bpmn / so-bpmn-infrastructure-common / src / main / java / org / onap / so / bpmn / infrastructure / workflow / service / ServicePluginFactory.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2018 Huawei Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Modifications Copyright (c) 2019 Samsung
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.so.bpmn.infrastructure.workflow.service;
24
25 import com.fasterxml.jackson.core.JsonProcessingException;
26 import com.fasterxml.jackson.databind.ObjectMapper;
27 import com.fasterxml.jackson.databind.SerializationFeature;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.net.SocketTimeoutException;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collections;
34 import java.util.HashMap;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Map.Entry;
38 import java.util.Optional;
39 import java.util.Properties;
40 import org.apache.commons.lang3.StringUtils;
41 import org.apache.http.HttpResponse;
42 import org.apache.http.ParseException;
43 import org.apache.http.client.HttpClient;
44 import org.apache.http.client.config.RequestConfig;
45 import org.apache.http.client.methods.HttpDelete;
46 import org.apache.http.client.methods.HttpGet;
47 import org.apache.http.client.methods.HttpPost;
48 import org.apache.http.client.methods.HttpPut;
49 import org.apache.http.client.methods.HttpRequestBase;
50 import org.apache.http.conn.ConnectTimeoutException;
51 import org.apache.http.entity.ContentType;
52 import org.apache.http.entity.StringEntity;
53 import org.apache.http.impl.client.HttpClientBuilder;
54 import org.apache.http.util.EntityUtils;
55 import org.camunda.bpm.engine.delegate.DelegateExecution;
56 import org.camunda.bpm.engine.runtime.Execution;
57 import org.onap.aai.domain.yang.LogicalLink;
58 import org.onap.aai.domain.yang.LogicalLinks;
59 import org.onap.aai.domain.yang.PInterface;
60 import org.onap.aai.domain.yang.Pnf;
61 import org.onap.aai.domain.yang.Relationship;
62 import org.onap.so.bpmn.core.UrnPropertiesReader;
63 import org.onap.so.bpmn.core.domain.Resource;
64 import org.onap.so.bpmn.core.domain.ServiceDecomposition;
65 import org.onap.so.bpmn.core.json.JsonUtils;
66 import org.onap.so.client.aai.AAIObjectPlurals;
67 import org.onap.so.client.aai.AAIObjectType;
68 import org.onap.so.client.aai.AAIResourcesClient;
69 import org.onap.so.client.aai.entities.AAIResultWrapper;
70 import org.onap.so.client.aai.entities.Relationships;
71 import org.onap.so.client.aai.entities.uri.AAIResourceUri;
72 import org.onap.so.client.aai.entities.uri.AAIUriFactory;
73 import org.onap.so.logger.ErrorCode;
74 import org.onap.so.logger.MessageEnum;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
77 import org.springframework.web.util.UriUtils;
78
79 public class ServicePluginFactory {
80
81     private static String OOF_DEFAULT_ENDPOINT;
82     private static String THIRD_SP_DEFAULT_ENDPOINT;
83     private static String INVENTORY_OSS_DEFAULT_ENDPOINT;
84     private static final int DEFAULT_TIME_OUT = 60000;
85
86     static JsonUtils jsonUtil = new JsonUtils();
87
88     private static Logger logger = LoggerFactory.getLogger(ServicePluginFactory.class);
89
90     private static ServicePluginFactory instance;
91
92     private static final String CUSTOM_RESOURCE_TP = "custom-resource-tp";
93     private static final String VS_MONITORED = "VS_assured";
94     private static final String VS_UNMONITORED = "VS_besteffort";
95     private static final String TS_MONITORED = "TS1";
96     private static final String TS_UNMONITORED = "TS2";
97     private static final String CUSTOM_TP_LIST[] =
98             new String[] {VS_MONITORED, VS_UNMONITORED, TS_MONITORED, TS_UNMONITORED};
99
100     static {
101         try (InputStream is = ClassLoader.class.getResourceAsStream("/application.properties")) {
102             Properties prop = new Properties();
103             prop.load(is);
104             OOF_DEFAULT_ENDPOINT = prop.getProperty("oof.default.endpoint");
105             THIRD_SP_DEFAULT_ENDPOINT = prop.getProperty("third.sp.default.endpoint");
106             INVENTORY_OSS_DEFAULT_ENDPOINT = prop.getProperty("inventory.oss.default.endpoint");
107         } catch (IOException e) {
108             logger.error("Failed to load property file!");
109         }
110     }
111
112     public static synchronized ServicePluginFactory getInstance() {
113         if (null == instance) {
114             instance = new ServicePluginFactory();
115         }
116         return instance;
117     }
118
119     private ServicePluginFactory() {
120
121     }
122
123     private String getInventoryOSSEndPoint() {
124         return UrnPropertiesReader.getVariable("mso.service-plugin.inventory-oss-endpoint",
125                 INVENTORY_OSS_DEFAULT_ENDPOINT);
126     }
127
128     private String getThirdSPEndPoint() {
129         return UrnPropertiesReader.getVariable("mso.service-plugin.third-sp-endpoint", THIRD_SP_DEFAULT_ENDPOINT);
130     }
131
132     private String getOOFCalcEndPoint() {
133         return UrnPropertiesReader.getVariable("mso.service-plugin.oof-calc-endpoint", OOF_DEFAULT_ENDPOINT);
134     }
135
136     @SuppressWarnings("unchecked")
137     public String doProcessSiteLocation(ServiceDecomposition serviceDecomposition, String uuiRequest) {
138         if (!isNeedProcessSite(uuiRequest)) {
139             return uuiRequest;
140         }
141
142         Map<String, Object> uuiObject = getJsonObject(uuiRequest, Map.class);
143         if (uuiObject == null) {
144             return uuiRequest;
145         }
146         Map<String, Object> serviceObject =
147                 (Map<String, Object>) uuiObject.getOrDefault("service", Collections.emptyMap());
148         Map<String, Object> serviceParametersObject =
149                 (Map<String, Object>) serviceObject.getOrDefault("parameters", Collections.emptyMap());
150         Map<String, Object> serviceRequestInputs =
151                 (Map<String, Object>) serviceParametersObject.getOrDefault("requestInputs", Collections.emptyMap());
152         List<Object> resources =
153                 (List<Object>) serviceParametersObject.getOrDefault("resources", Collections.emptyList());
154
155         if (isSiteLocationLocal(serviceRequestInputs, resources)) {
156             // resources changed : added TP info
157             return getJsonString(uuiObject);
158         }
159
160         List<Resource> addResourceList = new ArrayList<>();
161         addResourceList.addAll(serviceDecomposition.getServiceResources());
162
163         serviceDecomposition.setVnfResources(null);
164         serviceDecomposition.setAllottedResources(null);
165         serviceDecomposition.setNetworkResources(null);
166         serviceDecomposition.setConfigResources(null);
167         for (Resource resource : addResourceList) {
168             String resourcemodelName = resource.getModelInfo().getModelName();
169             if (StringUtils.containsIgnoreCase(resourcemodelName, "sppartner")) {
170                 // change serviceDecomposition
171                 serviceDecomposition.addResource(resource);
172                 break;
173             }
174         }
175
176         return uuiRequest;
177     }
178
179     private boolean isNeedProcessSite(String uuiRequest) {
180         return uuiRequest.toLowerCase().contains("address") && uuiRequest.toLowerCase().contains("clientsignal");
181     }
182
183     @SuppressWarnings("unchecked")
184     private boolean isSiteLocationLocal(Map<String, Object> serviceRequestInputs, List<Object> resources) {
185         Map<String, Object> tpInfoMap = getTPforVPNAttachment(serviceRequestInputs);
186
187         if (tpInfoMap.isEmpty()) {
188             return true;
189         }
190         String host = (String) tpInfoMap.get("host");
191         logger.info("host string from tpinfo:" + host);
192         // host is empty means TP is in local, not empty means TP is in remote ONAP
193         if (!host.isEmpty()) {
194             return false;
195         }
196
197         Map<String, Object> accessTPInfo = new HashMap<String, Object>();
198         accessTPInfo.put("access-provider-id", tpInfoMap.get("access-provider-id"));
199         accessTPInfo.put("access-client-id", tpInfoMap.get("access-client-id"));
200         accessTPInfo.put("access-topology-id", tpInfoMap.get("access-topology-id"));
201         accessTPInfo.put("access-node-id", tpInfoMap.get("access-node-id"));
202         accessTPInfo.put("access-ltp-id", tpInfoMap.get("access-ltp-id"));
203
204         // change resources
205         boolean flgResourceFound = false;
206         String resourceName = (String) tpInfoMap.get("resourceName");
207         for (Object curResource : resources) {
208             Map<String, Object> resource = (Map<String, Object>) curResource;
209             String curResourceName = (String) resource.get("resourceName");
210             curResourceName = curResourceName.replaceAll(" ", "");
211             if (resourceName.equalsIgnoreCase(curResourceName)) {
212                 flgResourceFound = true;
213                 logger.info("found match to add site tp info using uui template resource name");
214                 putResourceRequestInputs(resource, accessTPInfo);
215                 break;
216             }
217         }
218
219         if (!flgResourceFound) {
220             String attacmentResName = UrnPropertiesReader.getVariable("sp-partner.attachment-resource-name");
221             for (Object curResource : resources) {
222                 Map<String, Object> resource = (Map<String, Object>) curResource;
223                 String curResourceName = (String) resource.get("resourceName");
224
225                 if (attacmentResName.equals(curResourceName)) {
226                     logger.info("found match to add site tp info using customized resource name");
227                     putResourceRequestInputs(resource, accessTPInfo);
228                 }
229             }
230         }
231
232         return true;
233     }
234
235     @SuppressWarnings("unchecked")
236     private Map<String, Object> getTPforVPNAttachment(Map<String, Object> serviceRequestInputs) {
237         Object location = null;
238         Object clientSignal = null;
239         String vpnAttachmentResourceName = null;
240
241         // support R2 uuiReq and R1 uuiReq
242         // logic for R2 uuiRequest params in service level
243         for (Entry<String, Object> entry : serviceRequestInputs.entrySet()) {
244             String key = entry.getKey();
245             if (key.toLowerCase().contains("address")) {
246                 location = entry.getValue();
247             }
248             if (key.toLowerCase().contains("clientsignal")) {
249                 clientSignal = entry.getValue();
250                 vpnAttachmentResourceName = key.substring(0, key.indexOf("_"));
251             }
252         }
253
254         Map<String, Object> tpInfoMap = new HashMap<String, Object>();
255
256         // Site resource has location param and SOTNAttachment resource has clientSignal param
257         if (location == null || clientSignal == null) {
258             return tpInfoMap;
259         }
260
261         // Query terminal points from InventoryOSS system by location.
262         String locationAddress = (String) location;
263         List<Object> locationTPList = queryAccessTPbyLocationFromInventoryOSS(locationAddress);
264         if (locationTPList != null && !locationTPList.isEmpty()) {
265             for (Object tp : locationTPList) {
266                 Map<String, Object> tpJson = (Map<String, Object>) tp;
267                 String loc = (String) tpJson.get("location");
268                 if (StringUtils.equalsIgnoreCase(locationAddress, loc)) {
269                     tpInfoMap = tpJson;
270                     // add resourceName
271                     tpInfoMap.put("resourceName", vpnAttachmentResourceName);
272                     logger.info("*** we will try to find resourcename(" + vpnAttachmentResourceName
273                             + ") to add resource input ***");
274                     break;
275                 }
276             }
277             logger.info("Get Terminal TP from InventoryOSS: " + tpInfoMap);
278             return tpInfoMap;
279         }
280
281         return tpInfoMap;
282     }
283
284     @SuppressWarnings("unchecked")
285     private List<Object> queryAccessTPbyLocationFromInventoryOSS(String locationAddress) {
286         String url = getInventoryOSSEndPoint();
287         url += "/oss/inventory?location=" + UriUtils.encode(locationAddress, "UTF-8");
288         String responseContent = sendRequest(url, "GET", "");
289         List<Object> accessTPs = new ArrayList<>();
290         if (null != responseContent) {
291             accessTPs = getJsonObject(responseContent, List.class);
292         }
293         return accessTPs;
294     }
295
296     @SuppressWarnings("unchecked")
297     private void putResourceRequestInputs(Map<String, Object> resource, Map<String, Object> resourceInputs) {
298         Map<String, Object> resourceParametersObject = new HashMap<>();
299         Map<String, Object> resourceRequestInputs = new HashMap<>();
300         resourceRequestInputs.put("requestInputs", resourceInputs);
301         resourceParametersObject.put("parameters", resourceRequestInputs);
302
303         if (resource.containsKey("parameters")) {
304             Map<String, Object> resParametersObject = (Map<String, Object>) resource.get("parameters");
305             if (resParametersObject.containsKey("requestInputs")) {
306                 Map<String, Object> resRequestInputs = (Map<String, Object>) resourceRequestInputs.get("requestInputs");
307                 Map<String, Object> oldRequestInputs = (Map<String, Object>) resParametersObject.get("requestInputs");
308                 if (oldRequestInputs != null) {
309                     oldRequestInputs.putAll(resRequestInputs);
310                 } else {
311                     resParametersObject.put("requestInputs", resRequestInputs);
312                 }
313             } else {
314                 resParametersObject.putAll(resourceRequestInputs);
315             }
316         } else {
317             resource.putAll(resourceParametersObject);
318         }
319
320         return;
321     }
322
323
324
325     @SuppressWarnings("unchecked")
326     public String doTPResourcesAllocation(DelegateExecution execution, String uuiRequest) {
327         Map<String, Object> uuiObject = getJsonObject(uuiRequest, Map.class);
328         if (uuiObject == null) {
329             return uuiRequest;
330         }
331         Map<String, Object> serviceObject =
332                 (Map<String, Object>) uuiObject.getOrDefault("service", Collections.emptyMap());
333         Map<String, Object> serviceParametersObject =
334                 (Map<String, Object>) serviceObject.getOrDefault("parameters", Collections.emptyMap());
335         Map<String, Object> serviceRequestInputs =
336                 (Map<String, Object>) serviceParametersObject.getOrDefault("requestInputs", Collections.emptyMap());
337
338         if (!isNeedAllocateCrossTPResources(serviceRequestInputs)) {
339             return uuiRequest;
340         }
341
342         allocateCrossTPResources(execution, serviceRequestInputs);
343         return getJsonString(uuiObject);
344     }
345
346     @SuppressWarnings("unchecked")
347     private boolean isNeedAllocateCrossTPResources(Map<String, Object> serviceRequestInputs) {
348         if (serviceRequestInputs.containsKey("CallSource")) {
349             String callSource = (String) serviceRequestInputs.get("CallSource");
350             if ("ExternalAPI".equalsIgnoreCase(callSource)) {
351                 return false;
352             }
353         }
354         for (String input : serviceRequestInputs.keySet()) {
355             if (input.toLowerCase().contains("sotnconnectivity")) {
356                 return true;
357             }
358         }
359         return false;
360     }
361
362     private void customizeTP(Map<String, Object> crossTps, String svcName, DelegateExecution execution) {
363         Optional<String> customType = Arrays.stream(CUSTOM_TP_LIST).filter(svcName::contains).findFirst();
364         if (customType.isPresent()) {
365             logger.info("customizing TP");
366             String localTPs = UrnPropertiesReader.getVariable(CUSTOM_RESOURCE_TP + "." + customType.get() + ".local");
367             String remoteTPs = UrnPropertiesReader.getVariable(CUSTOM_RESOURCE_TP + "." + customType.get() + ".remote");
368
369             String localTP = (String) crossTps.get("local-access-ltp-id");
370             String remoteTP = (String) crossTps.get("remote-access-ltp-id");
371
372             if (localTPs.contains(localTP) && remoteTPs.contains(remoteTP)) {
373                 logger.info("using same tp returned from AAI");
374                 return;
375             }
376
377             crossTps.put("local-access-ltp-id", localTPs.split(",")[0]);
378             crossTps.put("remote-access-ltp-id", remoteTPs.split(",")[0]);
379         }
380         logger.info("cross TP info:" + crossTps);
381     }
382
383     @SuppressWarnings("unchecked")
384     private void allocateCrossTPResources(DelegateExecution execution, Map<String, Object> serviceRequestInputs) {
385
386         String serviceName = (String) execution.getVariable("serviceInstanceName");
387         Map<String, Object> crossTPs = this.getTPsfromAAI(serviceName);
388         // customizeTP(crossTPs, serviceName, execution);
389
390         if (crossTPs == null || crossTPs.isEmpty()) {
391             serviceRequestInputs.put("local-access-provider-id", "");
392             serviceRequestInputs.put("local-access-client-id", "");
393             serviceRequestInputs.put("local-access-topology-id", "");
394             serviceRequestInputs.put("local-access-node-id", "");
395             serviceRequestInputs.put("local-access-ltp-id", "");
396             serviceRequestInputs.put("remote-access-provider-id", "");
397             serviceRequestInputs.put("remote-access-client-id", "");
398             serviceRequestInputs.put("remote-access-topology-id", "");
399             serviceRequestInputs.put("remote-access-node-id", "");
400             serviceRequestInputs.put("remote-access-ltp-id", "");
401         } else {
402             serviceRequestInputs.put("local-access-provider-id", crossTPs.get("local-access-provider-id"));
403             serviceRequestInputs.put("local-access-client-id", crossTPs.get("local-access-client-id"));
404             serviceRequestInputs.put("local-access-topology-id", crossTPs.get("local-access-topology-id"));
405             serviceRequestInputs.put("local-access-node-id", crossTPs.get("local-access-node-id"));
406             serviceRequestInputs.put("local-access-ltp-id", crossTPs.get("local-access-ltp-id"));
407             serviceRequestInputs.put("remote-access-provider-id", crossTPs.get("remote-access-provider-id"));
408             serviceRequestInputs.put("remote-access-client-id", crossTPs.get("remote-access-client-id"));
409             serviceRequestInputs.put("remote-access-topology-id", crossTPs.get("remote-access-topology-id"));
410             serviceRequestInputs.put("remote-access-node-id", crossTPs.get("remote-access-node-id"));
411             serviceRequestInputs.put("remote-access-ltp-id", crossTPs.get("remote-access-ltp-id"));
412         }
413
414         return;
415     }
416
417     private LogicalLink selectLogicalLink(List<LogicalLink> logicalLinks, String svcName) {
418         Optional<String> customType = Arrays.stream(CUSTOM_TP_LIST).filter(svcName::contains).findFirst();
419         if (customType.isPresent()) {
420
421             String[] allowedList =
422                     UrnPropertiesReader.getVariable(CUSTOM_RESOURCE_TP + "." + customType.get() + ".local").split(",");
423
424             for (String localTp : allowedList) {
425                 for (LogicalLink link : logicalLinks) {
426                     for (Relationship relationship : link.getRelationshipList().getRelationship()) {
427                         if (relationship.getRelatedTo().equals("p-interface")
428                                 && relationship.getRelatedLink().contains("-ltpId-" + localTp)
429                                 && link.getOperationalStatus().equalsIgnoreCase("up")) {
430                             logger.info("linkname:" + link.getLinkName() + " is matching with allowed list");
431                             return link;
432                         }
433                     }
434                 }
435             }
436
437             logger.error("There is no matching logical link for allowed list :" + Arrays.toString(allowedList));
438             return null;
439         } else {
440             logger.info("link customization is not required");
441             return logicalLinks.get(0);
442         }
443     }
444
445     // This method returns Local and remote TPs information from AAI
446     public Map getTPsfromAAI(String serviceName) {
447         Map<String, Object> tpInfo = new HashMap<>();
448
449         AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectPlurals.LOGICAL_LINK);
450         AAIResourcesClient client = new AAIResourcesClient();
451         Optional<LogicalLinks> result = client.get(LogicalLinks.class, uri);
452
453         if (result.isPresent()) {
454             LogicalLinks links = result.get();
455             LogicalLink link = selectLogicalLink(links.getLogicalLink(), serviceName);
456
457             if (link != null) {
458                 boolean isRemoteLink = false;
459                 logger.info("processing link :" + link.getLinkName());
460                 AAIResultWrapper wrapper = new AAIResultWrapper(link);
461                 Optional<Relationships> optRelationships = wrapper.getRelationships();
462                 List<AAIResourceUri> pInterfaces = new ArrayList<>();
463                 if (optRelationships.isPresent()) {
464                     Relationships relationships = optRelationships.get();
465                     if (!relationships.getRelatedAAIUris(AAIObjectType.EXT_AAI_NETWORK).isEmpty()) {
466                         isRemoteLink = true;
467                     }
468                     pInterfaces.addAll(relationships.getRelatedAAIUris(AAIObjectType.P_INTERFACE));
469                     if (isRemoteLink) {
470                         // find remote p interface
471                         AAIResourceUri localTP = null;
472                         AAIResourceUri remoteTP = null;
473
474                         AAIResourceUri pInterface0 = pInterfaces.get(0);
475
476                         if (isRemotePInterface(client, pInterface0)) {
477                             remoteTP = pInterfaces.get(0);
478                             localTP = pInterfaces.get(1);
479                         } else {
480                             localTP = pInterfaces.get(0);
481                             remoteTP = pInterfaces.get(1);
482                         }
483
484                         if (localTP != null && remoteTP != null) {
485                             // give local tp
486                             String tpUrl = localTP.build().toString();
487                             String localNodeId = tpUrl.split("/")[4];
488                             tpInfo.put("local-access-node-id", localNodeId);
489
490                             logger.info("Get info for local TP :" + localNodeId);
491                             Optional<Pnf> optLocalPnf = client.get(Pnf.class,
492                                     AAIUriFactory.createResourceUri(AAIObjectType.PNF, localNodeId));
493
494                             if (optLocalPnf.isPresent()) {
495                                 Pnf localPnf = optLocalPnf.get();
496
497                                 for (Relationship rel : localPnf.getRelationshipList().getRelationship()) {
498                                     if (rel.getRelatedTo().equalsIgnoreCase("network-resource")) {
499                                         String[] networkRef = rel.getRelatedLink()
500                                                 .substring(rel.getRelatedLink().lastIndexOf("/") + 1).split("-");
501                                         if (networkRef.length == 6) {
502                                             tpInfo.put("local-access-provider-id", networkRef[1]);
503                                             tpInfo.put("local-access-client-id", networkRef[3]);
504                                             tpInfo.put("local-access-topology-id", networkRef[5]);
505                                         }
506                                     }
507                                 }
508                             }
509                             String ltpIdStr = tpUrl.substring(tpUrl.lastIndexOf("/") + 1);
510                             if (ltpIdStr.contains("-")) {
511                                 tpInfo.put("local-access-ltp-id", ltpIdStr.substring(ltpIdStr.lastIndexOf("-") + 1));
512                             }
513
514                             // give remote tp
515                             tpUrl = remoteTP.build().toString();
516                             PInterface intfRemote = client.get(PInterface.class, remoteTP).get();
517
518                             String remoteNodeId = tpUrl.split("/")[4];
519                             tpInfo.put("remote-access-node-id", remoteNodeId);
520
521                             logger.info("Get info for remote TP:" + remoteNodeId);
522
523                             String[] networkRefRemote = intfRemote.getNetworkRef().split("-");
524                             Optional<Pnf> optRemotePnf = client.get(Pnf.class,
525                                     AAIUriFactory.createResourceUri(AAIObjectType.PNF, remoteNodeId));
526
527                             if (optRemotePnf.isPresent()) {
528                                 Pnf remotePnf = optRemotePnf.get();
529
530                                 for (Relationship rel : remotePnf.getRelationshipList().getRelationship()) {
531                                     if (rel.getRelatedTo().equalsIgnoreCase("network-resource")) {
532                                         String[] networkRef = rel.getRelatedLink()
533                                                 .substring(rel.getRelatedLink().lastIndexOf("/") + 1).split("-");
534                                         if (networkRef.length == 6) {
535                                             tpInfo.put("remote-access-provider-id", networkRefRemote[1]);
536                                             tpInfo.put("remote-access-client-id", networkRefRemote[3]);
537                                             tpInfo.put("remote-access-topology-id", networkRefRemote[5]);
538                                         }
539                                     }
540                                 }
541                             }
542
543                             String ltpIdStrR = tpUrl.substring(tpUrl.lastIndexOf("/") + 1);
544                             if (ltpIdStrR.contains("-")) {
545                                 tpInfo.put("remote-access-ltp-id", ltpIdStrR.substring(ltpIdStr.lastIndexOf("-") + 1));
546                             }
547                         }
548                     }
549                 }
550             }
551         }
552         return tpInfo;
553     }
554
555     // this method check if pInterface is remote
556     private boolean isRemotePInterface(AAIResourcesClient client, AAIResourceUri uri) {
557
558         String uriString = uri.build().toString();
559
560         if (uriString != null) {
561             // get the pnfname
562             String[] token = uriString.split("/");
563             AAIResourceUri parent = AAIUriFactory.createResourceUri(AAIObjectType.PNF, token[4]);
564
565             AAIResultWrapper wrapper = client.get(parent);
566             Optional<Relationships> optRelationships = wrapper.getRelationships();
567             if (optRelationships.isPresent()) {
568                 Relationships relationships = optRelationships.get();
569
570                 return !relationships.getRelatedAAIUris(AAIObjectType.EXT_AAI_NETWORK).isEmpty();
571             }
572         }
573
574         return false;
575     }
576
577     public String preProcessService(ServiceDecomposition serviceDecomposition, String uuiRequest) {
578
579         // now only for sotn
580         if (isSOTN(serviceDecomposition, uuiRequest)) {
581             // We Need to query the terminalpoint of the VPN by site location
582             // info
583             return preProcessSOTNService(serviceDecomposition, uuiRequest);
584         }
585         return uuiRequest;
586     }
587
588     public String doServiceHoming(ServiceDecomposition serviceDecomposition, String uuiRequest) {
589         // now only for sotn
590         if (isSOTN(serviceDecomposition, uuiRequest)) {
591             return doSOTNServiceHoming(serviceDecomposition, uuiRequest);
592         }
593         return uuiRequest;
594     }
595
596     private boolean isSOTN(ServiceDecomposition serviceDecomposition, String uuiRequest) {
597         // there should be a register platform , we check it very simple here.
598         return uuiRequest.contains("clientSignal") && uuiRequest.contains("vpnType");
599     }
600
601     @SuppressWarnings("unchecked")
602     private String preProcessSOTNService(ServiceDecomposition serviceDecomposition, String uuiRequest) {
603         Map<String, Object> uuiObject = getJsonObject(uuiRequest, Map.class);
604         if (uuiObject == null) {
605             return uuiRequest;
606         }
607         Map<String, Object> serviceObject =
608                 (Map<String, Object>) uuiObject.getOrDefault("service", Collections.emptyMap());
609         Map<String, Object> serviceParametersObject =
610                 (Map<String, Object>) serviceObject.getOrDefault("parameters", Collections.emptyMap());
611         Map<String, Object> serviceRequestInputs =
612                 (Map<String, Object>) serviceParametersObject.getOrDefault("requestInputs", Collections.emptyMap());
613         List<Object> resources =
614                 (List<Object>) serviceParametersObject.getOrDefault("resources", Collections.emptyList());
615         // This is a logic for demo , it could not be finalized to community.
616         String srcLocation = "";
617         String dstLocation = "";
618         String srcClientSignal = "";
619         String dstClientSignal = "";
620         // support R2 uuiReq and R1 uuiReq
621         // logic for R2 uuiRequest params in service level
622         for (Entry<String, Object> entry : serviceRequestInputs.entrySet()) {
623             if (entry.getKey().toLowerCase().contains("location")) {
624                 if ("".equals(srcLocation)) {
625                     srcLocation = (String) entry.getValue();
626                 } else if ("".equals(dstLocation)) {
627                     dstLocation = (String) entry.getValue();
628                 }
629             }
630             if (entry.getKey().toLowerCase().contains("clientsignal")) {
631                 if ("".equals(srcClientSignal)) {
632                     srcClientSignal = (String) entry.getValue();
633                 } else if ("".equals(dstClientSignal)) {
634                     dstClientSignal = (String) entry.getValue();
635                 }
636             }
637         }
638
639         // logic for R1 uuiRequest, params in resource level
640         for (Object resource : resources) {
641             Map<String, Object> resourceObject = (Map<String, Object>) resource;
642             Map<String, Object> resourceParametersObject = (Map<String, Object>) resourceObject.get("parameters");
643             Map<String, Object> resourceRequestInputs =
644                     (Map<String, Object>) resourceParametersObject.get("requestInputs");
645             for (Entry<String, Object> entry : resourceRequestInputs.entrySet()) {
646                 if (entry.getKey().toLowerCase().contains("location")) {
647                     if ("".equals(srcLocation)) {
648                         srcLocation = (String) entry.getValue();
649                     } else if ("".equals(dstLocation)) {
650                         dstLocation = (String) entry.getValue();
651                     }
652                 }
653                 if (entry.getKey().toLowerCase().contains("clientsignal")) {
654                     if ("".equals(srcClientSignal)) {
655                         srcClientSignal = (String) entry.getValue();
656                     } else if ("".equals(dstClientSignal)) {
657                         dstClientSignal = (String) entry.getValue();
658                     }
659                 }
660             }
661         }
662
663         Map<String, Object> vpnRequestInputs = getVPNResourceRequestInputs(resources);
664         // here we put client signal to vpn resource inputs
665         if (null != vpnRequestInputs) {
666             vpnRequestInputs.put("src-client-signal", srcClientSignal);
667             vpnRequestInputs.put("dst-client-signal", dstClientSignal);
668         }
669
670
671         // Now we need to query terminal points from SP resourcemgr system.
672         List<Object> locationTerminalPointList = queryTerminalPointsFromServiceProviderSystem(srcLocation, dstLocation);
673         if (locationTerminalPointList != null) {
674             Map<String, Object> tpInfoMap = (Map<String, Object>) locationTerminalPointList.get(0);
675
676             serviceRequestInputs.put("inner-src-access-provider-id", tpInfoMap.get("access-provider-id"));
677             serviceRequestInputs.put("inner-src-access-client-id", tpInfoMap.get("access-client-id"));
678             serviceRequestInputs.put("inner-src-access-topology-id", tpInfoMap.get("access-topology-id"));
679             serviceRequestInputs.put("inner-src-access-node-id", tpInfoMap.get("access-node-id"));
680             serviceRequestInputs.put("inner-src-access-ltp-id", tpInfoMap.get("access-ltp-id"));
681             tpInfoMap = (Map<String, Object>) locationTerminalPointList.get(1);
682
683             serviceRequestInputs.put("inner-dst-access-provider-id", tpInfoMap.get("access-provider-id"));
684             serviceRequestInputs.put("inner-dst-access-client-id", tpInfoMap.get("access-client-id"));
685             serviceRequestInputs.put("inner-dst-access-topology-id", tpInfoMap.get("access-topology-id"));
686             serviceRequestInputs.put("inner-dst-access-node-id", tpInfoMap.get("access-node-id"));
687             serviceRequestInputs.put("inner-dst-access-ltp-id", tpInfoMap.get("access-ltp-id"));
688         }
689         String newRequest = getJsonString(uuiObject);
690         return newRequest;
691     }
692
693     private List<Object> queryTerminalPointsFromServiceProviderSystem(String srcLocation, String dstLocation) {
694         Map<String, String> locationSrc = new HashMap<>();
695         locationSrc.put("location", srcLocation);
696         Map<String, String> locationDst = new HashMap<>();
697         locationDst.put("location", dstLocation);
698         List<Map<String, String>> locations = new ArrayList<>();
699         locations.add(locationSrc);
700         locations.add(locationDst);
701         List<Object> returnList = new ArrayList<>();
702         String reqContent = getJsonString(locations);
703         String url = getThirdSPEndPoint();
704         String responseContent = sendRequest(url, "POST", reqContent);
705         if (null != responseContent) {
706             returnList = getJsonObject(responseContent, List.class);
707         }
708         return returnList;
709     }
710
711     @SuppressWarnings("unchecked")
712     private Map<String, Object> getVPNResourceRequestInputs(List<Object> resources) {
713         for (Object resource : resources) {
714             Map<String, Object> resourceObject = (Map<String, Object>) resource;
715             Map<String, Object> resourceParametersObject = (Map<String, Object>) resourceObject.get("parameters");
716             Map<String, Object> resourceRequestInputs =
717                     (Map<String, Object>) resourceParametersObject.get("requestInputs");
718             for (Entry<String, Object> entry : resourceRequestInputs.entrySet()) {
719                 if (entry.getKey().toLowerCase().contains("vpntype")) {
720                     return resourceRequestInputs;
721                 }
722             }
723         }
724         return null;
725     }
726
727     public static void main(String args[]) {
728         String str =
729                 "restconf/config/GENERIC-RESOURCE-API:services/service/eca7e542-12ba-48de-8544-fac59303b14e/service-data/networks/network/aec07806-1671-4af2-b722-53c8e320a633/network-data/";
730
731         int index1 = str.indexOf("/network/");
732         int index2 = str.indexOf("/network-data");
733
734         String str1 = str.substring(index1 + "/network/".length(), index2);
735         System.out.println(str1);
736
737     }
738
739     @SuppressWarnings("unchecked")
740     private String doSOTNServiceHoming(ServiceDecomposition serviceDecomposition, String uuiRequest) {
741         // query the route for the service.
742         Map<String, Object> uuiObject = getJsonObject(uuiRequest, Map.class);
743         if (uuiObject == null) {
744             return uuiRequest;
745         }
746         Map<String, Object> serviceObject =
747                 (Map<String, Object>) uuiObject.getOrDefault("service", Collections.emptyMap());
748         Map<String, Object> serviceParametersObject =
749                 (Map<String, Object>) serviceObject.getOrDefault("parameters", Collections.emptyMap());
750         Map<String, Object> serviceRequestInputs =
751                 (Map<String, Object>) serviceParametersObject.getOrDefault("requestInputs", Collections.emptyMap());
752         Map<String, Object> oofQueryObject = new HashMap<>();
753         List<Object> resources =
754                 (List<Object>) serviceParametersObject.getOrDefault("resources", Collections.emptyList());
755         oofQueryObject.put("src-access-provider-id", serviceRequestInputs.get("inner-src-access-provider-id"));
756         oofQueryObject.put("src-access-client-id", serviceRequestInputs.get("inner-src-access-client-id"));
757         oofQueryObject.put("src-access-topology-id", serviceRequestInputs.get("inner-src-access-topology-id"));
758         oofQueryObject.put("src-access-node-id", serviceRequestInputs.get("inner-src-access-node-id"));
759         oofQueryObject.put("src-access-ltp-id", serviceRequestInputs.get("inner-src-access-ltp-id"));
760         oofQueryObject.put("dst-access-provider-id", serviceRequestInputs.get("inner-dst-access-provider-id"));
761         oofQueryObject.put("dst-access-client-id", serviceRequestInputs.get("inner-dst-access-client-id"));
762         oofQueryObject.put("dst-access-topology-id", serviceRequestInputs.get("inner-dst-access-topology-id"));
763         oofQueryObject.put("dst-access-node-id", serviceRequestInputs.get("inner-dst-access-node-id"));
764         oofQueryObject.put("dst-access-ltp-id", serviceRequestInputs.get("inner-dst-access-ltp-id"));
765         String oofRequestReq = getJsonString(oofQueryObject);
766         String url = getOOFCalcEndPoint();
767         String responseContent = sendRequest(url, "POST", oofRequestReq);
768
769         List<Object> returnList = new ArrayList<>();
770         if (null != responseContent) {
771             returnList = getJsonObject(responseContent, List.class);
772         }
773         // in demo we have only one VPN. no cross VPNs, so get first item.
774         Map<String, Object> returnRoute = getReturnRoute(returnList);
775         Map<String, Object> vpnRequestInputs = getVPNResourceRequestInputs(resources);
776         if (null != vpnRequestInputs) {
777             vpnRequestInputs.putAll(returnRoute);
778         }
779         return getJsonString(uuiObject);
780     }
781
782     private Map<String, Object> getReturnRoute(List<Object> returnList) {
783         Map<String, Object> returnRoute = new HashMap<>();
784         for (Object returnVpn : returnList) {
785             Map<String, Object> returnVpnInfo = (Map<String, Object>) returnVpn;
786             String accessTopoId = (String) returnVpnInfo.get("access-topology-id");
787             if ("100".equals(accessTopoId)) {
788                 returnRoute.putAll(returnVpnInfo);
789             } else if ("101".equals(accessTopoId)) {
790                 for (String key : returnVpnInfo.keySet()) {
791                     returnRoute.put("domain1-" + key, returnVpnInfo.get(key));
792                 }
793             } else if ("102".equals(accessTopoId)) {
794                 for (String key : returnVpnInfo.keySet()) {
795                     returnRoute.put("domain2-" + key, returnVpnInfo.get(key));
796                 }
797             } else {
798                 for (String key : returnVpnInfo.keySet()) {
799                     returnRoute.put("domain" + accessTopoId + "-" + key, returnVpnInfo.get(key));
800                 }
801             }
802         }
803         return returnRoute;
804     }
805
806     private Map<String, Object> getResourceParams(Execution execution, String resourceCustomizationUuid,
807             String serviceParameters) {
808         List<String> resourceList =
809                 jsonUtil.StringArrayToList(execution, JsonUtils.getJsonValue(serviceParameters, "resources"));
810         // Get the right location str for resource. default is an empty array.
811         String resourceInputsFromUui = "";
812         for (String resource : resourceList) {
813             String resCusUuid = JsonUtils.getJsonValue(resource, "resourceCustomizationUuid");
814             if (resourceCustomizationUuid.equals(resCusUuid)) {
815                 String resourceParameters = JsonUtils.getJsonValue(resource, "parameters");
816                 resourceInputsFromUui = JsonUtils.getJsonValue(resourceParameters, "requestInputs");
817             }
818         }
819         Map<String, Object> resourceInputsFromUuiMap = getJsonObject(resourceInputsFromUui, Map.class);
820         return resourceInputsFromUuiMap;
821     }
822
823     private static <T> T getJsonObject(String jsonstr, Class<T> type) {
824         ObjectMapper mapper = new ObjectMapper();
825         mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
826         try {
827             return mapper.readValue(jsonstr, type);
828         } catch (IOException e) {
829             logger.error("{} {} fail to unMarshal json", MessageEnum.RA_NS_EXC.toString(),
830                     ErrorCode.BusinessProcesssError.getValue(), e);
831         }
832         return null;
833     }
834
835     public static String getJsonString(Object srcObj) {
836         ObjectMapper mapper = new ObjectMapper();
837         mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
838         String jsonStr = null;
839         try {
840             jsonStr = mapper.writeValueAsString(srcObj);
841         } catch (JsonProcessingException e) {
842             logger.debug("SdcToscaParserException", e);
843         }
844         return jsonStr;
845     }
846
847     private static String sendRequest(String url, String methodType, String content) {
848
849         String msbUrl = url;
850         HttpRequestBase method = null;
851         HttpResponse httpResponse = null;
852
853         try {
854             int timeout = DEFAULT_TIME_OUT;
855
856             RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout)
857                     .setConnectionRequestTimeout(timeout).build();
858
859             HttpClient client = HttpClientBuilder.create().build();
860
861             if ("POST".equals(methodType.toUpperCase())) {
862                 HttpPost httpPost = new HttpPost(msbUrl);
863                 httpPost.setConfig(requestConfig);
864                 httpPost.setEntity(new StringEntity(content, ContentType.APPLICATION_JSON));
865                 method = httpPost;
866             } else if ("PUT".equals(methodType.toUpperCase())) {
867                 HttpPut httpPut = new HttpPut(msbUrl);
868                 httpPut.setConfig(requestConfig);
869                 httpPut.setEntity(new StringEntity(content, ContentType.APPLICATION_JSON));
870                 method = httpPut;
871             } else if ("GET".equals(methodType.toUpperCase())) {
872                 HttpGet httpGet = new HttpGet(msbUrl);
873                 httpGet.setConfig(requestConfig);
874                 httpGet.addHeader("X-FromAppId", "MSO");
875                 httpGet.addHeader("Accept", "application/json");
876                 method = httpGet;
877             } else if ("DELETE".equals(methodType.toUpperCase())) {
878                 HttpDelete httpDelete = new HttpDelete(msbUrl);
879                 httpDelete.setConfig(requestConfig);
880                 method = httpDelete;
881             }
882
883             httpResponse = client.execute(method);
884             String responseContent = null;
885             if (null != httpResponse && httpResponse.getEntity() != null) {
886                 try {
887                     responseContent = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
888                 } catch (ParseException e) {
889                     logger.debug("ParseException in sendrequest", e);
890                 } catch (IOException e) {
891                     logger.debug("IOException in sendrequest", e);
892                 }
893             }
894             if (null != method) {
895                 method.reset();
896             }
897             method = null;
898             return responseContent;
899
900         } catch (SocketTimeoutException | ConnectTimeoutException e) {
901             return null;
902
903         } catch (Exception e) {
904             return null;
905
906         } finally {
907             if (httpResponse != null) {
908                 try {
909                     EntityUtils.consume(httpResponse.getEntity());
910                 } catch (Exception e) {
911                 }
912             }
913             if (method != null) {
914                 try {
915                     method.reset();
916                 } catch (Exception e) {
917
918                 }
919             }
920         }
921     }
922 }