6f514c03fe9cb143eca51cc43cbd6f3d93751633
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.tosca.services.impl;
18
19 import org.apache.commons.collections4.CollectionUtils;
20 import org.apache.commons.collections4.MapUtils;
21 import org.apache.commons.lang3.StringUtils;
22 import org.openecomp.core.utilities.CommonMethods;
23 import org.openecomp.sdc.common.errors.CoreException;
24 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
25 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
26 import org.openecomp.sdc.tosca.datatypes.model.AttributeDefinition;
27 import org.openecomp.sdc.tosca.datatypes.model.CapabilityDefinition;
28 import org.openecomp.sdc.tosca.datatypes.model.CapabilityType;
29 import org.openecomp.sdc.tosca.datatypes.model.DefinitionOfDataType;
30 import org.openecomp.sdc.tosca.datatypes.model.Import;
31 import org.openecomp.sdc.tosca.datatypes.model.InterfaceDefinitionType;
32 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
33 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
34 import org.openecomp.sdc.tosca.datatypes.model.ParameterDefinition;
35 import org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition;
36 import org.openecomp.sdc.tosca.datatypes.model.PropertyType;
37 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
38 import org.openecomp.sdc.tosca.datatypes.model.RequirementDefinition;
39 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
40 import org.openecomp.sdc.tosca.errors.ToscaElementTypeNotFoundErrorBuilder;
41 import org.openecomp.sdc.tosca.errors.ToscaInvalidEntryNotFoundErrorBuilder;
42 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder;
43 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstitutionServiceTemplateErrorBuilder;
44 import org.openecomp.sdc.tosca.services.DataModelUtil;
45 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
46 import org.openecomp.sdc.tosca.services.ToscaConstants;
47 import org.openecomp.sdc.tosca.services.ToscaExtensionYamlUtil;
48 import org.openecomp.sdc.tosca.services.ToscaUtil;
49
50 import java.lang.reflect.InvocationTargetException;
51 import java.util.ArrayList;
52 import java.util.Collection;
53 import java.util.Collections;
54 import java.util.HashMap;
55 import java.util.HashSet;
56 import java.util.List;
57 import java.util.Map;
58 import java.util.Objects;
59 import java.util.Optional;
60 import java.util.Set;
61
62 public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
63   private final String GET_NODE_TYPE_METHOD_NAME = "getNode_types";
64   private final String GET_DERIVED_FROM_METHOD_NAME = "getDerived_from";
65   private final String GET_TYPE_METHOD_NAME = "getType";
66   private final String GET_DATA_TYPE_METHOD_NAME = "getData_types";
67   private final String GET_INTERFACE_TYPE_METHOD_NAME = "getInterface_types";
68   private final String TOSCA_DOT = "tosca.";
69   private final String DOT_ROOT = ".Root";
70
71   @Override
72   public List<Map<String, RequirementDefinition>> calculateExposedRequirements(
73       List<Map<String, RequirementDefinition>> nodeTypeRequirementsDefinitionList,
74       Map<String, RequirementAssignment> nodeTemplateRequirementsAssignment) {
75
76     if (nodeTypeRequirementsDefinitionList == null) {
77       return Collections.emptyList();
78     }
79     for (Map.Entry<String, RequirementAssignment> entry : nodeTemplateRequirementsAssignment
80         .entrySet()) {
81       if (entry.getValue().getNode() != null) {
82         Optional<RequirementDefinition> requirementDefinition =
83             DataModelUtil.getRequirementDefinition(nodeTypeRequirementsDefinitionList, entry
84                 .getKey());
85         RequirementDefinition cloneRequirementDefinition;
86         if (requirementDefinition.isPresent()) {
87           cloneRequirementDefinition = requirementDefinition.get().clone();
88           updateRequirementDefinition(nodeTypeRequirementsDefinitionList, entry,
89               cloneRequirementDefinition);
90         }
91       } else {
92         for (Map<String, RequirementDefinition> nodeTypeRequirementsMap :
93             nodeTypeRequirementsDefinitionList) {
94           updateMinMaxOccurencesForNodeTypeRequirement(entry, nodeTypeRequirementsMap);
95         }
96       }
97     }
98     return nodeTypeRequirementsDefinitionList;
99   }
100
101   private void updateMinMaxOccurencesForNodeTypeRequirement(
102       Map.Entry<String, RequirementAssignment> entry,
103       Map<String, RequirementDefinition> nodeTypeRequirementsMap) {
104     Object max = nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences() != null
105         && nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences().length > 0
106         ? nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences()[1] : 1;
107     Object min = nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences() != null
108         && nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences().length > 0
109         ? nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences()[0] : 1;
110     nodeTypeRequirementsMap.get(entry.getKey()).setOccurrences(new Object[]{min, max});
111   }
112
113   private void updateRequirementDefinition(
114       List<Map<String, RequirementDefinition>> nodeTypeRequirementsDefinitionList,
115       Map.Entry<String, RequirementAssignment> entry,
116       RequirementDefinition cloneRequirementDefinition) {
117     if (!evaluateRequirementFulfillment(cloneRequirementDefinition)) {
118       CommonMethods.mergeEntryInList(entry.getKey(), cloneRequirementDefinition,
119           nodeTypeRequirementsDefinitionList);
120     } else {
121       DataModelUtil.removeRequirementsDefinition(nodeTypeRequirementsDefinitionList, entry
122           .getKey());
123     }
124   }
125
126   private static boolean evaluateRequirementFulfillment(RequirementDefinition
127                                                             requirementDefinition) {
128     Object[] occurrences = requirementDefinition.getOccurrences();
129     if (occurrences == null) {
130       requirementDefinition.setOccurrences(new Object[]{1, 1});
131       return false;
132     }
133     if (occurrences[1].equals(ToscaConstants.UNBOUNDED)) {
134       return false;
135     }
136
137     if (occurrences[1].equals(1)) {
138       return true;
139     }
140     occurrences[1] = (Integer) occurrences[1] - 1;
141     return false;
142   }
143
144   @Override
145   public Map<String, CapabilityDefinition> calculateExposedCapabilities(
146       Map<String, CapabilityDefinition> nodeTypeCapabilitiesDefinition,
147       Map<String, Map<String, RequirementAssignment>> fullFilledRequirementsDefinitionMap) {
148
149     String capabilityKey;
150     String capability;
151     String node;
152     for (Map.Entry<String, Map<String, RequirementAssignment>> entry :
153         fullFilledRequirementsDefinitionMap.entrySet()) {
154       for (Map.Entry<String, RequirementAssignment> fullFilledEntry : entry.getValue().entrySet()) {
155
156         capability = fullFilledEntry.getValue().getCapability();
157         node = fullFilledEntry.getValue().getNode();
158         capabilityKey = capability + "_" + node;
159         CapabilityDefinition capabilityDefinition = nodeTypeCapabilitiesDefinition.get(
160             capabilityKey);
161         if (capabilityDefinition != null) {
162           CapabilityDefinition clonedCapabilityDefinition = capabilityDefinition.clone();
163           nodeTypeCapabilitiesDefinition.put(capabilityKey, capabilityDefinition.clone());
164           updateNodeTypeCapabilitiesDefinition(nodeTypeCapabilitiesDefinition, capabilityKey,
165               clonedCapabilityDefinition);
166         }
167       }
168     }
169
170     Map<String, CapabilityDefinition> exposedCapabilitiesDefinition = new HashMap<>();
171     for (Map.Entry<String, CapabilityDefinition> entry : nodeTypeCapabilitiesDefinition
172         .entrySet()) {
173       exposedCapabilitiesDefinition.put(entry.getKey(), entry.getValue());
174     }
175     return exposedCapabilitiesDefinition;
176   }
177
178   private void updateNodeTypeCapabilitiesDefinition(
179       Map<String, CapabilityDefinition> nodeTypeCapabilitiesDefinition, String capabilityKey,
180       CapabilityDefinition clonedCapabilityDefinition) {
181     if (evaluateCapabilityFulfillment(clonedCapabilityDefinition)) {
182       nodeTypeCapabilitiesDefinition.remove(capabilityKey);
183     } else {
184       nodeTypeCapabilitiesDefinition.put(capabilityKey, clonedCapabilityDefinition);
185     }
186   }
187
188   private static boolean evaluateCapabilityFulfillment(CapabilityDefinition capabilityDefinition) {
189
190     Object[] occurrences = capabilityDefinition.getOccurrences();
191     if (occurrences == null) {
192       capabilityDefinition.setOccurrences(new Object[]{1, ToscaConstants.UNBOUNDED});
193       return false;
194     }
195     if (occurrences[1].equals(ToscaConstants.UNBOUNDED)) {
196       return false;
197     }
198
199     if (occurrences[1].equals(1)) {
200       return true;
201     }
202     occurrences[1] = (Integer) occurrences[1] - 1;
203     return false;
204   }
205
206   /*
207     node template with type equal to node type or derived from node type
208      */
209   @Override
210   public Map<String, NodeTemplate> getNodeTemplatesByType(ServiceTemplate serviceTemplate,
211                                                           String nodeType,
212                                                           ToscaServiceModel toscaServiceModel) {
213     Map<String, NodeTemplate> nodeTemplates = new HashMap<>();
214
215     if (Objects.nonNull(serviceTemplate.getTopology_template())
216         && MapUtils.isNotEmpty(serviceTemplate.getTopology_template().getNode_templates())) {
217       for (Map.Entry<String, NodeTemplate> nodeTemplateEntry : serviceTemplate
218           .getTopology_template().getNode_templates().entrySet()) {
219         if (isTypeOf(nodeTemplateEntry.getValue(), nodeType, serviceTemplate, toscaServiceModel)) {
220           nodeTemplates.put(nodeTemplateEntry.getKey(), nodeTemplateEntry.getValue());
221         }
222
223       }
224     }
225     return nodeTemplates;
226   }
227
228   @Override
229   public Optional<NodeType> fetchNodeType(String nodeTypeKey, Collection<ServiceTemplate>
230       serviceTemplates) {
231     Optional<Map<String, NodeType>> nodeTypeMap = serviceTemplates.stream()
232         .map(ServiceTemplate::getNode_types)
233         .filter(nodeTypes -> Objects.nonNull(nodeTypes) && nodeTypes.containsKey(nodeTypeKey))
234         .findFirst();
235     return nodeTypeMap.map(stringNodeTypeMap -> stringNodeTypeMap.get(nodeTypeKey));
236   }
237
238   @Override
239   public boolean isTypeOf(NodeTemplate nodeTemplate, String nodeType,
240                           ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
241     return isTypeOf(nodeTemplate, nodeType, GET_NODE_TYPE_METHOD_NAME, serviceTemplate,
242         toscaServiceModel);
243   }
244
245   @Override
246   public List<RequirementAssignment> getRequirements(NodeTemplate nodeTemplate,
247                                                      String requirementId) {
248     List<RequirementAssignment> requirements = new ArrayList<>();
249     List<Map<String, RequirementAssignment>> requirementList = nodeTemplate.getRequirements();
250     if (requirementList != null) {
251       requirementList.stream().filter(reqMap -> reqMap.get(requirementId) != null)
252           .forEach(reqMap -> {
253             ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
254             RequirementAssignment reqAssignment = toscaExtensionYamlUtil
255                 .yamlToObject(toscaExtensionYamlUtil.objectToYaml(reqMap.get(requirementId)),
256                     RequirementAssignment.class);
257             requirements.add(reqAssignment);
258           });
259     }
260     return requirements;
261   }
262
263   @Override
264   public Optional<NodeTemplate> getNodeTemplateById(ServiceTemplate serviceTemplate,
265                                                     String nodeTemplateId) {
266     if ((serviceTemplate.getTopology_template() != null)
267         && (serviceTemplate.getTopology_template().getNode_templates() != null)
268         && (serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId)
269         != null)) {
270       return Optional
271           .of(serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId));
272     }
273     return Optional.empty();
274   }
275
276   @Override
277   public Optional<String> getSubstituteServiceTemplateName(String substituteNodeTemplateId,
278                                                            NodeTemplate substitutableNodeTemplate) {
279     if (!isSubstitutableNodeTemplate(substitutableNodeTemplate)) {
280       return Optional.empty();
281     }
282
283     if (substitutableNodeTemplate.getProperties() != null
284         && substitutableNodeTemplate.getProperties()
285         .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME) != null) {
286       Object serviceTemplateFilter = substitutableNodeTemplate.getProperties()
287           .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
288       if (serviceTemplateFilter != null && serviceTemplateFilter instanceof Map) {
289         Object substituteServiceTemplate = ((Map) serviceTemplateFilter)
290             .get(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME);
291         handleNoSubstituteServiceTemplate(substituteNodeTemplateId, substituteServiceTemplate);
292         return Optional.of(substituteServiceTemplate.toString());
293       }
294     }
295     throw new CoreException(
296         new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId)
297             .build());
298   }
299
300   private void handleNoSubstituteServiceTemplate(String substituteNodeTemplateId,
301                                                  Object substituteServiceTemplate) {
302     if (substituteServiceTemplate == null) {
303       throw new CoreException(
304           new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId)
305               .build());
306     }
307   }
308
309   @Override
310   public Map<String, NodeTemplate> getSubstitutableNodeTemplates(ServiceTemplate serviceTemplate) {
311     Map<String, NodeTemplate> substitutableNodeTemplates = new HashMap<>();
312
313     if (serviceTemplate == null
314         || serviceTemplate.getTopology_template() == null
315         || serviceTemplate.getTopology_template().getNode_templates() == null) {
316       return substitutableNodeTemplates;
317     }
318
319     Map<String, NodeTemplate> nodeTemplates =
320         serviceTemplate.getTopology_template().getNode_templates();
321     for (Map.Entry<String, NodeTemplate> entry : nodeTemplates.entrySet()) {
322       String nodeTemplateId = entry.getKey();
323       NodeTemplate nodeTemplate = entry.getValue();
324       if (isSubstitutableNodeTemplate(nodeTemplate)) {
325         substitutableNodeTemplates.put(nodeTemplateId, nodeTemplate);
326       }
327     }
328
329     return substitutableNodeTemplates;
330   }
331
332   @Override
333   public Optional<Map.Entry<String, NodeTemplate>> getSubstitutionMappedNodeTemplateByExposedReq(
334       String substituteServiceTemplateFileName, ServiceTemplate substituteServiceTemplate,
335       String requirementId) {
336     if (isSubstitutionServiceTemplate(substituteServiceTemplateFileName,
337         substituteServiceTemplate)) {
338       Map<String, List<String>> substitutionMappingRequirements =
339           substituteServiceTemplate.getTopology_template().getSubstitution_mappings()
340               .getRequirements();
341       if (substitutionMappingRequirements != null) {
342         List<String> requirementMapping = substitutionMappingRequirements.get(requirementId);
343         if (requirementMapping != null && !requirementMapping.isEmpty()) {
344           String mappedNodeTemplateId = requirementMapping.get(0);
345           Optional<NodeTemplate> mappedNodeTemplate =
346               getNodeTemplateById(substituteServiceTemplate, mappedNodeTemplateId);
347           mappedNodeTemplate.orElseThrow(() -> new CoreException(
348               new ToscaInvalidEntryNotFoundErrorBuilder("Node Template", mappedNodeTemplateId)
349                   .build()));
350           Map.Entry<String, NodeTemplate> mappedNodeTemplateEntry =
351               new Map.Entry<String, NodeTemplate>() {
352                 @Override
353                 public String getKey() {
354                   return mappedNodeTemplateId;
355                 }
356
357                 @Override
358                 public NodeTemplate getValue() {
359                   return mappedNodeTemplate.get();
360                 }
361
362                 @Override
363                 public NodeTemplate setValue(NodeTemplate value) {
364                   return null;
365                 }
366               };
367           return Optional.of(mappedNodeTemplateEntry);
368         }
369       }
370     }
371     return Optional.empty();
372   }
373
374   /*
375   match only for the input which is not null
376    */
377   @Override
378   public boolean isDesiredRequirementAssignment(RequirementAssignment requirementAssignment,
379                                                 String capability, String node,
380                                                 String relationship) {
381     if (isSameCapability(requirementAssignment, capability)) {
382       return false;
383     }
384
385     if (isSameRequirement(requirementAssignment, node)) {
386       return false;
387     }
388
389     if (isSameRelationship(requirementAssignment, relationship)) {
390       return false;
391     }
392
393     return !(capability == null && node == null && relationship == null);
394
395   }
396
397   private boolean isSameRelationship(RequirementAssignment requirementAssignment,
398                                      String relationship) {
399     return relationship != null && (requirementAssignment.getRelationship() == null
400         || !requirementAssignment.getRelationship().equals(relationship));
401   }
402
403   private boolean isSameRequirement(RequirementAssignment requirementAssignment, String node) {
404     return node != null && (requirementAssignment.getNode() == null
405         || !requirementAssignment.getNode().equals(node));
406   }
407
408   private boolean isSameCapability(RequirementAssignment requirementAssignment, String capability) {
409     return capability != null && (requirementAssignment.getCapability() == null
410         || !requirementAssignment.getCapability().equals(capability));
411   }
412
413   @Override
414   public Object getFlatEntity(ToscaElementTypes elementType, String typeId,
415                               ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel) {
416     Object returnEntity;
417
418     switch (elementType) {
419       case CAPABILITY_TYPE:
420         returnEntity = new CapabilityType();
421         break;
422       case NODE_TYPE:
423         returnEntity = new NodeType();
424         break;
425       default:
426         throw new RuntimeException(
427             "Entity[" + elementType + "] id[" + typeId + "] flat not supported");
428     }
429
430     scanAnFlatEntity(elementType, typeId, returnEntity, serviceTemplate, toscaModel,
431         new ArrayList<>(), 0);
432
433
434     return returnEntity;
435   }
436
437   @Override
438   public boolean isSubstitutableNodeTemplate(NodeTemplate nodeTemplate) {
439     return nodeTemplate.getDirectives() != null
440         && nodeTemplate.getDirectives().contains(ToscaConstants
441         .NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
442   }
443
444   private <T> Optional<Boolean> isTypeExistInServiceTemplateHierarchy(String typeToMatch,
445                                                                       String typeToSearch,
446                                                                       String getTypesMethodName,
447                                                                       ServiceTemplate serviceTemplate,
448                                                                       ToscaServiceModel toscaServiceModel,
449                                                                       Set<String> analyzedImportFiles)
450       throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
451     Map<String, T> searchableTypes =
452         (Map<String, T>) serviceTemplate.getClass().getMethod(getTypesMethodName)
453             .invoke(serviceTemplate);
454
455     if (!MapUtils.isEmpty(searchableTypes)) {
456       T typeObject = searchableTypes.get(typeToSearch);
457       if (Objects.nonNull(typeObject)) {
458         String derivedFromTypeVal =
459             (String) typeObject.getClass().getMethod(GET_DERIVED_FROM_METHOD_NAME).invoke(typeObject);
460         if (Objects.equals(derivedFromTypeVal, typeToMatch)) {
461           return Optional.of(true);
462         } else if (Objects.isNull(derivedFromTypeVal) || isTypeIsToscaRoot(derivedFromTypeVal)) {
463           return Optional.of(false);
464         } else {
465           return isTypeExistInServiceTemplateHierarchy(typeToMatch,
466               derivedFromTypeVal, getTypesMethodName, serviceTemplate, toscaServiceModel, null);
467         }
468       } else {
469         return isTypeExistInImports(typeToMatch, typeToSearch, getTypesMethodName,
470             serviceTemplate, toscaServiceModel, analyzedImportFiles);
471       }
472     }
473     return isTypeExistInImports(typeToMatch, typeToSearch, getTypesMethodName, serviceTemplate,
474         toscaServiceModel, analyzedImportFiles);
475   }
476
477   private Optional<Boolean> isTypeExistInImports(String typeToMatch,
478                                                  String typeToSearch,
479                                                  String getTypesMethodName,
480                                                  ServiceTemplate serviceTemplate,
481                                                  ToscaServiceModel toscaServiceModel,
482                                                  Set<String> filesScanned)
483       throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
484     List<Map<String, Import>> imports = serviceTemplate.getImports();
485     if (CollectionUtils.isEmpty(imports)) {
486       return Optional.empty();
487     }
488
489     Set<String> createdFilesScanned = createFilesScannedSet(filesScanned);
490
491     for (Map<String, Import> map : imports) {
492       ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
493       Import anImport = toscaExtensionYamlUtil
494           .yamlToObject(toscaExtensionYamlUtil.objectToYaml(map.values().iterator().next()),
495               Import.class);
496       handleImportWithNoFileEntry(anImport);
497       String importFile = anImport.getFile();
498       ServiceTemplate template =
499           toscaServiceModel.getServiceTemplates().get(fetchFileNameForImport(importFile,
500               serviceTemplate.getMetadata() == null ? null
501                   : serviceTemplate.getMetadata().get("filename")));
502       if (Objects.isNull(template)
503           || createdFilesScanned.contains(ToscaUtil.getServiceTemplateFileName(template))) {
504         continue;
505       } else {
506         createdFilesScanned.add(ToscaUtil.getServiceTemplateFileName(template));
507       }
508       Optional<Boolean> typeExistInServiceTemplateHierarchy =
509           isTypeExistInServiceTemplateHierarchy(typeToMatch, typeToSearch, getTypesMethodName,
510               template, toscaServiceModel, createdFilesScanned);
511       if (typeExistInServiceTemplateHierarchy.isPresent()
512           && (typeExistInServiceTemplateHierarchy.get())) {
513         createdFilesScanned.clear();
514         return Optional.of(true);
515       }
516
517     }
518     return Optional.of(false);
519   }
520
521   private void handleImportWithNoFileEntry(Import anImport) {
522     if (Objects.isNull(anImport) || Objects.isNull(anImport.getFile())) {
523       throw new RuntimeException("import without file entry");
524     }
525   }
526
527   private Set<String> createFilesScannedSet(Set<String> filesScanned) {
528     Set<String> retFileScanned = filesScanned;
529     if (Objects.isNull(retFileScanned)) {
530       retFileScanned = new HashSet<>();
531     }
532     return retFileScanned;
533   }
534
535   private boolean isTypeIsToscaRoot(String type) {
536     return (type.contains(TOSCA_DOT) && type.contains(DOT_ROOT));
537   }
538
539   private boolean isSubstitutionServiceTemplate(String substituteServiceTemplateFileName,
540                                                 ServiceTemplate substituteServiceTemplate) {
541     if (substituteServiceTemplate != null
542         && substituteServiceTemplate.getTopology_template() != null
543         && substituteServiceTemplate.getTopology_template().getSubstitution_mappings() != null) {
544       if (substituteServiceTemplate.getTopology_template().getSubstitution_mappings()
545           .getNode_type() == null) {
546         throw new CoreException(new ToscaInvalidSubstitutionServiceTemplateErrorBuilder(
547             substituteServiceTemplateFileName).build());
548       }
549       return true;
550     }
551     return false;
552
553   }
554
555   private boolean scanAnFlatEntity(ToscaElementTypes elementType, String typeId, Object entity,
556                                    ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel,
557                                    List<String> filesScanned, int rootScanStartInx) {
558
559
560     boolean entityFound = enrichEntityFromCurrentServiceTemplate(elementType, typeId, entity,
561         serviceTemplate, toscaModel, filesScanned, rootScanStartInx);
562     if (!entityFound) {
563       List<Map<String, Import>> imports = serviceTemplate.getImports();
564       if (CollectionUtils.isEmpty(imports)) {
565         return false;
566       }
567       boolean found = false;
568       for (Map<String, Import> importMap : imports) {
569         if (found) {
570           return true;
571         }
572         found = isFlatEntity(importMap, entity, serviceTemplate, filesScanned,
573             toscaModel, elementType, typeId);
574       }
575       return found;
576     }
577     return true;
578   }
579
580   private boolean isFlatEntity(Map<String, Import> importMap,
581                                Object entity,
582                                ServiceTemplate serviceTemplate,
583                                List<String> filesScanned,
584                                ToscaServiceModel toscaModel,
585                                ToscaElementTypes elementType, String typeId) {
586     boolean found = false;
587     ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
588     for (Object importObject : importMap.values()) {
589       Import importServiceTemplate = toscaExtensionYamlUtil
590           .yamlToObject(toscaExtensionYamlUtil.objectToYaml(importObject), Import.class);
591       String fileName = fetchFileNameForImport(importServiceTemplate.getFile(),
592           serviceTemplate.getMetadata() == null ? null : serviceTemplate.getMetadata().get(
593               "filename"));
594       if (filesScanned.contains(fileName)) {
595         return false;
596       } else {
597         filesScanned.add(fileName);
598       }
599       ServiceTemplate template = toscaModel.getServiceTemplates().get(fileName);
600       found = scanAnFlatEntity(elementType, typeId, entity, template, toscaModel,
601           filesScanned, filesScanned.size());
602     }
603     return found;
604   }
605
606   private String fetchFileNameForImport(String importServiceTemplateFile,
607                                         String currentMetadatafileName) {
608     if (importServiceTemplateFile.contains("../")) {
609       return importServiceTemplateFile.replace("../", "");
610     } else if (currentMetadatafileName != null) {
611       return currentMetadatafileName.substring(0, currentMetadatafileName.indexOf('/')) + "/"
612           + importServiceTemplateFile;
613     } else {
614       return importServiceTemplateFile;
615     }
616
617   }
618
619   private boolean enrichEntityFromCurrentServiceTemplate(ToscaElementTypes elementType,
620                                                          String typeId, Object entity,
621                                                          ServiceTemplate serviceTemplate,
622                                                          ToscaServiceModel toscaModel,
623                                                          List<String> filesScanned,
624                                                          int rootScanStartInx) {
625     switch (elementType) {
626       case CAPABILITY_TYPE:
627         if (enrichCapabilityType(elementType, typeId, entity, serviceTemplate, toscaModel,
628             filesScanned, rootScanStartInx)) {
629           return false;
630         }
631         break;
632       case NODE_TYPE:
633         if (enrichNodeTypeInfo(elementType, typeId, entity, serviceTemplate, toscaModel,
634             filesScanned, rootScanStartInx)) {
635           return false;
636         }
637         break;
638       default:
639         throw new RuntimeException(
640             "Entity[" + elementType + "] id[" + typeId + "] flat not supported");
641     }
642
643     return true;
644
645
646   }
647
648   private boolean enrichNodeTypeInfo(ToscaElementTypes elementType, String typeId, Object entity,
649                                      ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel,
650                                      List<String> filesScanned, int rootScanStartInx) {
651     String derivedFrom;
652     if (serviceTemplate.getNode_types() != null
653         && serviceTemplate.getNode_types().containsKey(typeId)) {
654
655       filesScanned.clear();
656       NodeType targetNodeType = (NodeType) entity;
657       NodeType sourceNodeType = serviceTemplate.getNode_types().get(typeId);
658       derivedFrom = sourceNodeType.getDerived_from();
659       if (derivedFrom != null) {
660         scanAnFlatEntity(elementType, derivedFrom, entity, serviceTemplate, toscaModel,
661             filesScanned, rootScanStartInx);
662       }
663       combineNodeTypeInfo(sourceNodeType, targetNodeType);
664     } else {
665       return true;
666     }
667     return false;
668   }
669
670   private boolean enrichCapabilityType(ToscaElementTypes elementType, String typeId, Object entity,
671                                        ServiceTemplate serviceTemplate,
672                                        ToscaServiceModel toscaModel, List<String> filesScanned,
673                                        int rootScanStartInx) {
674     String derivedFrom;
675     if (serviceTemplate.getCapability_types() != null
676         && serviceTemplate.getCapability_types().containsKey(typeId)) {
677
678       filesScanned.clear();
679       CapabilityType targetCapabilityType = (CapabilityType) entity;
680       CapabilityType sourceCapabilityType = serviceTemplate.getCapability_types().get(typeId);
681       derivedFrom = sourceCapabilityType.getDerived_from();
682       if (derivedFrom != null) {
683         scanAnFlatEntity(elementType, derivedFrom, entity, serviceTemplate, toscaModel,
684             filesScanned, rootScanStartInx);
685       }
686       combineCapabilityTypeInfo(sourceCapabilityType, targetCapabilityType);
687     } else {
688       return true;
689     }
690     return false;
691   }
692
693   private void combineNodeTypeInfo(NodeType sourceNodeType, NodeType targetNodeType) {
694     targetNodeType.setDerived_from(sourceNodeType.getDerived_from());
695     targetNodeType.setDescription(sourceNodeType.getDescription());
696     targetNodeType.setVersion(sourceNodeType.getVersion());
697     targetNodeType.setProperties(
698         CommonMethods.mergeMaps(targetNodeType.getProperties(), sourceNodeType.getProperties()));
699     targetNodeType.setInterfaces(
700         CommonMethods.mergeMaps(targetNodeType.getInterfaces(), sourceNodeType.getInterfaces()));
701     targetNodeType.setArtifacts(
702         CommonMethods.mergeMaps(targetNodeType.getArtifacts(), sourceNodeType.getArtifacts()));
703     targetNodeType.setAttributes(
704         CommonMethods.mergeMaps(targetNodeType.getAttributes(), sourceNodeType.getAttributes()));
705     targetNodeType.setCapabilities(CommonMethods
706         .mergeMaps(targetNodeType.getCapabilities(), sourceNodeType.getCapabilities()));
707     targetNodeType.setRequirements(CommonMethods
708         .mergeListsOfMap(targetNodeType.getRequirements(), sourceNodeType.getRequirements()));
709
710   }
711
712
713   private void combineCapabilityTypeInfo(CapabilityType sourceCapabilityType,
714                                          CapabilityType targetCapabilityType) {
715
716     targetCapabilityType.setAttributes(CommonMethods
717         .mergeMaps(targetCapabilityType.getAttributes(), sourceCapabilityType.getAttributes()));
718     targetCapabilityType.setProperties(CommonMethods
719         .mergeMaps(targetCapabilityType.getProperties(), sourceCapabilityType.getProperties()));
720     targetCapabilityType.setValid_source_types(CommonMethods
721         .mergeLists(targetCapabilityType.getValid_source_types(),
722             sourceCapabilityType.getValid_source_types()));
723
724     if (StringUtils.isNotEmpty(sourceCapabilityType.getDerived_from())) {
725       targetCapabilityType.setDerived_from(sourceCapabilityType.getDerived_from());
726     }
727     if (StringUtils.isNotEmpty(sourceCapabilityType.getDescription())) {
728       targetCapabilityType.setDescription(sourceCapabilityType.getDescription());
729     }
730     if (StringUtils.isNotEmpty(sourceCapabilityType.getVersion())) {
731       targetCapabilityType.setVersion(sourceCapabilityType.getVersion());
732     }
733
734
735   }
736
737
738   /*
739  * Create node type according to the input substitution service template, while the substitution
740  * service template can be mappted to this node type, for substitution mapping.
741  *
742  * @param substitutionServiceTemplate  substitution serivce template
743  * @param nodeTypeDerivedFromValue derived from value for the created node type
744  * @return the node type
745  */
746   @Override
747   public NodeType createInitSubstitutionNodeType(ServiceTemplate substitutionServiceTemplate,
748                                                  String nodeTypeDerivedFromValue) {
749     NodeType substitutionNodeType = new NodeType();
750     substitutionNodeType.setDerived_from(nodeTypeDerivedFromValue);
751     substitutionNodeType.setDescription(substitutionServiceTemplate.getDescription());
752     substitutionNodeType
753         .setProperties(manageSubstitutionNodeTypeProperties(substitutionServiceTemplate));
754     substitutionNodeType
755         .setAttributes(manageSubstitutionNodeTypeAttributes(substitutionServiceTemplate));
756     return substitutionNodeType;
757   }
758
759   @Override
760   public Map<String, PropertyDefinition> manageSubstitutionNodeTypeProperties(
761       ServiceTemplate substitutionServiceTemplate) {
762     Map<String, PropertyDefinition> substitutionNodeTypeProperties = new HashMap<>();
763     Map<String, ParameterDefinition> properties =
764         substitutionServiceTemplate.getTopology_template().getInputs();
765     if (properties == null) {
766       return null;
767     }
768
769     PropertyDefinition propertyDefinition;
770     String toscaPropertyName;
771     for (Map.Entry<String, ParameterDefinition> entry : properties.entrySet()) {
772       toscaPropertyName = entry.getKey();
773       propertyDefinition = new PropertyDefinition();
774       ParameterDefinition parameterDefinition =
775           substitutionServiceTemplate.getTopology_template().getInputs().get(toscaPropertyName);
776       propertyDefinition.setType(parameterDefinition.getType());
777       propertyDefinition.setDescription(parameterDefinition.getDescription());
778       propertyDefinition.set_default(parameterDefinition.get_default());
779       if (parameterDefinition.getRequired() != null) {
780         propertyDefinition.setRequired(parameterDefinition.getRequired());
781       }
782       if (propertyDefinition.get_default() != null) {
783         propertyDefinition.setRequired(false);
784       }
785       if (!CollectionUtils.isEmpty(parameterDefinition.getConstraints())) {
786         propertyDefinition.setConstraints(parameterDefinition.getConstraints());
787       }
788       propertyDefinition.setEntry_schema(parameterDefinition.getEntry_schema());
789       if (parameterDefinition.getStatus() != null) {
790         propertyDefinition.setStatus(parameterDefinition.getStatus());
791       }
792       substitutionNodeTypeProperties.put(toscaPropertyName, propertyDefinition);
793     }
794     return substitutionNodeTypeProperties;
795   }
796
797
798   private Map<String, AttributeDefinition> manageSubstitutionNodeTypeAttributes(
799       ServiceTemplate substitutionServiceTemplate) {
800     Map<String, AttributeDefinition> substitutionNodeTypeAttributes = new HashMap<>();
801     Map<String, ParameterDefinition> attributes =
802         substitutionServiceTemplate.getTopology_template().getOutputs();
803     if (attributes == null) {
804       return null;
805     }
806     AttributeDefinition attributeDefinition;
807     String toscaAttributeName;
808
809     for (Map.Entry<String, ParameterDefinition> entry : attributes.entrySet()) {
810       attributeDefinition = new AttributeDefinition();
811       toscaAttributeName = entry.getKey();
812       ParameterDefinition parameterDefinition =
813           substitutionServiceTemplate.getTopology_template().getOutputs().get(toscaAttributeName);
814       if (parameterDefinition.getType() != null && !parameterDefinition.getType().isEmpty()) {
815         attributeDefinition.setType(parameterDefinition.getType());
816       } else {
817         attributeDefinition.setType(PropertyType.STRING.getDisplayName());
818       }
819       attributeDefinition.setDescription(parameterDefinition.getDescription());
820       attributeDefinition.set_default(parameterDefinition.get_default());
821       attributeDefinition.setEntry_schema(parameterDefinition.getEntry_schema());
822       if (Objects.nonNull(parameterDefinition.getStatus())) {
823         attributeDefinition.setStatus(parameterDefinition.getStatus());
824       }
825       substitutionNodeTypeAttributes.put(toscaAttributeName, attributeDefinition);
826     }
827     return substitutionNodeTypeAttributes;
828   }
829
830   /**
831    * Checks if the requirement exists in the node template.
832    *
833    * @param nodeTemplate          the node template
834    * @param requirementId         the requirement id
835    * @param requirementAssignment the requirement assignment
836    * @return true if the requirement already exists and false otherwise
837    */
838   @Override
839   public boolean isRequirementExistInNodeTemplate(NodeTemplate nodeTemplate,
840                                                   String requirementId,
841                                                   RequirementAssignment requirementAssignment) {
842     List<Map<String, RequirementAssignment>> nodeTemplateRequirements = nodeTemplate
843         .getRequirements();
844     return nodeTemplateRequirements != null && nodeTemplateRequirements.stream().anyMatch(
845         requirement -> requirement.containsKey(requirementId) && DataModelUtil
846             .compareRequirementAssignment(requirementAssignment, requirement.get(requirementId)));
847   }
848
849   @Override
850   public boolean isTypeOf(InterfaceDefinitionType interfaceDefinition, String interfaceType,
851                           ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
852     return isTypeOf(interfaceDefinition, interfaceType, GET_INTERFACE_TYPE_METHOD_NAME, serviceTemplate,
853         toscaServiceModel);
854   }
855
856   @Override
857   public boolean isTypeOf(DefinitionOfDataType parameterDefinition, String dataType,
858                           ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
859     return isTypeOf(parameterDefinition, dataType, GET_DATA_TYPE_METHOD_NAME, serviceTemplate,
860         toscaServiceModel);
861   }
862
863   private <T> boolean isTypeOf(T object, String type, String getTypesMethodName,
864                                ServiceTemplate serviceTemplate,
865                                ToscaServiceModel toscaServiceModel) {
866     if (object == null) {
867       return false;
868     }
869
870     try {
871       String objectType = (String) object.getClass().getMethod(GET_TYPE_METHOD_NAME).invoke(object);
872       if (Objects.equals(objectType, type)) {
873         return true;
874       }
875
876       Optional<Boolean> typeExistInServiceTemplateHierarchy =
877           isTypeExistInServiceTemplateHierarchy(type, objectType, getTypesMethodName,
878               serviceTemplate, toscaServiceModel, null);
879       return typeExistInServiceTemplateHierarchy.orElseThrow(() -> new CoreException(
880           new ToscaElementTypeNotFoundErrorBuilder(objectType).build()));
881
882     } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
883       throw new RuntimeException(e);
884     }
885   }
886
887
888 }