class DriverInjection {

    public static TTopologyTemplate injectDriver(TTopologyTemplate topologyTemplate) throws Exception {

        List<TNodeTemplate> nodeTemplatesWithAbstractDA = DASpecification.getNodeTemplatesWithAbstractDAs(topologyTemplate);

        for (TNodeTemplate nodeTemplateWithAbstractDA : nodeTemplatesWithAbstractDA) {
            List<TDeploymentArtifact> abstractDAsAttachedToNodeTemplate = nodeTemplateWithAbstractDA.getDeploymentArtifacts().getDeploymentArtifact().stream()
                .filter(da -> DASpecification.getArtifactTypeOfDA(da).getAbstract() == TBoolean.YES)
                .collect(Collectors.toList());
            for (TDeploymentArtifact abstractDA : abstractDAsAttachedToNodeTemplate) {
                Map<TRelationshipTemplate, TNodeTemplate> nodeTemplatesWithConcreteDA = DASpecification.getNodesWithSuitableConcreteDAAndTheDirectlyConnectedNode(nodeTemplateWithAbstractDA, abstractDA, topologyTemplate);

                if (nodeTemplatesWithConcreteDA != null) {
                    for (TRelationshipTemplate relationshipTemplate : nodeTemplatesWithConcreteDA.keySet()) {
                        TDeploymentArtifact concreteDeploymentArtifact = DASpecification.getSuitableConcreteDA(abstractDA, nodeTemplatesWithConcreteDA.get(relationshipTemplate));
                        nodeTemplateWithAbstractDA.getDeploymentArtifacts().getDeploymentArtifact().add(concreteDeploymentArtifact);
                        setDriverProperty(relationshipTemplate, concreteDeploymentArtifact);
                    }
                    //concrete DAs from the delivering Node Template must not be deleted. They are uploaded by the OpenTOSCA Container but not used.
                    nodeTemplateWithAbstractDA.getDeploymentArtifacts().getDeploymentArtifact().remove(abstractDA);
                } else {
                    throw new WineryRepositoryException("No concrete DA found for the abstract DA");
                }
            }
        }
        return topologyTemplate;
    }

}