2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.tosca.services.impl;
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.apache.commons.collections4.MapUtils;
25 import org.openecomp.core.utilities.CommonMethods;
26 import org.openecomp.sdc.common.errors.CoreException;
27 import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
28 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
29 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
30 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
31 import org.openecomp.sdc.tosca.datatypes.model.CapabilityType;
32 import org.openecomp.sdc.tosca.datatypes.model.Import;
33 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
34 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
35 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
36 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
37 import org.openecomp.sdc.tosca.errors.ToscaInvalidEntryNotFoundErrorBuilder;
38 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder;
39 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstitutionServiceTemplateErrorBuilder;
40 import org.openecomp.sdc.tosca.errors.ToscaNodeTypeNotFoundErrorBuilder;
41 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
42 import org.openecomp.sdc.tosca.services.ToscaConstants;
43 import org.openecomp.sdc.tosca.services.yamlutil.ToscaExtensionYamlUtil;
45 import java.util.ArrayList;
46 import java.util.HashMap;
47 import java.util.HashSet;
48 import java.util.List;
50 import java.util.Objects;
51 import java.util.Optional;
54 public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
56 node template with type equal to node type or derived from node type.
59 public Map<String, NodeTemplate> getNodeTemplatesByType(ServiceTemplate serviceTemplate,
61 ToscaServiceModel toscaServiceModel) {
62 Map<String, NodeTemplate> nodeTemplates = new HashMap<>();
64 if (Objects.nonNull(serviceTemplate.getTopology_template())
65 && MapUtils.isNotEmpty(serviceTemplate.getTopology_template().getNode_templates())) {
66 for (Map.Entry<String, NodeTemplate> nodeTemplateEntry : serviceTemplate
67 .getTopology_template().getNode_templates().entrySet()) {
68 if (isTypeOf(nodeTemplateEntry.getValue(), nodeType, serviceTemplate, toscaServiceModel)) {
69 nodeTemplates.put(nodeTemplateEntry.getKey(), nodeTemplateEntry.getValue());
78 public boolean isTypeOf(NodeTemplate nodeTemplate, String nodeType,
79 ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
80 if (nodeTemplate == null) {
84 if (isNodeTemplateOfTypeNodeType(nodeTemplate, nodeType)) {
88 Optional<Boolean> nodeTypeExistInServiceTemplateHierarchy =
89 isNodeTypeExistInServiceTemplateHierarchy(nodeType, nodeTemplate.getType(), serviceTemplate,
90 toscaServiceModel, null);
91 return nodeTypeExistInServiceTemplateHierarchy.orElseThrow(() -> new CoreException(
92 new ToscaNodeTypeNotFoundErrorBuilder(nodeTemplate.getType()).build()));
96 private Optional<Boolean> isNodeTypeExistInServiceTemplateHierarchy(String nodeTypeToMatch,
97 String nodeTypeToSearch,
98 ServiceTemplate serviceTemplate,
99 ToscaServiceModel toscaServiceModel,
100 Set<String> analyzedImportFiles) {
101 Map<String, NodeType> searchableNodeTypes = serviceTemplate.getNode_types();
102 if (!MapUtils.isEmpty(searchableNodeTypes)) {
103 NodeType nodeType = searchableNodeTypes.get(nodeTypeToSearch);
104 if (Objects.nonNull(nodeType)) {
105 if (Objects.equals(nodeType.getDerived_from(), nodeTypeToMatch)) {
106 return Optional.of(true);
107 } else if (isNodeTypeIsToscaRoot(nodeType)) {
108 return Optional.of(false);
110 return isNodeTypeExistInServiceTemplateHierarchy(nodeTypeToMatch,
111 nodeType.getDerived_from(), serviceTemplate, toscaServiceModel, null);
114 return isNodeTypeExistInImports(nodeTypeToMatch, nodeTypeToSearch, serviceTemplate,
115 toscaServiceModel, analyzedImportFiles);
118 return isNodeTypeExistInImports(nodeTypeToMatch, nodeTypeToSearch, serviceTemplate,
119 toscaServiceModel, analyzedImportFiles);
123 private Optional<Boolean> isNodeTypeExistInImports(String nodeTypeToMatch,
124 String nodeTypeToSearch,
125 ServiceTemplate serviceTemplate,
126 ToscaServiceModel toscaServiceModel,
127 Set<String> analyzedImportFiles) {
128 Map<String, Import> imports = serviceTemplate.getImports();
129 if (imports == null) {
130 return Optional.empty();
133 analyzedImportFiles = createAnalyzedImportFilesSet(analyzedImportFiles);
134 for (Import anImport : imports.values()) {
135 if (Objects.isNull(anImport) || Objects.isNull(anImport.getFile())) {
136 throw new RuntimeException("import without file entry");
138 String importFile = anImport.getFile();
139 if (analyzedImportFiles.contains(importFile)) {
142 addImportFileToAnalyzedImportFilesSet(analyzedImportFiles, importFile);
143 ServiceTemplate template = toscaServiceModel.getServiceTemplates().get(importFile);
144 Optional<Boolean> nodeTypeExistInServiceTemplateHierarchy =
145 isNodeTypeExistInServiceTemplateHierarchy(nodeTypeToMatch, nodeTypeToSearch, template,
146 toscaServiceModel, analyzedImportFiles);
147 if (nodeTypeExistInServiceTemplateHierarchy.isPresent()) {
148 if (nodeTypeExistInServiceTemplateHierarchy.get()) {
149 return Optional.of(true);
153 return Optional.of(false);
156 private Set<String> addImportFileToAnalyzedImportFilesSet(Set<String> analyzedImportFiles,
158 analyzedImportFiles.add(importFile);
159 return analyzedImportFiles;
162 private Set<String> createAnalyzedImportFilesSet(Set<String> analyzedImportFiles) {
163 if (Objects.isNull(analyzedImportFiles)) {
164 analyzedImportFiles = new HashSet<>();
166 return analyzedImportFiles;
169 private boolean isNodeTypeIsToscaRoot(NodeType stNodeType) {
170 return Objects.equals(stNodeType.getDerived_from(), ToscaNodeType.ROOT.getDisplayName());
173 private boolean isNodeTemplateOfTypeNodeType(NodeTemplate nodeTemplate, String nodeType) {
174 return Objects.equals(nodeTemplate.getType(), nodeType);
178 public List<RequirementAssignment> getRequirements(NodeTemplate nodeTemplate,
179 String requirementId) {
180 List<RequirementAssignment> requirements = new ArrayList<>();
181 List<Map<String, RequirementAssignment>> requirementList = nodeTemplate.getRequirements();
182 if (requirementList != null) {
183 requirementList.stream().filter(reqMap -> reqMap.get(requirementId) != null)
185 ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
186 RequirementAssignment reqAssignment = toscaExtensionYamlUtil
187 .yamlToObject(toscaExtensionYamlUtil.objectToYaml(reqMap.get(requirementId)),
188 RequirementAssignment.class);
189 requirements.add(reqAssignment);
196 public Optional<NodeTemplate> getNodeTemplateById(ServiceTemplate serviceTemplate,
197 String nodeTemplateId) {
198 if ((serviceTemplate.getTopology_template() != null)
199 && (serviceTemplate.getTopology_template().getNode_templates() != null)
200 && (serviceTemplate.getTopology_template().getNode_templates()
201 .get(nodeTemplateId) != null)) {
203 .of(serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId));
205 return Optional.empty();
209 public Optional<String> getSubstituteServiceTemplateName(String substituteNodeTemplateId,
210 NodeTemplate substitutableNodeTemplate) {
211 if (!isSubstitutableNodeTemplate(substitutableNodeTemplate)) {
212 return Optional.empty();
215 if (substitutableNodeTemplate.getProperties() != null
216 && substitutableNodeTemplate.getProperties()
217 .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME) != null) {
218 Object serviceTemplateFilter = substitutableNodeTemplate.getProperties()
219 .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
220 if (serviceTemplateFilter != null && serviceTemplateFilter instanceof Map) {
221 Object substituteServiceTemplate = ((Map) serviceTemplateFilter)
222 .get(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME);
223 if (substituteServiceTemplate == null) {
224 throw new CoreException(
225 new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId)
228 return Optional.of(substituteServiceTemplate.toString());
231 throw new CoreException(
232 new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId)
237 public Map<String, NodeTemplate> getSubstitutableNodeTemplates(ServiceTemplate serviceTemplate) {
238 Map<String, NodeTemplate> substitutableNodeTemplates = new HashMap<>();
240 if (serviceTemplate == null
241 || serviceTemplate.getTopology_template() == null
242 || serviceTemplate.getTopology_template().getNode_templates() == null) {
243 return substitutableNodeTemplates;
246 Map<String, NodeTemplate> nodeTemplates =
247 serviceTemplate.getTopology_template().getNode_templates();
248 for (String nodeTemplateId : nodeTemplates.keySet()) {
249 NodeTemplate nodeTemplate = nodeTemplates.get(nodeTemplateId);
250 if (isSubstitutableNodeTemplate(nodeTemplate)) {
251 substitutableNodeTemplates.put(nodeTemplateId, nodeTemplate);
255 return substitutableNodeTemplates;
258 private boolean isSubstitutableNodeTemplate(NodeTemplate nodeTemplate) {
259 return nodeTemplate.getDirectives() != null
260 && nodeTemplate.getDirectives().contains(ToscaConstants
261 .NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
264 private boolean isSubstitutionServiceTemplate(String substituteServiceTemplateFileName,
265 ServiceTemplate substituteServiceTemplate) {
266 if (substituteServiceTemplate != null
267 && substituteServiceTemplate.getTopology_template() != null
268 && substituteServiceTemplate.getTopology_template().getSubstitution_mappings() != null) {
269 if (substituteServiceTemplate.getTopology_template().getSubstitution_mappings()
270 .getNode_type() == null) {
271 throw new CoreException(new ToscaInvalidSubstitutionServiceTemplateErrorBuilder(
272 substituteServiceTemplateFileName).build());
281 public Optional<Map.Entry<String, NodeTemplate>> getSubstitutionMappedNodeTemplateByExposedReq(
282 String substituteServiceTemplateFileName, ServiceTemplate substituteServiceTemplate,
283 String requirementId) {
284 if (isSubstitutionServiceTemplate(substituteServiceTemplateFileName,
285 substituteServiceTemplate)) {
286 Map<String, List<String>> substitutionMappingRequirements =
287 substituteServiceTemplate.getTopology_template().getSubstitution_mappings()
289 if (substitutionMappingRequirements != null) {
290 List<String> requirementMapping = substitutionMappingRequirements.get(requirementId);
291 if (requirementMapping != null && !requirementMapping.isEmpty()) {
292 String mappedNodeTemplateId = requirementMapping.get(0);
293 Optional<NodeTemplate> mappedNodeTemplate =
294 getNodeTemplateById(substituteServiceTemplate, mappedNodeTemplateId);
295 mappedNodeTemplate.orElseThrow(() -> new CoreException(
296 new ToscaInvalidEntryNotFoundErrorBuilder("Node Template", mappedNodeTemplateId)
298 Map.Entry<String, NodeTemplate> mappedNodeTemplateEntry =
299 new Map.Entry<String, NodeTemplate>() {
301 public String getKey() {
302 return mappedNodeTemplateId;
306 public NodeTemplate getValue() {
307 return mappedNodeTemplate.get();
311 public NodeTemplate setValue(NodeTemplate value) {
315 return Optional.of(mappedNodeTemplateEntry);
319 return Optional.empty();
324 match only for the input which is not null
327 public boolean isDesiredRequirementAssignment(RequirementAssignment requirementAssignment,
328 String capability, String node,
329 String relationship) {
330 if (capability != null) {
331 if (requirementAssignment.getCapability() == null
332 || !requirementAssignment.getCapability().equals(capability)) {
338 if (requirementAssignment.getNode() == null
339 || !requirementAssignment.getNode().equals(node)) {
344 if (relationship != null) {
345 if (requirementAssignment.getRelationship() == null
346 || !requirementAssignment.getRelationship().equals(relationship)) {
351 return !(capability == null && node == null && relationship == null);
356 public Object getFlatEntity(ToscaElementTypes elementType, String typeId,
357 ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel) {
360 switch (elementType) {
361 case CAPABILITY_TYPE:
362 returnEntity = new CapabilityType();
365 throw new RuntimeException(
366 "Entity[" + elementType + "] id[" + typeId + "] flat not supported");
369 scanAnFlatEntity(elementType, typeId, returnEntity, serviceTemplate, toscaModel);
375 private void scanAnFlatEntity(ToscaElementTypes elementType, String typeId, Object entity,
376 ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel) {
379 boolean entityFound =
380 enrichEntityFromCurrentServiceTemplate(elementType, typeId, entity, serviceTemplate,
383 Map<String, Import> imports = serviceTemplate.getImports();
384 if (MapUtils.isEmpty(imports)) {
387 for (Import importServiceTemplate : imports.values()) {
388 ServiceTemplate template =
389 toscaModel.getServiceTemplates().get(importServiceTemplate.getFile());
390 scanAnFlatEntity(elementType, typeId, entity, template, toscaModel);
397 private boolean enrichEntityFromCurrentServiceTemplate(ToscaElementTypes elementType,
398 String typeId, Object entity,
399 ServiceTemplate serviceTemplate,
400 ToscaServiceModel toscaModel) {
402 switch (elementType) {
403 case CAPABILITY_TYPE:
404 if (serviceTemplate.getCapability_types() != null
405 && serviceTemplate.getCapability_types().containsKey(typeId)) {
407 CapabilityType targetCapabilityType = ((CapabilityType) entity);
408 CapabilityType sourceCapabilityType = serviceTemplate.getCapability_types().get(typeId);
409 derivedFrom = sourceCapabilityType.getDerived_from();
410 if (derivedFrom != null
411 && !ToscaCapabilityType.NFV_METRIC.getDisplayName().equals(derivedFrom)) {
412 scanAnFlatEntity(elementType, derivedFrom, entity, serviceTemplate, toscaModel);
414 combineCapabilityTypeInfo(sourceCapabilityType, targetCapabilityType);
420 throw new RuntimeException(
421 "Entity[" + elementType + "] id[" + typeId + "] flat not supported");
429 private void combineCapabilityTypeInfo(CapabilityType sourceCapabilityType,
430 CapabilityType targetCapabilityType) {
431 if (MapUtils.isNotEmpty(sourceCapabilityType.getAttributes())) {
432 if (targetCapabilityType.getAttributes() == null) {
433 targetCapabilityType.setAttributes(new HashMap<>());
435 targetCapabilityType.getAttributes().putAll(sourceCapabilityType.getAttributes());
438 if (MapUtils.isNotEmpty(sourceCapabilityType.getProperties())) {
439 if (targetCapabilityType.getProperties() == null) {
440 targetCapabilityType.setProperties(new HashMap<>());
442 targetCapabilityType.getProperties().putAll(sourceCapabilityType.getProperties());
445 if (CollectionUtils.isNotEmpty(sourceCapabilityType.getValid_source_types())) {
446 if (targetCapabilityType.getValid_source_types() == null) {
447 targetCapabilityType.setValid_source_types(new ArrayList<>());
449 targetCapabilityType.getValid_source_types()
450 .addAll(sourceCapabilityType.getValid_source_types());
453 if (CommonMethods.isEmpty(sourceCapabilityType.getDerived_from())) {
454 targetCapabilityType.setDerived_from(sourceCapabilityType.getDerived_from());
456 if (CommonMethods.isEmpty(sourceCapabilityType.getDescription())) {
457 targetCapabilityType.setDescription(sourceCapabilityType.getDescription());
459 if (CommonMethods.isEmpty(sourceCapabilityType.getVersion())) {
460 targetCapabilityType.setVersion(sourceCapabilityType.getVersion());