package alien4cloud.topology; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import javax.annotation.Resource; import org.alien4cloud.tosca.model.CSARDependency; import org.alien4cloud.tosca.model.templates.Capability; import org.alien4cloud.tosca.model.templates.NodeTemplate; import org.alien4cloud.tosca.model.templates.RelationshipTemplate; import org.alien4cloud.tosca.model.templates.Topology; import org.alien4cloud.tosca.model.types.CapabilityType; import org.alien4cloud.tosca.model.types.NodeType; import org.alien4cloud.tosca.model.types.RelationshipType; import org.elasticsearch.common.collect.Lists; import org.springframework.stereotype.Service; import com.google.common.collect.Maps; import alien4cloud.component.ICSARRepositorySearchService; import alien4cloud.dao.IGenericSearchDAO; import alien4cloud.exception.NotFoundException; import alien4cloud.tosca.context.ToscaContextual; import alien4cloud.tosca.topology.NodeTemplateBuilder; import lombok.extern.slf4j.Slf4j; @Service @Slf4j public class TopologyServiceCore { @Resource(name = "alien-es-dao") private IGenericSearchDAO alienDAO; @Resource private ICSARRepositorySearchService csarRepoSearchService; /** * Get the Map of {@link NodeTemplate} from a topology * * @param topology the topology * @return this topology's node templates */ public static Map<String, NodeTemplate> getNodeTemplates(Topology topology) { Map<String, NodeTemplate> nodeTemplates = topology.getNodeTemplates(); if (nodeTemplates == null) { throw new NotFoundException("Topology [" + topology.getId() + "] do not have any node template"); } return nodeTemplates; } /** * Get a {@link NodeTemplate} given its name from a map * * @param topologyId the topology's id * @param nodeTemplateName the name of the node template * @param nodeTemplates the topology's node templates * @return the found node template, throws NotFoundException if not found */ public static NodeTemplate getNodeTemplate(String topologyId, String nodeTemplateName, Map<String, NodeTemplate> nodeTemplates) { NodeTemplate nodeTemplate = nodeTemplates.get(nodeTemplateName); if (nodeTemplate == null) { throw new NotFoundException("Topology [" + topologyId + "] do not have node template with name [" + nodeTemplateName + "]"); } return nodeTemplate; } public Topology getTopology(String topologyId) { return alienDAO.findById(Topology.class, topologyId); } /** * Retrieve a topology given its Id * * @param topologyId id of the topology * @return the found topology, throws NotFoundException if not found */ public Topology getOrFail(String topologyId) { Topology topology = getTopology(topologyId); if (topology == null) { throw new NotFoundException("Topology [" + topologyId + "] cannot be found"); } return topology; } /** * Get a {@link NodeTemplate} given its name from a topology * * @param topology the topology * @param nodeTemplateId the name of the node template * @return the found node template, throws NotFoundException if not found */ public static NodeTemplate getNodeTemplate(Topology topology, String nodeTemplateId) { Map<String, NodeTemplate> nodeTemplates = getNodeTemplates(topology); return getNodeTemplate(topology.getId(), nodeTemplateId, nodeTemplates); } /** * Get the indexed node types used in a topology. * * @param topology The topology for which to get indexed node types. * @param abstractOnly If true, only abstract types will be retrieved. * @param useTemplateNameAsKey If true the name of the node template will be used as key for the type in the returned map, if not the type will be used as * key. * @param failOnTypeNotFound * @return A map of indexed node types. */ public Map<String, NodeType> getIndexedNodeTypesFromTopology(Topology topology, boolean abstractOnly, boolean useTemplateNameAsKey, boolean failOnTypeNotFound) { return getIndexedNodeTypesFromDependencies(topology.getNodeTemplates(), topology.getDependencies(), abstractOnly, useTemplateNameAsKey, failOnTypeNotFound); } public Map<String, NodeType> getIndexedNodeTypesFromDependencies(Map<String, NodeTemplate> nodeTemplates, Set<CSARDependency> dependencies, boolean abstractOnly, boolean useTemplateNameAsKey, boolean failOnTypeNotFound) { Map<String, NodeType> nodeTypes = Maps.newHashMap(); if (nodeTemplates == null) { return nodeTypes; } for (Map.Entry<String, NodeTemplate> template : nodeTemplates.entrySet()) { if (!nodeTypes.containsKey(template.getValue().getType())) { NodeType nodeType = failOnTypeNotFound ? csarRepoSearchService.getRequiredElementInDependencies(NodeType.class, template.getValue().getType(), dependencies) : csarRepoSearchService.getElementInDependencies(NodeType.class, template.getValue().getType(), dependencies); if (!abstractOnly || nodeType.isAbstract()) { String key = useTemplateNameAsKey ? template.getKey() : template.getValue().getType(); nodeTypes.put(key, nodeType); } } } return nodeTypes; } /** * Get IndexedRelationshipType in a topology * * @param topology the topology to find all relationship types * @param failOnTypeNotFound * @return the map containing rel */ public Map<String, RelationshipType> getIndexedRelationshipTypesFromTopology(Topology topology, boolean failOnTypeNotFound) { Map<String, RelationshipType> relationshipTypes = Maps.newHashMap(); if (topology.getNodeTemplates() == null) { return relationshipTypes; } for (Map.Entry<String, NodeTemplate> templateEntry : topology.getNodeTemplates().entrySet()) { NodeTemplate template = templateEntry.getValue(); if (template.getRelationships() != null) { for (Map.Entry<String, RelationshipTemplate> relationshipEntry : template.getRelationships().entrySet()) { RelationshipTemplate relationship = relationshipEntry.getValue(); if (!relationshipTypes.containsKey(relationship.getType())) { RelationshipType relationshipType = failOnTypeNotFound ? csarRepoSearchService.getRequiredElementInDependencies(RelationshipType.class, relationship.getType(), topology.getDependencies()) : csarRepoSearchService.getElementInDependencies(RelationshipType.class, relationship.getType(), topology.getDependencies()); relationshipTypes.put(relationship.getType(), relationshipType); } } } } return relationshipTypes; } /** * Get IndexedRelationshipType in a topology * * @param topology the topology to find all relationship types * @return the map containing rel */ public Map<String, CapabilityType> getIndexedCapabilityTypesFromTopology(Topology topology) { Map<String, CapabilityType> capabilityTypes = Maps.newHashMap(); if (topology.getNodeTemplates() == null) { return capabilityTypes; } for (Map.Entry<String, NodeTemplate> templateEntry : topology.getNodeTemplates().entrySet()) { NodeTemplate template = templateEntry.getValue(); if (template.getCapabilities() != null) { for (Map.Entry<String, Capability> capabilityEntry : template.getCapabilities().entrySet()) { Capability capability = capabilityEntry.getValue(); if (!capabilityTypes.containsKey(capability.getType())) { CapabilityType capabilityType = csarRepoSearchService.getRequiredElementInDependencies(CapabilityType.class, capability.getType(), topology.getDependencies()); capabilityTypes.put(capability.getType(), capabilityType); } } } } return capabilityTypes; } /** * Build a node template * * @param dependencies The dependencies in which to search for the node type. This is used by the ToscaContextual annotation. * @param indexedNodeType The index node type from which to create the node. * @param templateToMerge The node template to merge in the type to create the actual node template. * @return return the node template instance. */ @ToscaContextual public NodeTemplate buildNodeTemplate(Set<CSARDependency> dependencies, NodeType indexedNodeType, NodeTemplate templateToMerge) { return NodeTemplateBuilder.buildNodeTemplate(indexedNodeType, templateToMerge); } /** * * Get all the relationships in which a given node template is a target * * @param nodeTemplateName the name of the node template which is target for relationship * @param nodeTemplates all topology's node templates * @return all relationships which have nodeTemplateName as target */ public List<RelationshipTemplate> getTargetRelatedRelatonshipsTemplate(String nodeTemplateName, Map<String, NodeTemplate> nodeTemplates) { List<RelationshipTemplate> toReturn = Lists.newArrayList(); for (String key : nodeTemplates.keySet()) { NodeTemplate nodeTemp = nodeTemplates.get(key); if (nodeTemp.getRelationships() == null) { continue; } for (String key2 : nodeTemp.getRelationships().keySet()) { RelationshipTemplate relTemp = nodeTemp.getRelationships().get(key2); if (relTemp == null) { continue; } if (relTemp.getTarget() != null && relTemp.getTarget().equals(nodeTemplateName)) { toReturn.add(relTemp); } } } return toReturn; } /** * Assign an id to the topology, save it and return the generated id. * * @param topology * @return */ public String saveTopology(Topology topology) { String topologyId = UUID.randomUUID().toString(); topology.setId(topologyId); save(topology); return topologyId; } public void save(Topology topology) { this.alienDAO.save(topology); } }