All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.thucydides.core.requirements.RequirementsServiceImplementation Maven / Gradle / Ivy

There is a newer version: 4.2.1
Show newest version
package net.thucydides.core.requirements;

import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import net.thucydides.core.ThucydidesSystemProperty;
import net.thucydides.core.guice.Injectors;
import net.thucydides.core.model.Release;
import net.thucydides.core.model.TestOutcome;
import net.thucydides.core.model.TestTag;
import net.thucydides.core.releases.ReleaseManager;
import net.thucydides.core.reports.html.ReportNameProvider;
import net.thucydides.core.requirements.model.Requirement;
import net.thucydides.core.statistics.service.AnnotationBasedTagProvider;
import net.thucydides.core.statistics.service.FeatureStoryTagProvider;
import net.thucydides.core.util.EnvironmentVariables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.google.common.collect.Lists.newArrayList;
import static java.util.Collections.EMPTY_LIST;

public class RequirementsServiceImplementation implements RequirementsService {

    private List requirementsTagProviders;
    private List requirements;
    private List releases;
    private Map> requirementAncestors;
    private final EnvironmentVariables environmentVariables;

    private static final Logger LOGGER = LoggerFactory.getLogger(RequirementsTagProvider.class);

    private static final List NO_REQUIREMENTS = Lists.newArrayList();

    private static final List LOW_PRIORITY_PROVIDERS =
            ImmutableList.of(FileSystemRequirementsTagProvider.class.getCanonicalName(),
                             PackageAnnotationBasedTagProvider.class.getCanonicalName(),
                             AnnotationBasedTagProvider.class.getCanonicalName(),
                             FeatureStoryTagProvider.class.getCanonicalName()
                             );

    public RequirementsServiceImplementation() {
        environmentVariables = Injectors.getInjector().getProvider(EnvironmentVariables.class).get() ;
    }

    @Override
    public List getRequirements() {
        RequirementsMerger merger = new RequirementsMerger();

        if (requirements == null) {
            requirements = newArrayList();
            for (RequirementsTagProvider tagProvider : getRequirementsTagProviders()) {
                LOGGER.debug("Reading requirements from " + tagProvider);
                List newRequirements = tagProvider.getRequirements();
                requirements = merger.merge(requirements, newRequirements);
            }
            requirements = addParentsTo(requirements);
            indexRequirements();
            LOGGER.debug("Requirements found:" + requirements);
        }
        return requirements;
    }

    private List addParentsTo(List requirements) {
        return addParentsTo(requirements, null);
    }

    private List addParentsTo(List requirements, String parent) {
        List augmentedRequirements = Lists.newArrayList();
        for(Requirement requirement : requirements) {
            List children = requirement.hasChildren()
                    ? addParentsTo(requirement.getChildren(),requirement.getName()) : NO_REQUIREMENTS;
            augmentedRequirements.add(requirement.withParent(parent).withChildren(children));
        }
        return augmentedRequirements;
    }


    private void indexRequirements() {
        requirementAncestors = Maps.newHashMap();
        for (Requirement requirement : requirements) {
            List requirementPath = ImmutableList.of(requirement);
            requirementAncestors.put(requirement, ImmutableList.of(requirement));
            LOGGER.debug("Requirement ancestors for:" + requirement + " = " + requirementPath);
            indexChildRequirements(requirementPath, requirement.getChildren());
        }
    }

    ReleaseManager releaseManager;

    private ReleaseManager getReleaseManager() {
        if (releaseManager == null) {
            ReportNameProvider defaultNameProvider = new ReportNameProvider();
            releaseManager = new ReleaseManager(environmentVariables, defaultNameProvider);
        }
        return releaseManager;
    }


    private Map> getRequirementAncestors() {
        if (requirementAncestors == null) {
            getRequirements();
        }
        return requirementAncestors;
    }

    private void indexChildRequirements(List ancestors, List children) {
        for (Requirement requirement : children) {
            List requirementPath = newArrayList(ancestors);
            requirementPath.add(requirement);
            requirementAncestors.put(requirement, ImmutableList.copyOf(requirementPath));
            LOGGER.debug("Requirement ancestors for:" + requirement + " = " + requirementPath);
            indexChildRequirements(requirementPath, requirement.getChildren());
        }
    }


    @Override
    public Optional getParentRequirementFor(TestOutcome testOutcome) {

        try {
            for (RequirementsTagProvider tagProvider : getRequirementsTagProviders()) {
                Optional requirement = getParentRequirementOf(testOutcome, tagProvider);
                if (requirement.isPresent()) {
                    return requirement;
                }
            }
        } catch (RuntimeException handleTagProvidersElegantly) {
            LOGGER.error("Tag provider failure", handleTagProvidersElegantly);
        }
        return Optional.absent();
    }


    @Override
    public Optional getRequirementFor(TestTag tag) {

        try {
            for (RequirementsTagProvider tagProvider : getRequirementsTagProviders()) {
                Optional requirement = tagProvider.getRequirementFor(tag);
                if (requirement.isPresent()) {
                    return requirement;
                }
            }
        } catch (RuntimeException handleTagProvidersElegantly) {
            LOGGER.error("Tag provider failure", handleTagProvidersElegantly);
        }
        return Optional.absent();
    }

    @Override
    public boolean isRequirementsTag(TestTag tag) {
        return getRequirementTypes().contains(tag.getType());
    }

    @Override
    public List getAncestorRequirementsFor(TestOutcome testOutcome) {
        for (RequirementsTagProvider tagProvider : getRequirementsTagProviders()) {
            Optional requirement = getParentRequirementOf(testOutcome, tagProvider);
            if (requirement.isPresent()) {
                LOGGER.debug("Requirement found for test outcome " + testOutcome.getTitle() + "-" + testOutcome.getIssueKeys() + ": " + requirement);
                if (getRequirementAncestors().containsKey(requirement.get())) {
                    return getRequirementAncestors().get(requirement.get());
                } else {
                    LOGGER.warn("Requirement without identified ancestors found:" + requirement.get().getCardNumber());
                }
            }
        }
        return EMPTY_LIST;
    }

    Map> requirementCache = Maps.newConcurrentMap();

    private Optional getParentRequirementOf(TestOutcome testOutcome, RequirementsTagProvider tagProvider) {
        if (requirementCache.containsKey(testOutcome)) {
            return requirementCache.get(testOutcome);
        } else {
            Optional parentRequirement = findMatchingIndexedRequirement(tagProvider.getParentRequirementOf(testOutcome));
            requirementCache.put(testOutcome, parentRequirement);
            return parentRequirement;
        }
    }

    private Optional findMatchingIndexedRequirement(Optional requirement) {
        if (!requirement.isPresent()) {
            return requirement;
        }
        for(Requirement indexedRequirement : getAllRequirements()) {
            if (requirement.get().matches(indexedRequirement)) {
                return Optional.of(indexedRequirement);
            }
        }
        return Optional.absent();
    }

    @Override
    public List getReleaseVersionsFor(TestOutcome testOutcome) {
        List releases = newArrayList(testOutcome.getVersions());
        for (Requirement parentRequirement : getAncestorRequirementsFor(testOutcome)) {
            releases.addAll(parentRequirement.getReleaseVersions());
        }
        return releases;
    }

    @Override
    public List getReleasesFromRequirements() {
        if (releases == null) {
            if (getReleaseProvider().isPresent() && (getReleaseProvider().get().isActive())) {
                releases = getReleaseProvider().get().getReleases();
            } else {
                List> releaseVersions = getReleaseVersionsFrom(getRequirements());
                releases = getReleaseManager().extractReleasesFrom(releaseVersions);
            }
        }
        return releases;
    }

    private Optional getReleaseProvider() {
        List requirementsTagProviders = getRequirementsTagProviders();
        for (RequirementsTagProvider provider : requirementsTagProviders) {
            if ((provider instanceof ReleaseProvider) && ((ReleaseProvider) provider).isActive()) {
                return Optional.of((ReleaseProvider) provider);
            }
        }
        return Optional.absent();
    }

    @Override
    public List getRequirementTypes() {
        Set requirementTypes = Sets.newHashSet();
        for(Requirement requirement : getAllRequirements()) {
            requirementTypes.add(requirement.getType());
        }
        return ImmutableList.copyOf(requirementTypes);
    }

    private List> getReleaseVersionsFrom(List requirements) {
        List> releaseVersions = newArrayList();
        for (Requirement requirement : requirements) {
            releaseVersions.add(requirement.getReleaseVersions());
            releaseVersions.addAll(getReleaseVersionsFrom(requirement.getChildren()));
        }
        return releaseVersions;
    }

    private List getRequirementsTagProviders() {
        if (requirementsTagProviders == null) {
            RequirementsProviderService requirementsProviderService = Injectors.getInjector().getInstance(RequirementsProviderService.class);
            requirementsTagProviders = reprioritizeProviders(active(requirementsProviderService.getRequirementsProviders()));
        }
        return requirementsTagProviders;
    }

    private List active(List requirementsProviders) {
        boolean useDirectoryBasedRequirements =
                ThucydidesSystemProperty.THUCYDIDES_USE_REQUIREMENTS_DIRECTORIES.booleanFrom(environmentVariables, true);

        if (useDirectoryBasedRequirements) {
            return requirementsProviders;
        } else {
            List activeRequirementsProviders = newArrayList();
            for (RequirementsTagProvider provider : requirementsProviders) {
                if (!(provider instanceof FileSystemRequirementsTagProvider)) {
                    activeRequirementsProviders.add(provider);
                }
            }
            return activeRequirementsProviders;
        }
    }

    private List reprioritizeProviders(List requirementsTagProviders) {
        Map lowPriorityProviders = Maps.newHashMap();
        List prioritizedProviders = newArrayList();

        for (RequirementsTagProvider provider : requirementsTagProviders) {
            if (LOW_PRIORITY_PROVIDERS.contains(provider.getClass().getCanonicalName())) {
                lowPriorityProviders.put(provider.getClass().getCanonicalName(), provider);
            } else {
                prioritizedProviders.add(provider);
            }
        }
        addLowPriorityProviders(lowPriorityProviders, prioritizedProviders);
        return prioritizedProviders;
    }

    private void addLowPriorityProviders(Map lowPriorityProviders, List prioritizedProviders) {
        for(String lowPriorityProvider : LOW_PRIORITY_PROVIDERS) {
            if (lowPriorityProviders.containsKey(lowPriorityProvider)) {
                prioritizedProviders.add(lowPriorityProviders.get(lowPriorityProvider));
            }
        }
    }

    public List getAllRequirements() {
        List allRequirements = newArrayList();
        addRequirementsFrom(getRequirements(), allRequirements);
        return allRequirements;
    }

    private void addRequirementsFrom(List requirements, List allRequirements) {
        allRequirements.addAll(requirements);
        for (Requirement requirement : requirements) {
            addRequirementsFrom(requirement.getChildren(), allRequirements);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy