upgrade some 3rd parties dependencies
[vid.git] / vid-app-common / src / main / java / org / onap / vid / services / AAIServiceTree.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.vid.services;
22
23 import static java.util.Comparator.comparing;
24 import static java.util.stream.Collectors.toSet;
25 import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
26 import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
27
28 import com.fasterxml.jackson.databind.JsonNode;
29 import com.google.common.collect.ImmutableList;
30 import java.util.Collection;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Objects;
35 import java.util.Set;
36 import java.util.concurrent.ConcurrentSkipListSet;
37 import java.util.concurrent.ExecutorService;
38 import java.util.stream.Collectors;
39 import java.util.stream.Stream;
40 import javax.inject.Inject;
41 import javax.ws.rs.core.Response;
42 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
43 import org.onap.vid.aai.AaiClientInterface;
44 import org.onap.vid.aai.util.AAITreeConverter;
45 import org.onap.vid.asdc.AsdcCatalogException;
46 import org.onap.vid.asdc.parser.ServiceModelInflator;
47 import org.onap.vid.exceptions.GenericUncheckedException;
48 import org.onap.vid.model.ServiceModel;
49 import org.onap.vid.model.aaiTree.AAITreeNode;
50 import org.onap.vid.model.aaiTree.NodeType;
51 import org.onap.vid.model.aaiTree.ServiceInstance;
52 import org.onap.vid.utils.Tree;
53 import org.springframework.http.HttpMethod;
54 import org.springframework.stereotype.Component;
55
56 @Component
57 public class AAIServiceTree {
58
59     private final AAITreeNodeBuilder aaiTreeNodeBuilder;
60
61     private final AAITreeConverter aaiTreeConverter;
62
63     private final AaiClientInterface aaiClient;
64
65     private final VidService sdcService;
66
67     private final ServiceModelInflator serviceModelInflator;
68
69     private final ExecutorService executorService;
70
71     private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AAIServiceTree.class);
72
73     public static final Tree<AaiRelationship> AAI_TREE_PATHS =
74             new Tree<>(new AaiRelationship(NodeType.SERVICE_INSTANCE));
75
76     static {
77         AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.VOLUME_GROUP));
78         AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.VF_MODULE));
79         AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.GENERIC_VNF, NodeType.NETWORK, NodeType.VPN_BINDING));
80         AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.NETWORK, NodeType.VPN_BINDING));
81         AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.INSTANCE_GROUP, NodeType.GENERIC_VNF));
82         AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.COLLECTION_RESOURCE, NodeType.INSTANCE_GROUP));
83         AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.CONFIGURATION, NodeType.NETWORK, NodeType.VPN_BINDING));
84         AAI_TREE_PATHS.addPath(toAaiRelationshipList(NodeType.CONFIGURATION, NodeType.VPN_BINDING));
85     }
86
87     public static List<AAIServiceTree.AaiRelationship> toAaiRelationshipList(NodeType... types) {
88         return Stream.of(types).map(AAIServiceTree.AaiRelationship::new).collect(Collectors.toList());
89     }
90
91     @Inject
92     public AAIServiceTree(AaiClientInterface aaiClient, AAITreeNodeBuilder aaiTreeNodeBuilder,
93                           AAITreeConverter aaiTreeConverter, VidService sdcService,
94                           ServiceModelInflator serviceModelInflator, ExecutorService executorService) {
95         this.aaiClient = aaiClient;
96         this.aaiTreeNodeBuilder = aaiTreeNodeBuilder;
97         this.aaiTreeConverter = aaiTreeConverter;
98         this.sdcService = sdcService;
99         this.serviceModelInflator = serviceModelInflator;
100         this.executorService = executorService;
101     }
102
103     List<AAITreeNode> buildAAITreeForUniqueResource(String getUrl, NodeType nodeType) {
104         return buildAAITreeForUniqueResourceFromCustomQuery(getUrl, null, HttpMethod.GET, nodeType);
105     }
106
107     List<AAITreeNode> buildAAITreeForUniqueResourceFromCustomQuery(String url, String payload, HttpMethod method, NodeType nodeType) {
108         Tree<AAIServiceTree.AaiRelationship> pathsToSearch = new Tree<>(new AAIServiceTree.AaiRelationship(nodeType));
109         return buildAAITree(url, payload, method, pathsToSearch, false);
110     }
111
112     public List<AAITreeNode> buildAAITree(String url, String payload, HttpMethod method, Tree<AaiRelationship> pathsToSearch, boolean enrichWithModelVersion) {
113
114         ConcurrentSkipListSet<AAITreeNode> nodesAccumulator = createNodesAccumulator();
115
116         List<AAITreeNode> aaiTreeNodes = fetchAAITree(url, payload, method, pathsToSearch, nodesAccumulator);
117
118         if (enrichWithModelVersion) {
119             enrichNodesWithModelVersionAndModelName(nodesAccumulator);
120         }
121
122         return aaiTreeNodes;
123     }
124
125     public ServiceInstance getServiceInstanceTopology(String globalCustomerId, String serviceType, String serviceInstanceId) {
126
127         String getURL = "business/customers/customer/" +
128                 globalCustomerId + "/service-subscriptions/service-subscription/" +
129                 serviceType + "/service-instances/service-instance/" + serviceInstanceId;
130
131         //Used later to get the nodes UUID
132         ConcurrentSkipListSet<AAITreeNode> nodesAccumulator = createNodesAccumulator();
133
134         AAITreeNode aaiTree = fetchAAITree(getURL, null, HttpMethod.GET, AAI_TREE_PATHS, nodesAccumulator).get(0);
135
136         //Populate nodes with model-name & model-version (from aai)
137         enrichNodesWithModelVersionAndModelName(nodesAccumulator);
138
139         final ServiceModel serviceModel = getServiceModel(aaiTree.getModelVersionId());
140
141         //Populate nodes with model-customization-name (from sdc model)
142         enrichNodesWithModelCustomizationName(nodesAccumulator, serviceModel);
143
144         return aaiTreeConverter.convertTreeToUIModel(aaiTree, globalCustomerId, serviceType, getInstantiationType(serviceModel), getInstanceRole(serviceModel), getInstanceType(serviceModel));
145     }
146
147     private String getInstanceType(ServiceModel serviceModel){
148         if (serviceModel != null && serviceModel.getService() != null) {
149             return serviceModel.getService().getServiceType();
150         }
151         return "";
152     }
153
154     private String getInstanceRole(ServiceModel serviceModel) {
155         if (serviceModel != null && serviceModel.getService() != null) {
156             return serviceModel.getService().getServiceRole();
157         }
158         return "";
159     }
160
161     private List<AAITreeNode> fetchAAITree(String url, String payload, HttpMethod method, Tree<AaiRelationship> pathsToSearch,
162                                            ConcurrentSkipListSet<AAITreeNode> nodesAccumulator) {
163         return aaiTreeNodeBuilder.buildNode(NodeType.fromString(pathsToSearch.getRootValue().type),
164                 url, payload, method, defaultIfNull(nodesAccumulator, createNodesAccumulator()),
165                 executorService, pathsToSearch);
166     }
167
168     private ConcurrentSkipListSet<AAITreeNode> createNodesAccumulator() {
169         return new ConcurrentSkipListSet<>(comparing(AAITreeNode::getUniqueNodeKey));
170     }
171
172     private String getInstantiationType(ServiceModel serviceModel) {
173         if (serviceModel.getService() != null && serviceModel.getService().getInstantiationType() != null) {
174             return serviceModel.getService().getInstantiationType();
175         } else {
176             return null;
177         }
178     }
179
180     private ServiceModel getServiceModel(String modelVersionId) {
181         try {
182             final ServiceModel serviceModel = sdcService.getService(modelVersionId);
183             if (serviceModel == null) {
184                 throw new GenericUncheckedException("Model version '" + modelVersionId + "' not found");
185             }
186             return serviceModel;
187         } catch (AsdcCatalogException e) {
188             throw new GenericUncheckedException("Exception while loading model version '" + modelVersionId + "'", e);
189         }
190
191     }
192
193     void enrichNodesWithModelCustomizationName(Collection<AAITreeNode> nodes, ServiceModel serviceModel) {
194         final Map<String, ServiceModelInflator.Names> customizationNameByVersionId = serviceModelInflator.toNamesByVersionId(serviceModel);
195
196         nodes.forEach(node -> {
197             final ServiceModelInflator.Names names = customizationNameByVersionId.get(node.getModelVersionId());
198             if (names != null) {
199                 node.setKeyInModel(names.getModelKey());
200                 node.setModelCustomizationName(names.getModelCustomizationName());
201             }
202         });
203     }
204
205
206     private void enrichNodesWithModelVersionAndModelName(Collection<AAITreeNode> nodes) {
207
208         Collection<String> invariantIDs = getModelInvariantIds(nodes);
209
210         Map<String, String> modelVersionByModelVersionId = new HashMap<>();
211         Map<String, String> modelNameByModelVersionId = new HashMap<>();
212
213         JsonNode models = getModels(aaiClient, invariantIDs);
214         if (models!=null) {
215             for (JsonNode model : models) {
216                 JsonNode modelVersions = model.get("model-vers").get("model-ver");
217                 for (JsonNode modelVersion : modelVersions) {
218                     final String modelVersionId = modelVersion.get("model-version-id").asText();
219                     modelVersionByModelVersionId.put(modelVersionId, modelVersion.get("model-version").asText());
220                     modelNameByModelVersionId.put(modelVersionId, modelVersion.get("model-name").asText());
221                 }
222             }
223         }
224
225         nodes.forEach(node -> {
226             node.setModelVersion(modelVersionByModelVersionId.get(node.getModelVersionId()));
227             node.setModelName(modelNameByModelVersionId.get(node.getModelVersionId()));
228         });
229
230     }
231
232     private JsonNode getModels(AaiClientInterface aaiClient, Collection<String> invariantIDs) {
233         Response response = aaiClient.getVersionByInvariantId(ImmutableList.copyOf(invariantIDs));
234         try {
235             JsonNode responseJson = JACKSON_OBJECT_MAPPER.readTree(response.readEntity(String.class));
236             return responseJson.get("model");
237         } catch (Exception e) {
238             LOGGER.error(EELFLoggerDelegate.errorLogger, "Failed to getVersionByInvariantId from A&AI", e);
239         }
240         return JACKSON_OBJECT_MAPPER.createObjectNode();
241     }
242
243     private Set<String> getModelInvariantIds(Collection<AAITreeNode> nodes) {
244         return nodes.stream()
245                 .map(AAITreeNode::getModelInvariantId)
246                 .filter(Objects::nonNull)
247                 .collect(toSet());
248     }
249
250     public static class AaiRelationship {
251
252         public final String type;
253
254         public AaiRelationship(String type) {
255             this.type = type;
256         }
257
258         public AaiRelationship(NodeType nodeType) {
259             this.type = nodeType.getType();
260         }
261
262         @Override
263         public boolean equals(Object o) {
264             if (this == o) return true;
265             if (!(o instanceof AaiRelationship)) return false;
266             AaiRelationship that = (AaiRelationship) o;
267             return Objects.equals(type, that.type);
268         }
269
270         @Override
271         public int hashCode() {
272             return Objects.hash(type);
273         }
274     }
275 }