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