package org.alien4cloud.tosca.editor.processors.nodetemplate; import java.util.HashMap; import javax.inject.Inject; import org.alien4cloud.tosca.catalog.index.IToscaTypeSearchService; import org.alien4cloud.tosca.editor.EditionContextManager; import org.alien4cloud.tosca.editor.operations.nodetemplate.AddNodeOperation; import org.alien4cloud.tosca.editor.processors.IEditorOperationProcessor; import org.alien4cloud.tosca.model.templates.NodeTemplate; import org.alien4cloud.tosca.model.templates.Topology; import org.alien4cloud.tosca.model.types.NodeType; import org.springframework.stereotype.Component; import alien4cloud.application.TopologyCompositionService; import alien4cloud.exception.CyclicReferenceException; import alien4cloud.exception.InvalidNodeNameException; import alien4cloud.exception.NotFoundException; import alien4cloud.paas.wf.WorkflowsBuilderService; import alien4cloud.topology.TopologyService; import alien4cloud.topology.TopologyUtils; import lombok.extern.slf4j.Slf4j; /** * Process an {@link AddNodeOperation} */ @Slf4j @Component public class AddNodeProcessor implements IEditorOperationProcessor<AddNodeOperation> { @Inject private IToscaTypeSearchService toscaTypeSearchService; @Inject private TopologyService topologyService; @Inject private TopologyCompositionService topologyCompositionService; @Inject private WorkflowsBuilderService workflowBuilderService; @Override public void process(AddNodeOperation operation) { Topology topology = EditionContextManager.getTopology(); if (!TopologyUtils.isValidNodeName(operation.getNodeName())) { throw new InvalidNodeNameException("A name should only contains alphanumeric character from the basic Latin alphabet and the underscore."); } topologyService.isUniqueNodeTemplateName(topology, operation.getNodeName()); String[] splittedId = operation.getIndexedNodeTypeId().split(":"); NodeType indexedNodeType = toscaTypeSearchService.find(NodeType.class, splittedId[0], splittedId[1]); if (indexedNodeType == null) { throw new NotFoundException(NodeType.class.getName(), operation.getIndexedNodeTypeId(), "Unable to find node type to create template in topology."); } if (indexedNodeType.getSubstitutionTopologyId() != null) { // TODO merge that in the topologyCompositionService.recursivelyDetectTopologyCompositionCyclicReference // it's a try to add this topology's type if (indexedNodeType.getSubstitutionTopologyId().equals(topology.getId())) { throw new CyclicReferenceException("Cyclic reference : a topology template can not reference itself"); } // detect try to add a substitution topology that indirectly reference this one topologyCompositionService.recursivelyDetectTopologyCompositionCyclicReference(topology.getId(), indexedNodeType.getSubstitutionTopologyId()); } if (topology.getNodeTemplates() == null) { topology.setNodeTemplates(new HashMap<>()); } log.debug("Create node template <{}>", operation.getNodeName()); indexedNodeType = topologyService.loadType(topology, indexedNodeType); NodeTemplate nodeTemplate = topologyService.buildNodeTemplate(topology.getDependencies(), indexedNodeType, null); nodeTemplate.setName(operation.getNodeName()); topology.getNodeTemplates().put(operation.getNodeName(), nodeTemplate); log.debug("Adding a new Node template <" + operation.getNodeName() + "> bound to the node type <" + operation.getIndexedNodeTypeId() + "> to the topology <" + topology.getId() + "> ."); WorkflowsBuilderService.TopologyContext topologyContext = workflowBuilderService.buildTopologyContext(topology); workflowBuilderService.addNode(topologyContext, operation.getNodeName(), nodeTemplate); } }