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