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