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