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);
}
}