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.vendorsoftwareproduct.services.impl.composition;
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.apache.commons.collections4.MapUtils;
25 import org.openecomp.core.utilities.json.JsonSchemaDataGenerator;
26 import org.openecomp.core.utilities.json.JsonUtil;
27 import org.openecomp.sdc.common.errors.CoreException;
28 import org.openecomp.sdc.common.errors.ErrorCategory;
29 import org.openecomp.sdc.common.errors.ErrorCode;
30 import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
31 import org.openecomp.sdc.vendorsoftwareproduct.dao.ComponentDao;
32 import org.openecomp.sdc.vendorsoftwareproduct.dao.NetworkDao;
33 import org.openecomp.sdc.vendorsoftwareproduct.dao.NicDao;
34 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDao;
35 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentEntity;
36 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.CompositionEntity;
37 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NetworkEntity;
38 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NicEntity;
39 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
40 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspQuestionnaireEntity;
41 import org.openecomp.sdc.vendorsoftwareproduct.services.composition.CompositionEntityDataManager;
42 import org.openecomp.sdc.vendorsoftwareproduct.services.schemagenerator.SchemaGenerator;
43 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Component;
44 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComponentData;
45 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionData;
46 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityId;
47 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityType;
48 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityValidationData;
49 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Network;
50 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Nic;
51 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateContext;
52 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateInput;
53 import org.openecomp.sdc.versioning.dao.types.Version;
55 import java.util.ArrayList;
56 import java.util.Collection;
57 import java.util.HashMap;
58 import java.util.HashSet;
59 import java.util.List;
61 import java.util.Objects;
64 public class CompositionEntityDataManagerImpl implements CompositionEntityDataManager {
66 private static final String COMPOSITION_ENTITY_DATA_MANAGER_ERR =
67 "COMPOSITION_ENTITY_DATA_MANAGER_ERR";
68 private static final String COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG =
69 "Invalid input: %s may not be null";
71 private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
73 private Map<CompositionEntityId, CompositionEntityData> entities = new HashMap<>();
74 private Map<CompositionEntityType, String> nonDynamicSchemas = new HashMap<>();
75 private List<CompositionEntityValidationData> roots = new ArrayList<>();
77 private VendorSoftwareProductInfoDao vspInfoDao;
78 private ComponentDao componentDao;
79 private NicDao nicDao;
80 private NetworkDao networkDao;
82 public CompositionEntityDataManagerImpl(VendorSoftwareProductInfoDao vspInfoDao,
83 ComponentDao componentDao,
84 NicDao nicDao, NetworkDao networkDao) {
85 this.vspInfoDao = vspInfoDao;
86 this.componentDao = componentDao;
88 this.networkDao = networkDao;
92 * Validate entity composition entity validation data.
94 * @param entity the entity
95 * @param schemaTemplateContext the schema template context
96 * @param schemaTemplateInput the schema template input
97 * @return the composition entity validation data
100 public CompositionEntityValidationData validateEntity(CompositionEntity entity,
101 SchemaTemplateContext schemaTemplateContext,
102 SchemaTemplateInput schemaTemplateInput) {
103 mdcDataDebugMessage.debugEntryMessage(null);
105 if (entity == null) {
106 throw new CoreException(
107 new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
108 .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
109 String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "composition entity"))
112 if (schemaTemplateContext == null) {
113 throw new CoreException(
114 new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
115 .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
116 String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "schema template context"))
120 CompositionEntityValidationData validationData =
121 new CompositionEntityValidationData(entity.getType(), entity.getId());
123 schemaTemplateContext == SchemaTemplateContext.composition ? entity.getCompositionData()
124 : entity.getQuestionnaireData();
125 validationData.setErrors(JsonUtil.validate(
126 json == null ? JsonUtil.object2Json(new Object()) : json,
127 generateSchema(schemaTemplateContext, entity.getType(), schemaTemplateInput)));
129 mdcDataDebugMessage.debugExitMessage(null);
130 return validationData;
136 * @param entity the entity
137 * @param schemaTemplateInput the schema template input
140 public void addEntity(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
141 if (entity == null) {
142 throw new CoreException(
143 new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
144 .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
145 String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "composition entity"))
148 entities.put(entity.getCompositionEntityId(),
149 new CompositionEntityData(entity, schemaTemplateInput));
153 * Validate entities questionnaire map.
158 public Map<CompositionEntityId, Collection<String>> validateEntitiesQuestionnaire() {
159 mdcDataDebugMessage.debugEntryMessage(null);
161 Map<CompositionEntityId, Collection<String>> errorsByEntityId = new HashMap<>();
162 entities.entrySet().forEach(entry -> {
163 Collection<String> errors = validateQuestionnaire(entry.getValue());
164 if (errors != null) {
165 errorsByEntityId.put(entry.getKey(), errors);
169 mdcDataDebugMessage.debugExitMessage(null);
170 return errorsByEntityId;
177 public void buildTrees() {
178 Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData =
180 entities.entrySet().forEach(
181 entry -> addValidationDataEntity(entitiesValidationData, entry.getKey(),
182 entry.getValue().entity));
185 public Collection<CompositionEntityValidationData> getTrees() {
190 public void saveCompositionData(String vspId, Version version, CompositionData compositionData) {
191 mdcDataDebugMessage.debugEntryMessage(null);
193 if (Objects.isNull(compositionData)) {
197 Map<String, String> networkIdByName = saveNetworks(vspId, version, compositionData);
198 saveComponents(vspId, version, compositionData, networkIdByName);
200 mdcDataDebugMessage.debugExitMessage(null);
204 public Set<CompositionEntityValidationData> getAllErrorsByVsp(String vspId) {
205 CompositionEntityValidationData matchVsp = null;
206 Set<CompositionEntityValidationData> entitiesWithErrors = new HashSet<>();
207 for (CompositionEntityValidationData root : roots) {
208 if (root.getEntityId().equals(vspId)) {
214 getEntityListWithErrors(matchVsp, entitiesWithErrors);
215 if (CollectionUtils.isNotEmpty(entitiesWithErrors)) {
216 updateValidationCompositionEntityName(entitiesWithErrors);
217 return entitiesWithErrors;
223 private boolean isThereErrorsInSubTree(CompositionEntityValidationData entity) {
224 if (Objects.isNull(entity)) {
228 if (CollectionUtils.isNotEmpty(entity.getErrors())) {
232 Collection<CompositionEntityValidationData> subEntitiesValidationData =
233 entity.getSubEntitiesValidationData();
234 return !CollectionUtils.isEmpty(subEntitiesValidationData) &&
235 checkForErrorsInChildren(subEntitiesValidationData);
239 private boolean checkForErrorsInChildren(
240 Collection<CompositionEntityValidationData> subEntitiesValidationData) {
241 boolean result = false;
242 for (CompositionEntityValidationData subEntity : subEntitiesValidationData) {
243 if (CollectionUtils.isNotEmpty(subEntity.getErrors())) {
247 result = result || isThereErrorsInSubTree(subEntity);
255 public void saveComponents(String vspId, Version version, CompositionData compositionData,
256 Map<String, String> networkIdByName) {
259 mdcDataDebugMessage.debugEntryMessage(null);
261 if (CollectionUtils.isNotEmpty(compositionData.getComponents())) {
262 for (Component component : compositionData.getComponents()) {
263 ComponentEntity componentEntity = new ComponentEntity(vspId, version, null);
264 componentEntity.setComponentCompositionData(component.getData());
266 String componentId = createComponent(componentEntity).getId();
268 saveNicsByComponent(vspId, version, networkIdByName, component, componentId);
272 mdcDataDebugMessage.debugExitMessage(null);
275 public void saveNicsByComponent(String vspId, Version version,
276 Map<String, String> networkIdByName, Component component,
277 String componentId) {
278 if (CollectionUtils.isNotEmpty(component.getNics())) {
279 for (Nic nic : component.getNics()) {
280 if (nic.getNetworkName() != null && MapUtils.isNotEmpty(networkIdByName)) {
281 nic.setNetworkId(networkIdByName.get(nic.getNetworkName()));
283 nic.setNetworkName(null);
285 NicEntity nicEntity = new NicEntity(vspId, version, componentId, null);
286 nicEntity.setNicCompositionData(nic);
287 createNic(nicEntity);
292 public Map<String, String> saveNetworks(String vspId, Version version,
293 CompositionData compositionData) {
294 mdcDataDebugMessage.debugEntryMessage(null);
296 Map<String, String> networkIdByName = new HashMap<>();
297 if (CollectionUtils.isNotEmpty(compositionData.getNetworks())) {
298 for (Network network : compositionData.getNetworks()) {
300 NetworkEntity networkEntity = new NetworkEntity(vspId, version, null);
301 networkEntity.setNetworkCompositionData(network);
303 if (network.getName() != null) {
304 networkIdByName.put(network.getName(), createNetwork(networkEntity).getId());
309 mdcDataDebugMessage.debugExitMessage(null);
310 return networkIdByName;
314 public NetworkEntity createNetwork(NetworkEntity network) {
315 mdcDataDebugMessage.debugEntryMessage(null);
317 //network.setId(CommonMethods.nextUuId()); will be set by the dao
318 networkDao.create(network);
319 mdcDataDebugMessage.debugExitMessage(null);
324 public ComponentEntity createComponent(ComponentEntity component) {
325 mdcDataDebugMessage.debugEntryMessage(null);
327 //component.setId(CommonMethods.nextUuId()); will be set by the dao
328 component.setQuestionnaireData(
329 new JsonSchemaDataGenerator(
330 generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.component,
334 componentDao.create(component);
336 mdcDataDebugMessage.debugExitMessage(null);
341 public NicEntity createNic(NicEntity nic) {
342 mdcDataDebugMessage.debugEntryMessage(null);
344 //nic.setId(CommonMethods.nextUuId()); will be set by the dao
345 nic.setQuestionnaireData(
346 new JsonSchemaDataGenerator(
347 generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.nic, null))
352 mdcDataDebugMessage.debugExitMessage(null);
357 public void addErrorsToTrees(Map<CompositionEntityId, Collection<String>> errors) {
358 roots.forEach(root -> addErrorsToTree(root, null, errors));
362 * get a flat list of all questionnaire entities that have validation errors
364 public Set<CompositionEntityValidationData> getEntityListWithErrors() {
365 mdcDataDebugMessage.debugEntryMessage(null);
366 Set<CompositionEntityValidationData> treeAsList = new HashSet<>();
368 for (CompositionEntityValidationData entity : roots) {
369 if (CollectionUtils.isNotEmpty(entity.getErrors())) {
370 addNodeWithErrors(entity, treeAsList);
372 getEntityListWithErrors(entity, treeAsList);
375 updateValidationCompositionEntityName(treeAsList);
377 mdcDataDebugMessage.debugExitMessage(null);
381 public void getEntityListWithErrors(CompositionEntityValidationData entity,
382 Set<CompositionEntityValidationData> compositionSet) {
383 Collection<CompositionEntityValidationData> childNodes =
384 entity.getSubEntitiesValidationData();
386 if (CollectionUtils.isEmpty(childNodes)) {
390 for (CompositionEntityValidationData child : childNodes) {
391 if (CollectionUtils.isNotEmpty(child.getErrors())) {
392 addNodeWithErrors(child, compositionSet);
394 getEntityListWithErrors(child, compositionSet);
399 public void addNodeWithErrors(CompositionEntityValidationData node,
400 Set<CompositionEntityValidationData> entitiesWithErrors) {
401 CompositionEntityValidationData compositionNodeToAdd = new CompositionEntityValidationData(node
402 .getEntityType(), node.getEntityId());
403 compositionNodeToAdd.setErrors(node.getErrors());
404 compositionNodeToAdd.setSubEntitiesValidationData(null);
406 entitiesWithErrors.add(compositionNodeToAdd);
409 public void removeNodesWithoutErrors() {
410 roots.forEach(root -> removeNodesWithoutErrors(root, null));
414 private CompositionEntityData getCompositionEntityDataById(CompositionEntityValidationData
416 for (Map.Entry<CompositionEntityId, CompositionEntityData> entityEntry : entities
418 if (entityEntry.getKey().getId().equals(entity.getEntityId())) {
419 return entityEntry.getValue();
426 private void updateValidationCompositionEntityName(Set<CompositionEntityValidationData>
428 for (CompositionEntityValidationData entity : compositionSet) {
429 String compositionData = getCompositionDataAsString(entity);
430 if (entity.getEntityType().equals(CompositionEntityType.vsp) ||
431 Objects.nonNull(compositionData)) {
432 entity.setEntityName(getEntityNameByEntityType(compositionData, entity));
437 private String getCompositionDataAsString(CompositionEntityValidationData entity) {
438 CompositionEntityData compositionEntityData = getCompositionEntityDataById(entity);
439 return compositionEntityData == null ? null : compositionEntityData.entity.getCompositionData();
443 private String getEntityNameByEntityType(String compositionData,
444 CompositionEntityValidationData entity) {
445 switch (entity.getEntityType()) {
447 ComponentData component = JsonUtil.json2Object(compositionData, ComponentData.class);
448 return component.getDisplayName();
451 Nic nic = JsonUtil.json2Object(compositionData, Nic.class);
452 return nic.getName();
455 Network network = JsonUtil.json2Object(compositionData, Network.class);
456 return network.getName();
459 CompositionEntityData vspEntity = getCompositionEntityDataById(entity);
460 VspQuestionnaireEntity vspQuestionnaireEntity = (VspQuestionnaireEntity) vspEntity.entity;
461 VspDetails vspDetails =
462 vspInfoDao.get(new VspDetails(vspQuestionnaireEntity.getId(),
463 vspQuestionnaireEntity.getVersion()));
464 return vspDetails.getName();
470 private void removeNodesWithoutErrors(CompositionEntityValidationData node,
471 CompositionEntityValidationData parent) {
473 if (Objects.isNull(node)) {
477 if (hasChildren(node)) {
478 Collection<CompositionEntityValidationData> subNodes =
479 new ArrayList<>(node.getSubEntitiesValidationData());
480 subNodes.forEach(subNode -> removeNodesWithoutErrors(subNode, node));
481 node.setSubEntitiesValidationData(subNodes);
483 if (canNodeGetRemovedFromValidationDataTree(node)) {
484 removeNodeFromChildren(parent, node);
486 } else if (canNodeGetRemovedFromValidationDataTree(node)) {
487 removeNodeFromChildren(parent, node);
491 private void removeNodeFromChildren(CompositionEntityValidationData parent,
492 CompositionEntityValidationData childToRemove) {
493 if (!Objects.isNull(parent)) {
494 parent.getSubEntitiesValidationData().remove(childToRemove);
498 private boolean hasChildren(CompositionEntityValidationData node) {
499 return !CollectionUtils.isEmpty(node.getSubEntitiesValidationData());
502 private boolean canNodeGetRemovedFromValidationDataTree(CompositionEntityValidationData node) {
503 return !hasChildren(node) && CollectionUtils.isEmpty(node.getErrors());
507 private void addValidationDataEntity(
508 Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData,
509 CompositionEntityId entityId, CompositionEntity entity) {
510 if (entitiesValidationData.containsKey(entityId)) {
514 CompositionEntityValidationData validationData =
515 new CompositionEntityValidationData(entity.getType(), entity.getId());
516 entitiesValidationData.put(entityId, validationData);
518 CompositionEntityId parentEntityId = entityId.getParentId();
519 if (parentEntityId == null) {
520 roots.add(validationData);
522 CompositionEntityData parentEntity = entities.get(parentEntityId);
523 if (parentEntity == null) {
524 roots.add(validationData);
526 addValidationDataEntity(entitiesValidationData, parentEntityId, parentEntity.entity);
527 entitiesValidationData.get(parentEntityId).addSubEntityValidationData(validationData);
532 private void addErrorsToTree(CompositionEntityValidationData node,
533 CompositionEntityId parentNodeId,
534 Map<CompositionEntityId, Collection<String>> errors) {
538 CompositionEntityId nodeId = new CompositionEntityId(node.getEntityId(), parentNodeId);
539 node.setErrors(errors.get(nodeId));
541 if (node.getSubEntitiesValidationData() != null) {
542 node.getSubEntitiesValidationData()
543 .forEach(subNode -> addErrorsToTree(subNode, nodeId, errors));
547 private Collection<String> validateQuestionnaire(CompositionEntityData compositionEntityData) {
548 return JsonUtil.validate(
549 compositionEntityData.entity.getQuestionnaireData() == null
550 ? JsonUtil.object2Json(new Object())
551 : compositionEntityData.entity.getQuestionnaireData(),
552 getSchema(compositionEntityData.entity.getType(), SchemaTemplateContext.questionnaire,
553 compositionEntityData.schemaTemplateInput));
556 private String getSchema(CompositionEntityType compositionEntityType,
557 SchemaTemplateContext schemaTemplateContext,
558 SchemaTemplateInput schemaTemplateInput) {
559 return schemaTemplateInput == null
560 ? nonDynamicSchemas.computeIfAbsent(compositionEntityType,
561 k -> generateSchema(schemaTemplateContext, compositionEntityType, null))
562 : generateSchema(schemaTemplateContext, compositionEntityType, schemaTemplateInput);
565 private static class CompositionEntityData {
566 private CompositionEntity entity;
567 private SchemaTemplateInput schemaTemplateInput;
569 CompositionEntityData(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
570 this.entity = entity;
571 this.schemaTemplateInput = schemaTemplateInput;
576 // todo - make SchemaGenerator non static and mock it in UT instead of mocking this method (and
577 // make the method private
579 protected String generateSchema(SchemaTemplateContext schemaTemplateContext,
580 CompositionEntityType compositionEntityType,
581 SchemaTemplateInput schemaTemplateInput) {
582 return SchemaGenerator
583 .generate(schemaTemplateContext, compositionEntityType, schemaTemplateInput);