use cache for retrieving all subscribers list
[vid.git] / vid-app-common / src / main / java / org / onap / vid / services / AaiServiceImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2018 - 2019 Nokia. All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.vid.services;
23
24 import static org.onap.vid.aai.AaiClient.QUERY_FORMAT_RESOURCE;
25 import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
26
27 import com.fasterxml.jackson.databind.JsonNode;
28 import java.io.UnsupportedEncodingException;
29 import java.net.URLEncoder;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.Collections;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Objects;
36 import java.util.concurrent.ExecutorService;
37 import java.util.stream.Collectors;
38 import javax.validation.constraints.NotNull;
39 import javax.ws.rs.core.Response;
40 import org.apache.commons.lang3.StringUtils;
41 import org.apache.http.HttpStatus;
42 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
43 import org.onap.vid.aai.AaiClientInterface;
44 import org.onap.vid.aai.AaiGetVnfResponse;
45 import org.onap.vid.aai.AaiOverTLSClientInterface;
46 import org.onap.vid.aai.AaiResponse;
47 import org.onap.vid.aai.AaiResponseTranslator;
48 import org.onap.vid.aai.ExceptionWithRequestInfo;
49 import org.onap.vid.aai.ServiceInstance;
50 import org.onap.vid.aai.ServiceInstancesSearchResults;
51 import org.onap.vid.aai.ServiceSubscription;
52 import org.onap.vid.aai.ServiceSubscriptions;
53 import org.onap.vid.aai.Services;
54 import org.onap.vid.aai.SubscriberFilteredResults;
55 import org.onap.vid.aai.model.AaiGetInstanceGroupsByCloudRegion;
56 import org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.AaiGetRelatedInstanceGroupsByVnfId;
57 import org.onap.vid.aai.model.AaiGetOperationalEnvironments.OperationalEnvironmentList;
58 import org.onap.vid.aai.model.AaiGetPnfs.Pnf;
59 import org.onap.vid.aai.model.AaiGetServicesRequestModel.GetServicesAAIRespone;
60 import org.onap.vid.aai.model.AaiGetTenatns.GetTenantsResponse;
61 import org.onap.vid.aai.model.AaiRelationResponse;
62 import org.onap.vid.aai.model.GetServiceModelsByDistributionStatusResponse;
63 import org.onap.vid.aai.model.InstanceGroupInfo;
64 import org.onap.vid.aai.model.LogicalLinkResponse;
65 import org.onap.vid.aai.model.Model;
66 import org.onap.vid.aai.model.ModelVer;
67 import org.onap.vid.aai.model.OwningEntity;
68 import org.onap.vid.aai.model.OwningEntityResponse;
69 import org.onap.vid.aai.model.PortDetailsTranslator;
70 import org.onap.vid.aai.model.Project;
71 import org.onap.vid.aai.model.ProjectResponse;
72 import org.onap.vid.aai.model.Properties;
73 import org.onap.vid.aai.model.RelatedToProperty;
74 import org.onap.vid.aai.model.Relationship;
75 import org.onap.vid.aai.model.RelationshipData;
76 import org.onap.vid.aai.model.RelationshipList;
77 import org.onap.vid.aai.model.Result;
78 import org.onap.vid.aai.model.ServiceRelationships;
79 import org.onap.vid.aai.model.VnfResult;
80 import org.onap.vid.asdc.beans.Service;
81 import org.onap.vid.exceptions.GenericUncheckedException;
82 import org.onap.vid.model.ServiceInstanceSearchResult;
83 import org.onap.vid.model.SubscriberList;
84 import org.onap.vid.model.aaiTree.AAITreeNode;
85 import org.onap.vid.model.aaiTree.Network;
86 import org.onap.vid.model.aaiTree.NodeType;
87 import org.onap.vid.model.aaiTree.RelatedVnf;
88 import org.onap.vid.model.aaiTree.VpnBinding;
89 import org.onap.vid.model.aaiTree.VpnBindingKt;
90 import org.onap.vid.roles.RoleValidator;
91 import org.onap.vid.utils.Intersection;
92 import org.onap.vid.utils.Tree;
93 import org.springframework.beans.factory.annotation.Autowired;
94 import org.springframework.http.HttpMethod;
95
96 public class AaiServiceImpl implements AaiService {
97     private static final String SERVICE_INSTANCE_ID = "service-instance.service-instance-id";
98     private static final String SERVICE_TYPE = "service-subscription.service-type";
99     private static final String CUSTOMER_ID = "customer.global-customer-id";
100     private static final String SERVICE_INSTANCE_NAME = "service-instance.service-instance-name";
101     private static final String TENANT_NODE_TYPE = "tenant";
102     private static final String CLOUD_REGION_NODE_TYPE = "cloud-region";
103     private int indexOfSubscriberName = 6;
104
105     private AaiClientInterface aaiClient;
106     private AaiResponseTranslator aaiResponseTranslator;
107     private AAIServiceTree aaiServiceTree;
108     private ExecutorService executorService;
109
110
111     private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AaiServiceImpl.class);
112
113     @Autowired
114     public AaiServiceImpl(
115         AaiClientInterface aaiClient,
116         AaiResponseTranslator aaiResponseTranslator,
117         AAIServiceTree aaiServiceTree,
118         ExecutorService executorService)
119     {
120         this.aaiClient = aaiClient;
121         this.aaiResponseTranslator = aaiResponseTranslator;
122         this.aaiServiceTree = aaiServiceTree;
123         this.executorService = executorService;
124     }
125
126     private List<Service> convertModelToService(Model model) {
127         List<Service> services = new ArrayList<>();
128
129         if(validateModel(model)){
130             for (ModelVer modelVer: model.getModelVers().getModelVer()) {
131                 Service service = new Service.ServiceBuilder()
132                         .setUuid(modelVer.getModelVersionId())
133                         .setInvariantUUID(model.getModelInvariantId())
134                         .setCategory(model.getModelType() != null ? model.getModelType() : "")
135                         .setVersion(modelVer.getModelVersion())
136                         .setName( modelVer.getModelName())
137                         .setDistributionStatus(modelVer.getDistributionStatus())
138                         .setToscaModelURL(null)
139                         .setLifecycleState(null)
140                         .setArtifacts(null)
141                         .setResources(null).build();
142
143
144
145                 services.add(service);
146             }
147         } else {
148             return Collections.emptyList();
149         }
150
151         return services;
152     }
153
154     private boolean validateModel(Model model){
155         if (model == null) {
156             return false;
157         } else {
158             return model.getModelVers() != null && model.getModelVers().getModelVer() != null && model.getModelVers().getModelVer().get(0).getModelVersionId() != null;
159         }
160     }
161
162     private List<ServiceInstanceSearchResult> getServicesByOwningEntityId(List<String> owningEntities, RoleValidator roleValidator) {
163         AaiResponse<OwningEntityResponse> owningEntityResponse = aaiClient.getServicesByOwningEntityId(owningEntities);
164         List<ServiceInstanceSearchResult> serviceInstanceSearchResultList = new ArrayList<>();
165         if (owningEntityResponse.getT() != null) {
166             for (OwningEntity owningEntity : owningEntityResponse.getT().getOwningEntity()) {
167                 if (owningEntity.getRelationshipList() != null) {
168                     serviceInstanceSearchResultList = convertRelationshipToSearchResult(owningEntity, serviceInstanceSearchResultList, roleValidator);
169                 }
170             }
171         }
172         return serviceInstanceSearchResultList;
173     }
174
175     private List<ServiceInstanceSearchResult> getServicesByProjectNames(List<String> projectNames, RoleValidator roleValidator) {
176         AaiResponse<ProjectResponse> projectByIdResponse = aaiClient.getServicesByProjectNames(projectNames);
177         List<ServiceInstanceSearchResult> serviceInstanceSearchResultList = new ArrayList<>();
178         if (projectByIdResponse.getT() != null) {
179             for (Project project : projectByIdResponse.getT().getProject()) {
180                 if (project.getRelationshipList() != null) {
181                     serviceInstanceSearchResultList = convertRelationshipToSearchResult(project, serviceInstanceSearchResultList, roleValidator);
182                 }
183             }
184         }
185         return serviceInstanceSearchResultList;
186     }
187
188     private List<ServiceInstanceSearchResult> convertRelationshipToSearchResult(AaiRelationResponse owningEntityResponse, List<ServiceInstanceSearchResult> serviceInstanceSearchResultList, RoleValidator roleValidator) {
189         if (owningEntityResponse.getRelationshipList().getRelationship() != null) {
190             List<Relationship> relationshipList = owningEntityResponse.getRelationshipList().getRelationship();
191             for (Relationship relationship : relationshipList) {
192                 ServiceInstanceSearchResult serviceInstanceSearchResult = new ServiceInstanceSearchResult();
193                 extractRelationshipData(relationship, serviceInstanceSearchResult, roleValidator);
194                 extractRelatedToProperty(relationship, serviceInstanceSearchResult);
195                 serviceInstanceSearchResultList.add(serviceInstanceSearchResult);
196             }
197         }
198         return serviceInstanceSearchResultList;
199     }
200
201     private void extractRelationshipData(Relationship relationship, ServiceInstanceSearchResult serviceInstanceSearchResult, RoleValidator roleValidator) {
202         List<RelationshipData> relationshipDataList = relationship.getRelationDataList();
203         if (relationshipDataList != null) {
204             setSubscriberName(relationship, serviceInstanceSearchResult);
205             for (RelationshipData relationshipData : relationshipDataList) {
206                 String key = relationshipData.getRelationshipKey();
207                 if (key.equals(SERVICE_INSTANCE_ID)) {
208                     serviceInstanceSearchResult.setServiceInstanceId(relationshipData.getRelationshipValue());
209                 } else if (key.equals(SERVICE_TYPE)) {
210                     serviceInstanceSearchResult.setServiceType(relationshipData.getRelationshipValue());
211                 } else if (key.equals(CUSTOMER_ID)) {
212                     serviceInstanceSearchResult.setGlobalCustomerId(relationshipData.getRelationshipValue());
213                 }
214             }
215
216             boolean isPermitted = roleValidator.isServicePermitted(serviceInstanceSearchResult.getSubscriberName(), serviceInstanceSearchResult.getServiceType());
217             serviceInstanceSearchResult.setIsPermitted(isPermitted);
218         }
219     }
220
221     private void setSubscriberName(Relationship relationship, ServiceInstanceSearchResult serviceInstanceSearchResult) {
222         String relatedLink = relationship.getRelatedLink();
223         String[] subsciber = relatedLink.split("/");
224         serviceInstanceSearchResult.setSubscriberName(subsciber[indexOfSubscriberName]);
225     }
226
227     private void extractRelatedToProperty(Relationship relationship, ServiceInstanceSearchResult serviceInstanceSearchResult) {
228         List<RelatedToProperty> relatedToPropertyList = relationship.getRelatedToPropertyList();
229         if (relatedToPropertyList != null) {
230             for (RelatedToProperty relatedToProperty : relatedToPropertyList) {
231                 if (relatedToProperty.getPropertyKey().equals(SERVICE_INSTANCE_NAME)) {
232                     serviceInstanceSearchResult.setServiceInstanceName(relatedToProperty.getPropertyValue());
233                 }
234             }
235         }
236     }
237
238     @Override
239     public SubscriberFilteredResults getFullSubscriberList(RoleValidator roleValidator) {
240         AaiResponse<SubscriberList> subscriberResponse = aaiClient.getAllSubscribers();
241
242         return new SubscriberFilteredResults(roleValidator, subscriberResponse.getT(),
243                 subscriberResponse.getErrorMessage(),
244                 subscriberResponse.getHttpCode());
245     }
246
247     @Override
248     public AaiResponse<OperationalEnvironmentList> getOperationalEnvironments(String operationalEnvironmentType, String operationalEnvironmentStatus) {
249         return aaiClient.getOperationalEnvironments(operationalEnvironmentType, operationalEnvironmentStatus);
250     }
251
252     @Override
253     public AaiResponse<SubscriberList> getFullSubscriberList() {
254         return aaiClient.getAllSubscribers();
255     }
256
257     @Override
258     public AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator, boolean omitServiceInstances) {
259         AaiResponse<Services> subscriberResponse = aaiClient.getSubscriberData(subscriberId, omitServiceInstances);
260         String subscriberGlobalId = subscriberResponse.getT().globalCustomerId;
261         for (ServiceSubscription serviceSubscription : subscriberResponse.getT().serviceSubscriptions.serviceSubscription) {
262             String serviceType = serviceSubscription.serviceType;
263             serviceSubscription.isPermitted = roleValidator.isServicePermitted(subscriberGlobalId, serviceType);
264         }
265         return subscriberResponse;
266
267     }
268
269     @Override
270     public AaiResponse getServiceInstanceSearchResults(String subscriberId, String instanceIdentifier, RoleValidator roleValidator, List<String> owningEntities, List<String> projects) {
271         List<List<ServiceInstanceSearchResult>> resultList = new ArrayList<>();
272         ServiceInstancesSearchResults serviceInstancesSearchResults = new ServiceInstancesSearchResults();
273
274         if (subscriberId != null || instanceIdentifier != null) {
275             resultList.add(getServicesBySubscriber(subscriberId, instanceIdentifier, roleValidator));
276         }
277         if (owningEntities != null) {
278             resultList.add(getServicesByOwningEntityId(owningEntities, roleValidator));
279         }
280         if (projects != null) {
281             resultList.add(getServicesByProjectNames(projects, roleValidator));
282         }
283         if (!resultList.isEmpty()) {
284             serviceInstancesSearchResults.serviceInstances = Intersection.of(resultList);
285         }
286
287         return new AaiResponse<>(serviceInstancesSearchResults, null, HttpStatus.SC_OK);
288     }
289
290
291     private List<ServiceInstanceSearchResult> getServicesBySubscriber(String subscriberId, String instanceIdentifier, RoleValidator roleValidator) {
292         AaiResponse<Services> subscriberResponse = aaiClient.getSubscriberData(subscriberId, false);
293         String subscriberGlobalId = subscriberResponse.getT().globalCustomerId;
294         String subscriberName = subscriberResponse.getT().subscriberName;
295         ServiceSubscriptions serviceSubscriptions = subscriberResponse.getT().serviceSubscriptions;
296
297         return getSearchResultsForSubscriptions(serviceSubscriptions, subscriberId, instanceIdentifier, roleValidator, subscriberGlobalId, subscriberName);
298
299     }
300
301
302     private ArrayList<ServiceInstanceSearchResult> getSearchResultsForSubscriptions(ServiceSubscriptions serviceSubscriptions, String subscriberId, String instanceIdentifier, RoleValidator roleValidator, String subscriberGlobalId, String subscriberName) {
303         ArrayList<ServiceInstanceSearchResult> results = new ArrayList<>();
304
305         if (serviceSubscriptions != null) {
306             for (ServiceSubscription serviceSubscription : serviceSubscriptions.serviceSubscription) {
307                 String serviceType = serviceSubscription.serviceType;
308                 serviceSubscription.isPermitted = roleValidator.isServicePermitted(subscriberGlobalId, serviceType);
309                 ArrayList<ServiceInstanceSearchResult> resultsForSubscription = getSearchResultsForSingleSubscription(serviceSubscription, subscriberId, instanceIdentifier, subscriberName, serviceType);
310                 results.addAll(resultsForSubscription);
311             }
312         }
313
314         return results;
315     }
316
317     private ArrayList<ServiceInstanceSearchResult> getSearchResultsForSingleSubscription(ServiceSubscription serviceSubscription, String subscriberId, String instanceIdentifier, String subscriberName, String serviceType) {
318         ArrayList<ServiceInstanceSearchResult> results = new ArrayList<>();
319
320         if (serviceSubscription.serviceInstances != null) {
321             for (ServiceInstance serviceInstance : serviceSubscription.serviceInstances.serviceInstance) {
322                 ServiceInstanceSearchResult serviceInstanceSearchResult =
323                         new ServiceInstanceSearchResult(serviceInstance.serviceInstanceId, subscriberId, serviceType, serviceInstance.serviceInstanceName,
324                                 subscriberName, serviceInstance.modelInvariantId, serviceInstance.modelVersionId, serviceSubscription.isPermitted);
325
326                 if ((instanceIdentifier == null) || (serviceInstanceMatchesIdentifier(instanceIdentifier, serviceInstance))){
327                     results.add(serviceInstanceSearchResult);
328                 }
329             }
330         }
331
332         return results;
333     }
334
335     private boolean serviceInstanceMatchesIdentifier(String instanceIdentifier, ServiceInstance serviceInstance) {
336         return instanceIdentifier.equals(serviceInstance.serviceInstanceId) || instanceIdentifier.equals(serviceInstance.serviceInstanceName);
337     }
338
339     @Override
340     public Response getVersionByInvariantId(List<String> modelInvariantId) {
341         try {
342             return aaiClient.getVersionByInvariantId(modelInvariantId);
343         } catch (Exception e) {
344             LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to getVersionByInvariantId from A&AI", e);
345         }
346         return null;
347     }
348
349     @Override
350     public AaiResponse<Pnf> getSpecificPnf(String pnfId) {
351         return aaiClient.getSpecificPnf(pnfId);
352     }
353
354     @Override
355     public AaiResponse getPNFData(String globalCustomerId, String serviceType, String modelVersionId, String modelInvariantId, String cloudRegion, String equipVendor, String equipModel) {
356         return aaiClient.getPNFData(globalCustomerId, serviceType, modelVersionId, modelInvariantId, cloudRegion, equipVendor, equipModel);
357     }
358
359
360
361     @Override
362     public AaiResponse getServices(RoleValidator roleValidator) {
363         AaiResponse<GetServicesAAIRespone> subscriberResponse = aaiClient.getServices();
364         if (subscriberResponse.getT() != null) {
365             for (org.onap.vid.aai.model.AaiGetServicesRequestModel.Service service : subscriberResponse.getT().service) {
366                 service.isPermitted = true;
367             }
368         }
369         return subscriberResponse;
370     }
371
372     @Override
373     public AaiResponse<GetTenantsResponse[]> getTenants(String globalCustomerId, String serviceType, RoleValidator roleValidator) {
374         AaiResponse<GetTenantsResponse[]> aaiGetTenantsResponse = aaiClient.getTenants(globalCustomerId, serviceType);
375         GetTenantsResponse[] tenants = aaiGetTenantsResponse.getT();
376         if (tenants != null) {
377             for (GetTenantsResponse tenant : tenants) {
378                 tenant.isPermitted = roleValidator.isTenantPermitted(globalCustomerId, serviceType, tenant.tenantName);
379             }
380         }
381         return aaiGetTenantsResponse;
382     }
383
384     @Override
385     public AaiResponse getVNFData(String globalSubscriberId, String serviceType, String serviceInstanceId) {
386         return aaiClient.getVNFData(globalSubscriberId, serviceType, serviceInstanceId);
387     }
388
389     @Override
390     public AaiResponse<AaiGetVnfResponse> getVNFData(String globalSubscriberId, String serviceType) {
391         AaiResponse<AaiGetVnfResponse> response = aaiClient.getVNFData(globalSubscriberId, serviceType);
392         return filterChangeManagementVNFCandidatesResponse(response);
393     }
394
395     protected AaiResponse<AaiGetVnfResponse> filterChangeManagementVNFCandidatesResponse(AaiResponse<AaiGetVnfResponse> response) {
396
397         if (response != null && response.getT() != null) {
398             List<VnfResult> filteredVnfs = response.getT().results.stream()
399                     .filter(result -> (
400                             result.nodeType.equalsIgnoreCase("generic-vnf") ||
401                                     result.nodeType.equalsIgnoreCase("service-instance")))
402                     .collect(Collectors.toList());
403
404             AaiGetVnfResponse aaiGetVnfResponse = new AaiGetVnfResponse();
405             aaiGetVnfResponse.results = filteredVnfs;
406             return new AaiResponse<>(aaiGetVnfResponse, response.getErrorMessage(), response.getHttpCode());
407         }
408
409         return new AaiResponse<>();
410     }
411
412     @Override
413     public AaiResponse getAaiZones() {
414         return aaiClient.getAllAicZones();
415     }
416
417     @Override
418     public AaiResponse getAicZoneForPnf(String globalCustomerId, String serviceType, String serviceId) {
419         String aicZone = "";
420
421         AaiResponse<ServiceRelationships> serviceInstanceResp = aaiClient.getServiceInstance(globalCustomerId, serviceType, serviceId);
422         if (serviceInstanceResp.getT() != null) {
423             List<String> aicZoneList = getRelationshipDataByType(serviceInstanceResp.getT().getRelationshipList(), "zone", "zone.zone-id");
424             if (!aicZoneList.isEmpty()) {
425                 aicZone = aicZoneList.get(0);
426             } else {
427                 LOGGER.warn("aic zone not found for service instance " + serviceId);
428             }
429         } else {
430             if (serviceInstanceResp.getErrorMessage() != null) {
431                 LOGGER.error("get service instance {} return error {}", serviceId, serviceInstanceResp.getErrorMessage());
432                 return new AaiResponse(aicZone , serviceInstanceResp.getErrorMessage() ,serviceInstanceResp.getHttpCode());
433             } else {
434                 LOGGER.warn("get service instance {} return empty body", serviceId);
435                 return new AaiResponse(aicZone , "get service instance " + serviceId + " return empty body" ,serviceInstanceResp.getHttpCode());
436             }
437         }
438
439         return new AaiResponse(aicZone , null ,HttpStatus.SC_OK);
440     }
441
442     @Override
443     public AaiResponse getNodeTemplateInstances(String globalCustomerId, String serviceType, String modelVersionId, String modelInvariantId, String cloudRegion) {
444         return aaiClient.getNodeTemplateInstances(globalCustomerId, serviceType, modelVersionId, modelInvariantId, cloudRegion);
445     }
446
447     @Override
448     public AaiResponse getNetworkCollectionDetails(String serviceInstanceId){
449         return aaiClient.getNetworkCollectionDetails(serviceInstanceId);
450     }
451
452     @Override
453     public AaiResponse<AaiGetInstanceGroupsByCloudRegion> getInstanceGroupsByCloudRegion(String cloudOwner, String cloudRegionId, String networkFunction){
454         return aaiClient.getInstanceGroupsByCloudRegion(cloudOwner, cloudRegionId, networkFunction);
455     }
456
457     @Override
458     public Collection<Service> getServicesByDistributionStatus() {
459         AaiResponse<GetServiceModelsByDistributionStatusResponse> serviceModelsByDistributionStatusResponse = aaiClient.getServiceModelsByDistributionStatus();
460         Collection<Service> services = new ArrayList<>();
461         if (serviceModelsByDistributionStatusResponse.getT() != null) {
462             List<Result> results = serviceModelsByDistributionStatusResponse.getT().getResults();
463             for (Result result : results) {
464                 if(result.getModel() != null) {
465                     List<Service> service = convertModelToService(result.getModel());
466                     services.addAll(service);
467                 }
468             }
469         }
470         return services;
471     }
472
473     @Override
474     public List<String> getServiceInstanceAssociatedPnfs(String globalCustomerId, String serviceType, String serviceInstanceId) {
475         List<String> pnfs = new ArrayList<>();
476
477         AaiResponse<ServiceRelationships> serviceInstanceResp = aaiClient.getServiceInstance(globalCustomerId, serviceType, serviceInstanceId);
478         if (serviceInstanceResp.getT() != null) {
479
480             addPnfsToListViaLogicalLinks(pnfs, serviceInstanceResp);
481             addPnfsToListViaDirectRelations(pnfs, serviceInstanceResp);
482
483             if (pnfs.isEmpty()) {
484                 LOGGER.warn("no pnf direct relation found for service id:" + serviceInstanceId+
485                         " name: "+serviceInstanceResp.getT().getServiceInstanceName());
486             }
487         } else {
488             if (serviceInstanceResp.getErrorMessage() != null) {
489                 LOGGER.error("get service instance {} return error {}", serviceInstanceId, serviceInstanceResp.getErrorMessage());
490             } else {
491                 LOGGER.warn("get service instance {} return empty body", serviceInstanceId);
492             }
493         }
494
495         return pnfs.stream().distinct().collect(Collectors.toList());
496     }
497
498     @Override
499     public AaiResponseTranslator.PortMirroringConfigData getPortMirroringConfigData(String configurationId) {
500         AaiResponse<JsonNode> aaiResponse = aaiClient.getCloudRegionAndSourceByPortMirroringConfigurationId(configurationId);
501         return aaiResponseTranslator.extractPortMirroringConfigData(aaiResponse);
502     }
503
504     @Override
505     public AaiResponse getInstanceGroupsByVnfInstanceId(String vnfInstanceId){
506         AaiResponse<AaiGetRelatedInstanceGroupsByVnfId> aaiResponse = aaiClient.getInstanceGroupsByVnfInstanceId(vnfInstanceId);
507         if(aaiResponse.getHttpCode() == HttpStatus.SC_OK){
508             return new AaiResponse<>(convertGetInstanceGroupsResponseToSimpleResponse(aaiResponse.getT()), aaiResponse.getErrorMessage(), aaiResponse.getHttpCode());
509         }
510         return aaiResponse;
511     }
512
513     @Override
514     public GetTenantsResponse getHomingDataByVfModule(String vnfInstanceId, String vfModuleId) {
515         return aaiClient.getHomingDataByVfModule(vnfInstanceId,vfModuleId);
516     }
517
518     @Override
519     public List<RelatedVnf> searchGroupMembers(String globalCustomerId, String serviceType, String invariantId, String groupType, String groupRole) {
520         String getURL = "business/customers/customer/" +
521                 globalCustomerId + "/service-subscriptions/service-subscription/" +
522                 serviceType + "/service-instances?model-invariant-id=" + invariantId;
523
524         Tree<AAIServiceTree.AaiRelationship> pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(NodeType.SERVICE_INSTANCE));
525         pathsToSearch.addPath(AAIServiceTree.toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.INSTANCE_GROUP));
526
527         //get all vnfs related to service-instances from the model-invariant-id
528         List<AAITreeNode> aaiTree = aaiServiceTree.buildAAITree(getURL, null, HttpMethod.GET, pathsToSearch, true);
529
530         //filter by instance-group-role & instance-group-type properties (from getAdditionalProperties)
531         //only vnfs has related instance-group with the same groupType & groupRole - are filtered out.
532         List<AAITreeNode> filteredVnfs = filterByInstanceGroupRoleAndType(aaiTree, groupRole, groupType);
533
534         //convert vnfs to expected result
535         List<RelatedVnf> convertedVnfs = filteredVnfs.stream()
536                 .map(RelatedVnf::from)
537                 .collect(Collectors.toList());
538
539         try {
540             return executorService.submit(() ->
541                     convertedVnfs.parallelStream()
542                             .map(this::enrichRelatedVnfWithCloudRegionAndTenant)
543                             .collect(Collectors.toList())
544             ).get();
545         } catch (Exception e) {
546             LOGGER.error(EELFLoggerDelegate.errorLogger, "Search group Members - Failed to enrich vnf with cloud region", e);
547             return convertedVnfs;
548         }
549     }
550
551     private List<AAITreeNode> filterByInstanceGroupRoleAndType(List<AAITreeNode> aaiTree, String groupRole, String groupType) {
552
553         return aaiTree.stream()
554                 .map(AAITreeNode::getChildren)
555                 .flatMap(Collection::stream)
556                 .filter(vnf -> isInstanceGroupsNotMatchRoleAndType(vnf.getChildren(), groupRole, groupType))
557                 .collect(Collectors.toList());
558     }
559
560     public boolean isInstanceGroupsNotMatchRoleAndType(List<AAITreeNode> instanceGroups, String groupRole, String groupType) {
561         return instanceGroups.stream()
562                 .map(AAITreeNode::getAdditionalProperties)
563                 .allMatch(props ->
564                         (!(groupRole.equals(props.get("instance-group-role")) &&
565                                 groupType.equals(props.get("instance-group-type"))))
566                 );
567     }
568
569     public RelatedVnf enrichRelatedVnfWithCloudRegionAndTenant(RelatedVnf vnf) {
570         Map<String, Properties> cloudRegionAndTenant = aaiClient.getCloudRegionAndTenantByVnfId(vnf.getInstanceId());
571
572         if (cloudRegionAndTenant.containsKey(TENANT_NODE_TYPE)) {
573             vnf.setTenantId(cloudRegionAndTenant.get(TENANT_NODE_TYPE).getTenantId());
574             vnf.setTenantName(cloudRegionAndTenant.get(TENANT_NODE_TYPE).getTenantName());
575         }
576
577         if (cloudRegionAndTenant.containsKey(CLOUD_REGION_NODE_TYPE)) {
578             vnf.setLcpCloudRegionId(cloudRegionAndTenant.get(CLOUD_REGION_NODE_TYPE).getCloudRegionId());
579         }
580
581         return vnf;
582     }
583
584     private List<InstanceGroupInfo> convertGetInstanceGroupsResponseToSimpleResponse(AaiGetRelatedInstanceGroupsByVnfId response) {
585         List<InstanceGroupInfo> instanceGroupInfoList = new ArrayList<>();
586         for(org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship: response.getRelationshipList().getRelationship()){
587             getInstanceGroupInfoFromRelationship(relationship, instanceGroupInfoList);
588         }
589         return instanceGroupInfoList;
590     }
591
592     private void getInstanceGroupInfoFromRelationship(org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.Relationship relationship, List<InstanceGroupInfo> instanceGroupInfoList) {
593         if(StringUtils.equals(relationship.getRelatedTo(),"instance-group")){
594             for(org.onap.vid.aai.model.AaiGetNetworkCollectionDetails.RelatedToProperty relatedToProperty: relationship.getRelatedToPropertyList()){
595                 if(StringUtils.equals(relatedToProperty.getKey(),"instance-group.instance-group-name")){
596                     instanceGroupInfoList.add(new InstanceGroupInfo(relatedToProperty.getValue()));
597                 }
598             }
599         }
600     }
601
602     @Override
603     public  List<PortDetailsTranslator.PortDetails> getPortMirroringSourcePorts(String configurationId){
604         return aaiClient.getPortMirroringSourcePorts(configurationId);
605     }
606
607     private void addPnfsToListViaDirectRelations(List<String> pnfs, AaiResponse<ServiceRelationships> serviceInstanceResp) {
608         pnfs.addAll(getRelationshipDataByType(serviceInstanceResp.getT().getRelationshipList(), "pnf", "pnf.pnf-name"));
609     }
610
611     private void addPnfsToListViaLogicalLinks(List<String> pnfs, AaiResponse<ServiceRelationships> serviceInstanceResp) {
612         List<String> logicalLinks = getRelationshipDataByType(serviceInstanceResp.getT().getRelationshipList(), "logical-link", "logical-link.link-name");
613         for (String logicalLink : logicalLinks) {
614             String link;
615             try {
616                 link = URLEncoder.encode(logicalLink, "UTF-8");
617             } catch (UnsupportedEncodingException e) {
618                 LOGGER.error("Failed to encode logical link: " + logicalLink, e);
619                 continue;
620             }
621
622             AaiResponse<LogicalLinkResponse> logicalLinkResp = aaiClient.getLogicalLink(link);
623             if (logicalLinkResp.getT() != null) {
624                 //lag-interface is the key for pnf - approved by Bracha
625                 List<String> linkPnfs = getRelationshipDataByType(logicalLinkResp.getT().getRelationshipList(), "lag-interface", "pnf.pnf-name");
626                 if (!linkPnfs.isEmpty()) {
627                     pnfs.addAll(linkPnfs);
628                 } else {
629                     LOGGER.warn("no pnf found for logical link " + logicalLink);
630                 }
631             } else {
632                 if (logicalLinkResp.getErrorMessage() != null) {
633                     LOGGER.error("get logical link " + logicalLink + " return error", logicalLinkResp.getErrorMessage());
634                 } else {
635                     LOGGER.warn("get logical link " + logicalLink + " return empty body");
636                 }
637             }
638         }
639     }
640
641     private List<String> getRelationshipDataByType(RelationshipList relationshipList, String relationshipType, String relationshipDataKey) {
642         List<String> relationshipValues = new ArrayList<>();
643         for (Relationship relationship : relationshipList.getRelationship()) {
644             if (relationship.getRelatedTo().equals(relationshipType)) {
645                 relationshipValues.addAll( relationship.getRelationDataList().stream()
646                         .filter(rel -> rel.getRelationshipKey().equals(relationshipDataKey))
647                         .map(RelationshipData::getRelationshipValue)
648                         .collect(Collectors.toList())
649                 );
650             }
651         }
652
653
654         return relationshipValues;
655     }
656
657     public String getAAIServiceTree(String globalCustomerId, String serviceType, String serviceInstanceId) {
658         String result;
659         try {
660             org.onap.vid.model.aaiTree.ServiceInstance tree = aaiServiceTree.getServiceInstanceTopology(globalCustomerId, serviceType, serviceInstanceId);
661             result = JACKSON_OBJECT_MAPPER.writeValueAsString(tree);
662         } catch (Exception e) {
663             throw new GenericUncheckedException(e);
664         }
665         return result;
666     }
667
668     @Override
669     public List<VpnBinding> getVpnListByVpnType(String vpnType) {
670         String path = "network/vpn-bindings?vpn-type=" + vpnType;
671
672         try {
673             List<AAITreeNode> aaiTree = aaiServiceTree.buildAAITreeForUniqueResource(path, NodeType.VPN_BINDING);
674             return aaiTree.stream().map(VpnBindingKt::from).collect(Collectors.toList());
675         } catch (ExceptionWithRequestInfo exception) {
676             if (Objects.equals(404, exception.getHttpCode())) {
677                 return Collections.emptyList();
678             }
679             throw exception;
680         }
681
682     }
683
684     @Override
685     public List<Network> getL3NetworksByCloudRegion(String cloudRegionId, String tenantId, String networkRole) {
686         String payload = buildPayloadForL3NetworksByCloudRegion(cloudRegionId, tenantId, networkRole);
687
688         try {
689             List<AAITreeNode> aaiTree = aaiServiceTree.buildAAITreeForUniqueResourceFromCustomQuery(QUERY_FORMAT_RESOURCE, payload, HttpMethod.PUT, NodeType.NETWORK);
690             return aaiTree.stream().map(Network::from).collect(Collectors.toList());
691         } catch (ExceptionWithRequestInfo exception) {
692             if (Objects.equals(404, exception.getHttpCode())) {
693                 return Collections.emptyList();
694             }
695             throw exception;
696         }
697     }
698
699     @NotNull
700     protected String buildPayloadForL3NetworksByCloudRegion(String cloudRegionId, String tenantId, String networkRole) {
701         String networkRolePart = StringUtils.isEmpty(networkRole) ? "" : "&networkRole=" + networkRole;
702         String cloudOwner = aaiClient.getCloudOwnerByCloudRegionId(cloudRegionId);
703         return "{\"start\":\"/cloud-infrastructure/cloud-regions/cloud-region/" + cloudOwner + "/" + cloudRegionId + "\"," +
704                 "\"query\":\"query/l3-networks-by-cloud-region?tenantId=" + tenantId + networkRolePart + "\"}";
705     }
706 }