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.api.Logger;
31 import org.openecomp.sdc.logging.api.LoggerFactory;
32 import org.openecomp.sdc.logging.context.impl.MdcDataDebugMessage;
33 import org.openecomp.sdc.vendorsoftwareproduct.dao.ComponentDao;
34 import org.openecomp.sdc.vendorsoftwareproduct.dao.NetworkDao;
35 import org.openecomp.sdc.vendorsoftwareproduct.dao.NicDao;
36 import org.openecomp.sdc.vendorsoftwareproduct.dao.VendorSoftwareProductInfoDao;
37 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.ComponentEntity;
38 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.CompositionEntity;
39 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NetworkEntity;
40 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.NicEntity;
41 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspDetails;
42 import org.openecomp.sdc.vendorsoftwareproduct.dao.type.VspQuestionnaireEntity;
43 import org.openecomp.sdc.vendorsoftwareproduct.services.composition.CompositionEntityDataManager;
44 import org.openecomp.sdc.vendorsoftwareproduct.services.schemagenerator.SchemaGenerator;
45 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Component;
46 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.ComponentData;
47 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionData;
48 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityId;
49 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityType;
50 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.CompositionEntityValidationData;
51 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Network;
52 import org.openecomp.sdc.vendorsoftwareproduct.types.composition.Nic;
53 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateContext;
54 import org.openecomp.sdc.vendorsoftwareproduct.types.schemagenerator.SchemaTemplateInput;
55 import org.openecomp.sdc.versioning.dao.types.Version;
57 import java.util.ArrayList;
58 import java.util.Collection;
59 import java.util.HashMap;
60 import java.util.HashSet;
61 import java.util.List;
63 import java.util.Objects;
66 public class CompositionEntityDataManagerImpl implements CompositionEntityDataManager {
68 private static final String COMPOSITION_ENTITY_DATA_MANAGER_ERR =
69 "COMPOSITION_ENTITY_DATA_MANAGER_ERR";
70 private static final String COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG =
71 "Invalid input: %s may not be null";
73 private static final Logger logger =
74 LoggerFactory.getLogger(CompositionEntityDataManagerImpl.class);
75 private static MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
77 private Map<CompositionEntityId, CompositionEntityData> entities = new HashMap<>();
78 private Map<CompositionEntityType, String> nonDynamicSchemas = new HashMap<>();
79 private List<CompositionEntityValidationData> roots = new ArrayList<>();
81 private VendorSoftwareProductInfoDao vspInfoDao;
82 private ComponentDao componentDao;
83 private NicDao nicDao;
84 private NetworkDao networkDao;
86 public CompositionEntityDataManagerImpl(VendorSoftwareProductInfoDao vspInfoDao,
87 ComponentDao componentDao,
88 NicDao nicDao, NetworkDao networkDao) {
89 this.vspInfoDao = vspInfoDao;
90 this.componentDao = componentDao;
92 this.networkDao = networkDao;
96 * Validate entity composition entity validation data.
98 * @param entity the entity
99 * @param schemaTemplateContext the schema template context
100 * @param schemaTemplateInput the schema template input
101 * @return the composition entity validation data
104 public CompositionEntityValidationData validateEntity(CompositionEntity entity,
105 SchemaTemplateContext schemaTemplateContext,
106 SchemaTemplateInput schemaTemplateInput) {
107 mdcDataDebugMessage.debugEntryMessage(null);
109 if (entity == null) {
110 throw new CoreException(
111 new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
112 .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
113 String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "composition entity"))
116 if (schemaTemplateContext == null) {
117 throw new CoreException(
118 new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
119 .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
120 String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "schema template context"))
124 CompositionEntityValidationData validationData =
125 new CompositionEntityValidationData(entity.getType(), entity.getId());
127 schemaTemplateContext == SchemaTemplateContext.composition ? entity.getCompositionData()
128 : entity.getQuestionnaireData();
129 validationData.setErrors(JsonUtil.validate(
130 json == null ? JsonUtil.object2Json(new Object()) : json,
131 generateSchema(schemaTemplateContext, entity.getType(), schemaTemplateInput)));
133 mdcDataDebugMessage.debugExitMessage(null);
134 return validationData;
140 * @param entity the entity
141 * @param schemaTemplateInput the schema template input
144 public void addEntity(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
145 if (entity == null) {
146 throw new CoreException(
147 new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION)
148 .withId(COMPOSITION_ENTITY_DATA_MANAGER_ERR).withMessage(
149 String.format(COMPOSITION_ENTITY_DATA_MANAGER_ERR_MSG, "composition entity"))
152 entities.put(entity.getCompositionEntityId(),
153 new CompositionEntityData(entity, schemaTemplateInput));
157 * Validate entities questionnaire map.
162 public Map<CompositionEntityId, Collection<String>> validateEntitiesQuestionnaire() {
163 mdcDataDebugMessage.debugEntryMessage(null);
165 Map<CompositionEntityId, Collection<String>> errorsByEntityId = new HashMap<>();
166 entities.entrySet().forEach(entry -> {
167 Collection<String> errors = validateQuestionnaire(entry.getValue());
168 if (errors != null) {
169 errorsByEntityId.put(entry.getKey(), errors);
173 mdcDataDebugMessage.debugExitMessage(null);
174 return errorsByEntityId;
181 public void buildTrees() {
182 Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData =
184 entities.entrySet().forEach(
185 entry -> addValidationDataEntity(entitiesValidationData, entry.getKey(),
186 entry.getValue().entity));
189 public Collection<CompositionEntityValidationData> getTrees() {
194 public void saveCompositionData(String vspId, Version version, CompositionData compositionData) {
195 mdcDataDebugMessage.debugEntryMessage(null);
197 if (Objects.isNull(compositionData)) {
201 Map<String, String> networkIdByName = saveNetworks(vspId, version, compositionData);
202 saveComponents(vspId, version, compositionData, networkIdByName);
204 mdcDataDebugMessage.debugExitMessage(null);
208 public Set<CompositionEntityValidationData> getAllErrorsByVsp(String vspId) {
209 CompositionEntityValidationData matchVsp = null;
210 Set<CompositionEntityValidationData> entitiesWithErrors = new HashSet<>();
211 for (CompositionEntityValidationData root : roots) {
212 if (root.getEntityId().equals(vspId)) {
218 getEntityListWithErrors(matchVsp, entitiesWithErrors);
219 if (CollectionUtils.isNotEmpty(entitiesWithErrors)) {
220 updateValidationCompositionEntityName(entitiesWithErrors);
221 return entitiesWithErrors;
227 private boolean isThereErrorsInSubTree(CompositionEntityValidationData entity) {
228 if (Objects.isNull(entity)) {
232 if (CollectionUtils.isNotEmpty(entity.getErrors())) {
236 Collection<CompositionEntityValidationData> subEntitiesValidationData =
237 entity.getSubEntitiesValidationData();
238 return !CollectionUtils.isEmpty(subEntitiesValidationData) &&
239 checkForErrorsInChildren(subEntitiesValidationData);
243 private boolean checkForErrorsInChildren(
244 Collection<CompositionEntityValidationData> subEntitiesValidationData) {
245 boolean result = false;
246 for (CompositionEntityValidationData subEntity : subEntitiesValidationData) {
247 if (CollectionUtils.isNotEmpty(subEntity.getErrors())) {
251 result = result || isThereErrorsInSubTree(subEntity);
259 public void saveComponents(String vspId, Version version, CompositionData compositionData,
260 Map<String, String> networkIdByName) {
263 mdcDataDebugMessage.debugEntryMessage(null);
265 if (CollectionUtils.isNotEmpty(compositionData.getComponents())) {
266 for (Component component : compositionData.getComponents()) {
267 ComponentEntity componentEntity = new ComponentEntity(vspId, version, null);
268 componentEntity.setComponentCompositionData(component.getData());
270 String componentId = createComponent(componentEntity).getId();
272 saveNicsByComponent(vspId, version, networkIdByName, component, componentId);
276 mdcDataDebugMessage.debugExitMessage(null);
279 public void saveNicsByComponent(String vspId, Version version,
280 Map<String, String> networkIdByName, Component component,
281 String componentId) {
282 if (CollectionUtils.isNotEmpty(component.getNics())) {
283 for (Nic nic : component.getNics()) {
284 if (nic.getNetworkName() != null && MapUtils.isNotEmpty(networkIdByName)) {
285 nic.setNetworkId(networkIdByName.get(nic.getNetworkName()));
287 nic.setNetworkName(null);
289 NicEntity nicEntity = new NicEntity(vspId, version, componentId, null);
290 nicEntity.setNicCompositionData(nic);
291 createNic(nicEntity);
296 public Map<String, String> saveNetworks(String vspId, Version version,
297 CompositionData compositionData) {
298 mdcDataDebugMessage.debugEntryMessage(null);
300 Map<String, String> networkIdByName = new HashMap<>();
301 if (CollectionUtils.isNotEmpty(compositionData.getNetworks())) {
302 for (Network network : compositionData.getNetworks()) {
304 NetworkEntity networkEntity = new NetworkEntity(vspId, version, null);
305 networkEntity.setNetworkCompositionData(network);
307 if (network.getName() != null) {
308 networkIdByName.put(network.getName(), createNetwork(networkEntity).getId());
313 mdcDataDebugMessage.debugExitMessage(null);
314 return networkIdByName;
318 public NetworkEntity createNetwork(NetworkEntity network) {
319 mdcDataDebugMessage.debugEntryMessage(null);
321 //network.setId(CommonMethods.nextUuId()); will be set by the dao
322 networkDao.create(network);
323 mdcDataDebugMessage.debugExitMessage(null);
328 public ComponentEntity createComponent(ComponentEntity component) {
329 mdcDataDebugMessage.debugEntryMessage(null);
331 //component.setId(CommonMethods.nextUuId()); will be set by the dao
332 component.setQuestionnaireData(
333 new JsonSchemaDataGenerator(
334 generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.component,
338 componentDao.create(component);
340 mdcDataDebugMessage.debugExitMessage(null);
345 public NicEntity createNic(NicEntity nic) {
346 mdcDataDebugMessage.debugEntryMessage(null);
348 //nic.setId(CommonMethods.nextUuId()); will be set by the dao
349 nic.setQuestionnaireData(
350 new JsonSchemaDataGenerator(
351 generateSchema(SchemaTemplateContext.questionnaire, CompositionEntityType.nic, null))
356 mdcDataDebugMessage.debugExitMessage(null);
361 public void addErrorsToTrees(Map<CompositionEntityId, Collection<String>> errors) {
362 roots.forEach(root -> addErrorsToTree(root, null, errors));
366 * get a flat list of all questionnaire entities that have validation errors
368 public Set<CompositionEntityValidationData> getEntityListWithErrors() {
369 mdcDataDebugMessage.debugEntryMessage(null);
370 Set<CompositionEntityValidationData> treeAsList = new HashSet<>();
372 for (CompositionEntityValidationData entity : roots) {
373 if (CollectionUtils.isNotEmpty(entity.getErrors())) {
374 addNodeWithErrors(entity, treeAsList);
376 getEntityListWithErrors(entity, treeAsList);
379 updateValidationCompositionEntityName(treeAsList);
381 mdcDataDebugMessage.debugExitMessage(null);
385 public void getEntityListWithErrors(CompositionEntityValidationData entity,
386 Set<CompositionEntityValidationData> compositionSet) {
387 Collection<CompositionEntityValidationData> childNodes =
388 entity.getSubEntitiesValidationData();
390 if (CollectionUtils.isEmpty(childNodes)) {
394 for (CompositionEntityValidationData child : childNodes) {
395 if (CollectionUtils.isNotEmpty(child.getErrors())) {
396 addNodeWithErrors(child, compositionSet);
398 getEntityListWithErrors(child, compositionSet);
403 public void addNodeWithErrors(CompositionEntityValidationData node,
404 Set<CompositionEntityValidationData> entitiesWithErrors) {
405 CompositionEntityValidationData compositionNodeToAdd = new CompositionEntityValidationData(node
406 .getEntityType(), node.getEntityId());
407 compositionNodeToAdd.setErrors(node.getErrors());
408 compositionNodeToAdd.setSubEntitiesValidationData(null);
410 entitiesWithErrors.add(compositionNodeToAdd);
413 public void removeNodesWithoutErrors() {
414 roots.forEach(root -> removeNodesWithoutErrors(root, null));
418 private CompositionEntityData getCompositionEntityDataById(CompositionEntityValidationData
420 for (Map.Entry<CompositionEntityId, CompositionEntityData> entityEntry : entities
422 if (entityEntry.getKey().getId().equals(entity.getEntityId())) {
423 return entityEntry.getValue();
430 private void updateValidationCompositionEntityName(Set<CompositionEntityValidationData>
432 for (CompositionEntityValidationData entity : compositionSet) {
433 String compositionData = getCompositionDataAsString(entity);
434 if (entity.getEntityType().equals(CompositionEntityType.vsp) ||
435 Objects.nonNull(compositionData)) {
436 entity.setEntityName(getEntityNameByEntityType(compositionData, entity));
441 private String getCompositionDataAsString(CompositionEntityValidationData entity) {
442 CompositionEntityData compositionEntityData = getCompositionEntityDataById(entity);
443 return compositionEntityData == null ? null : compositionEntityData.entity.getCompositionData();
447 private String getEntityNameByEntityType(String compositionData,
448 CompositionEntityValidationData entity) {
449 switch (entity.getEntityType()) {
451 ComponentData component = JsonUtil.json2Object(compositionData, ComponentData.class);
452 return component.getDisplayName();
455 Nic nic = JsonUtil.json2Object(compositionData, Nic.class);
456 return nic.getName();
459 Network network = JsonUtil.json2Object(compositionData, Network.class);
460 return network.getName();
463 CompositionEntityData vspEntity = getCompositionEntityDataById(entity);
464 VspQuestionnaireEntity vspQuestionnaireEntity = (VspQuestionnaireEntity) vspEntity.entity;
465 VspDetails vspDetails =
466 vspInfoDao.get(new VspDetails(vspQuestionnaireEntity.getId(),
467 vspQuestionnaireEntity.getVersion()));
468 return vspDetails.getName();
474 private void removeNodesWithoutErrors(CompositionEntityValidationData node,
475 CompositionEntityValidationData parent) {
477 if (Objects.isNull(node)) {
481 if (hasChildren(node)) {
482 Collection<CompositionEntityValidationData> subNodes =
483 new ArrayList<>(node.getSubEntitiesValidationData());
484 subNodes.forEach(subNode -> removeNodesWithoutErrors(subNode, node));
485 node.setSubEntitiesValidationData(subNodes);
487 if (canNodeGetRemovedFromValidationDataTree(node)) {
488 removeNodeFromChildren(parent, node);
490 } else if (canNodeGetRemovedFromValidationDataTree(node)) {
491 removeNodeFromChildren(parent, node);
495 private void removeNodeFromChildren(CompositionEntityValidationData parent,
496 CompositionEntityValidationData childToRemove) {
497 if (!Objects.isNull(parent)) {
498 parent.getSubEntitiesValidationData().remove(childToRemove);
502 private boolean hasChildren(CompositionEntityValidationData node) {
503 return !CollectionUtils.isEmpty(node.getSubEntitiesValidationData());
506 private boolean canNodeGetRemovedFromValidationDataTree(CompositionEntityValidationData node) {
507 return !hasChildren(node) && CollectionUtils.isEmpty(node.getErrors());
511 private void addValidationDataEntity(
512 Map<CompositionEntityId, CompositionEntityValidationData> entitiesValidationData,
513 CompositionEntityId entityId, CompositionEntity entity) {
514 if (entitiesValidationData.containsKey(entityId)) {
518 CompositionEntityValidationData validationData =
519 new CompositionEntityValidationData(entity.getType(), entity.getId());
520 entitiesValidationData.put(entityId, validationData);
522 CompositionEntityId parentEntityId = entityId.getParentId();
523 if (parentEntityId == null) {
524 roots.add(validationData);
526 CompositionEntityData parentEntity = entities.get(parentEntityId);
527 if (parentEntity == null) {
528 roots.add(validationData);
530 addValidationDataEntity(entitiesValidationData, parentEntityId, parentEntity.entity);
531 entitiesValidationData.get(parentEntityId).addSubEntityValidationData(validationData);
536 private void addErrorsToTree(CompositionEntityValidationData node,
537 CompositionEntityId parentNodeId,
538 Map<CompositionEntityId, Collection<String>> errors) {
542 CompositionEntityId nodeId = new CompositionEntityId(node.getEntityId(), parentNodeId);
543 node.setErrors(errors.get(nodeId));
545 if (node.getSubEntitiesValidationData() != null) {
546 node.getSubEntitiesValidationData()
547 .forEach(subNode -> addErrorsToTree(subNode, nodeId, errors));
551 private Collection<String> validateQuestionnaire(CompositionEntityData compositionEntityData) {
552 logger.debug(String.format("validateQuestionnaire start: " +
553 "[entity.type]=%s, [entity.id]=%s, [entity.questionnaireString]=%s",
554 compositionEntityData.entity.getType().name(),
555 compositionEntityData.entity.getCompositionEntityId().toString(),
556 compositionEntityData.entity.getQuestionnaireData()));
558 return JsonUtil.validate(
559 compositionEntityData.entity.getQuestionnaireData() == null
560 ? JsonUtil.object2Json(new Object())
561 : compositionEntityData.entity.getQuestionnaireData(),
562 getSchema(compositionEntityData.entity.getType(), SchemaTemplateContext.questionnaire,
563 compositionEntityData.schemaTemplateInput));
566 private String getSchema(CompositionEntityType compositionEntityType,
567 SchemaTemplateContext schemaTemplateContext,
568 SchemaTemplateInput schemaTemplateInput) {
569 return schemaTemplateInput == null
570 ? nonDynamicSchemas.computeIfAbsent(compositionEntityType,
571 k -> generateSchema(schemaTemplateContext, compositionEntityType, null))
572 : generateSchema(schemaTemplateContext, compositionEntityType, schemaTemplateInput);
575 private static class CompositionEntityData {
576 private CompositionEntity entity;
577 private SchemaTemplateInput schemaTemplateInput;
579 CompositionEntityData(CompositionEntity entity, SchemaTemplateInput schemaTemplateInput) {
580 this.entity = entity;
581 this.schemaTemplateInput = schemaTemplateInput;
586 // todo - make SchemaGenerator non static and mock it in UT instead of mocking this method (and
587 // make the method private
589 protected String generateSchema(SchemaTemplateContext schemaTemplateContext,
590 CompositionEntityType compositionEntityType,
591 SchemaTemplateInput schemaTemplateInput) {
592 return SchemaGenerator
593 .generate(schemaTemplateContext, compositionEntityType, schemaTemplateInput);