package alien4cloud.tosca.parser.postprocess;
import static alien4cloud.utils.AlienUtils.safe;
import java.util.Objects;
import javax.annotation.Resource;
import org.alien4cloud.tosca.model.definitions.Operation;
import org.alien4cloud.tosca.model.templates.NodeTemplate;
import org.alien4cloud.tosca.model.types.NodeType;
import org.springframework.stereotype.Component;
import org.yaml.snakeyaml.nodes.Node;
import alien4cloud.tosca.context.ToscaContext;
import alien4cloud.tosca.parser.ParsingContextExecution;
import alien4cloud.tosca.parser.ParsingError;
import alien4cloud.tosca.parser.ParsingErrorLevel;
import alien4cloud.tosca.parser.impl.ErrorCode;
import alien4cloud.tosca.topology.NodeTemplateBuilder;
/**
* Post process a node template
*/
@Component
public class NodeTemplatePostProcessor implements IPostProcessor<NodeTemplate> {
@Resource
private ReferencePostProcessor referencePostProcessor;
@Resource
private CapabilityPostProcessor capabilityPostProcessor;
@Resource
private RequirementPostProcessor requirementPostProcessor;
@Resource
private PropertyValueChecker propertyValueChecker;
@Resource
private TemplateDeploymentArtifactPostProcessor templateDeploymentArtifactPostProcessor;
@Resource
private ImplementationArtifactPostProcessor implementationArtifactPostProcessor;
@Override
public void process(final NodeTemplate instance) {
// ensure type exists
referencePostProcessor.process(new ReferencePostProcessor.TypeReference(instance, instance.getType(), NodeType.class));
final NodeType nodeType = ToscaContext.get(NodeType.class, instance.getType());
if (nodeType == null) {
return; // error managed by the reference post processor.
}
// FIXME we should check that the artifact is defined at the type level.
safe(instance.getArtifacts()).values().forEach(templateDeploymentArtifactPostProcessor);
// TODO Manage interfaces inputs to copy them to all operations.
safe(instance.getInterfaces()).values().stream().flatMap(anInterface -> safe(anInterface.getOperations()).values().stream())
.map(Operation::getImplementationArtifact).filter(Objects::nonNull).forEach(implementationArtifactPostProcessor);
// Merge the node template with data coming from the type (default values etc.).
NodeTemplate tempObject = NodeTemplateBuilder.buildNodeTemplate(nodeType, instance, false);
safe(instance.getCapabilities()).keySet().forEach(s -> {
if (!safe(tempObject.getCapabilities()).containsKey(s)) {
Node node = ParsingContextExecution.getObjectToNodeMap().get(s);
ParsingContextExecution.getParsingErrors()
.add(new ParsingError(ParsingErrorLevel.WARNING, ErrorCode.UNKNOWN_CAPABILITY, null, node.getStartMark(), null, node.getEndMark(), s));
}
});
instance.setAttributes(tempObject.getAttributes());
instance.setCapabilities(tempObject.getCapabilities());
instance.setProperties(tempObject.getProperties());
instance.setRequirements(tempObject.getRequirements());
instance.setArtifacts(tempObject.getArtifacts());
instance.setInterfaces(tempObject.getInterfaces());
// apply post processor to capabilities defined locally on the element (no need to post-processed the one merged)
safe(instance.getCapabilities()).entrySet().forEach(capabilityPostProcessor);
safe(instance.getRequirements()).entrySet().forEach(requirementPostProcessor);
propertyValueChecker.checkProperties(nodeType, instance.getProperties(), instance.getName());
}
}