package net.thucydides.core.releases; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.gson.Gson; import com.google.gson.GsonBuilder; 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.reports.TestOutcomes; import net.thucydides.core.reports.html.ReportNameProvider; import net.thucydides.core.requirements.RequirementsService; import net.thucydides.core.requirements.RequirementsTagProvider; import net.thucydides.core.requirements.reports.RequirementOutcome; import net.thucydides.core.util.EnvironmentVariables; import org.hamcrest.Matcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import static org.apache.commons.lang3.StringUtils.capitalize; import static org.apache.commons.lang3.StringUtils.lowerCase; import static org.hamcrest.Matchers.containsString; public class ReleaseManager { private final static String DEFAULT_RELEASE_TYPES = "Release,Iteration:Sprint"; private List<String> releaseTypes; private ReportNameProvider reportNameProvider; private RequirementsService requirementsService; private static final Logger LOGGER = LoggerFactory.getLogger(RequirementsTagProvider.class); public ReleaseManager(EnvironmentVariables environmentVariables, ReportNameProvider reportNameProvider) { this.reportNameProvider = reportNameProvider; this.requirementsService = Injectors.getInjector().getInstance(RequirementsService.class); String typeValues = ThucydidesSystemProperty.THUCYDIDES_RELEASE_TYPES.from(environmentVariables, DEFAULT_RELEASE_TYPES); releaseTypes = Splitter.on(",").trimResults().splitToList(typeValues); } public String getJSONReleasesFrom(TestOutcomes testOutcomes) { List<Release> releases = getReleasesFrom(testOutcomes); GsonBuilder builder = new GsonBuilder(); builder.setPrettyPrinting(); Gson gson = builder.create(); return gson.toJson(releases); } public String getJSONReleasesFrom(Release release) { GsonBuilder builder = new GsonBuilder(); builder.setPrettyPrinting(); Gson gson = builder.create(); return gson.toJson(ImmutableList.of(release)); } public List<Release> getFlattenedReleasesFrom(TestOutcomes testOutcomes) { return flattened(getReleasesFrom(testOutcomes)); } private List<Release> flattened(List<Release> releases) { List<Release> flattenedReleases = Lists.newArrayList(); for (Release release : releases) { flattenedReleases.add(release); flattenedReleases.addAll(flattened(release.getChildren())); } return ImmutableList.copyOf(flattenedReleases); } List<Release> NO_PARENTS = ImmutableList.of(); public List<Release> getReleasesFrom(TestOutcomes testOutcomes) { List<Release> releases = requirementsService.getReleasesFromRequirements(); LOGGER.debug("Loaded Releases: " + releases); enrichOutcomesWithReleaseTags(testOutcomes.getOutcomes()); if (releases.isEmpty()) { releases = extractReleasesFromTestOutcomeAnnotations(testOutcomes); } return ImmutableList.copyOf(releases); } private List<Release> extractReleasesFromTestOutcomeAnnotations(TestOutcomes testOutcomes) { List<Release> releases = Lists.newArrayList(); List<TestTag> releaseTags = testOutcomes.findMatchingTags() .withType("version") .withNameIn(matchingNames(releaseTypes.get(0))) .list(); for (TestTag tag : releaseTags) { releases.add(extractReleaseFor(tag, testOutcomes.withTag(tag), 1, NO_PARENTS)); } return releases; } private List<Matcher<String>> matchingNames(String possibleNames) { List<Matcher<String>> matchers = Lists.newArrayList(); List<String> nameCandidates = Splitter.on(":").trimResults().splitToList(possibleNames.toLowerCase()); for(String nameCandidate : nameCandidates) { matchers.add((containsString(nameCandidate))); matchers.add((containsString(capitalize(nameCandidate)))); matchers.add((containsString(lowerCase(nameCandidate)))); } return matchers; } public List<RequirementOutcome> enrichRequirementsOutcomesWithReleaseTags(List<? extends RequirementOutcome> outcomes) { List<RequirementOutcome> requirementOutcomes = Lists.newArrayList(); for (RequirementOutcome outcome : outcomes) { List<TestOutcome> enrichedOutcomes = enrichOutcomesWithReleaseTags(outcome.getTestOutcomes().getOutcomes()); requirementOutcomes.add(outcome.withTestOutcomes(TestOutcomes.of(enrichedOutcomes))); } return requirementOutcomes; } public List<TestOutcome> enrichOutcomesWithReleaseTags(List<? extends TestOutcome> outcomes) { List<TestOutcome> enrichedOutcomes = Lists.newArrayList(); for (TestOutcome outcome : outcomes) { List<String> releaseVersions = requirementsService.getReleaseVersionsFor(outcome); outcome.addTags(releaseTagsFrom(releaseVersions)); outcome.addVersions(releaseVersions); enrichedOutcomes.add(outcome); } return enrichedOutcomes; } private List<TestTag> releaseTagsFrom(List<String> releaseVersions) { List<TestTag> tags = Lists.newArrayList(); for (String releaseVersion : releaseVersions) { tags.add(TestTag.withName(releaseVersion).andType("version")); } return tags; } private Release extractReleaseFor(TestTag releaseTag, TestOutcomes testOutcomes, int level, List<Release> parents) { Release release = new Release(releaseTag); String reportName = reportNameProvider.forRelease(release); release = release.withReport(reportName).withParents(parents); List<Release> ancestors = ancestorsFor(release); if (level < releaseTypes.size()) { String childReleaseType = releaseTypes.get(level); List<TestTag> childReleaseTags = testOutcomes.findMatchingTags() .withType("version") .withNameIn(matchingNames(childReleaseType)) .list(); List<Release> children = Lists.newArrayList(); for (TestTag tag : childReleaseTags) { children.add(extractReleaseFor(tag, testOutcomes.withTag(tag), level + 1, ancestors)); } release = release.withChildren(children); } return release; } private List<Release> ancestorsFor(Release release) { List<Release> ancestors = new ArrayList<Release>(release.getParents()); ancestors.add(release); return ancestors; } public List<Release> extractReleasesFrom(List<List<String>> releaseVersions) { return extractReleasesOfTypeLevel(releaseVersions); } private ReportNameProvider defaultNameProvider; private ReportNameProvider getReportNameProvider() { if (defaultNameProvider == null) { defaultNameProvider = new ReportNameProvider(); } return defaultNameProvider; } private List<Release> extractReleasesOfTypeLevel(List<List<String>> releaseVersions) { List<Release> releases = Lists.newArrayList(); Set<String> distinctReleases = getDistinct(releaseVersions); for (String release : distinctReleases) { if (releaseIsOfType(release, releaseTypes.get(0))) { List<Release> subReleases = extractSubReleasesOfLevel(releaseVersions, release, 1, Collections.EMPTY_LIST); String reportName = getReportNameProvider().forRelease(release); addUniqueRelease(releases, Release.ofVersion(release) .withChildren(subReleases) .withReport(reportName)); } } Collections.sort(releases); return releases; } private boolean releaseIsOfType(String release, String releaseTypes) { for(Matcher matcher : matchingNames(releaseTypes)) { if (matcher.matches(release.toLowerCase())) { return true; } } return false; } private void addUniqueRelease(List<Release> releases, Release release) { if (!containsReleaseWithName(releases,release.getName())) releases.add(release); } private boolean containsReleaseWithName(List<Release> releases, String name) { for(Release release : releases) { if (release.getName().equalsIgnoreCase(name)) { return true; } } return false; } private List<Release> extractSubReleasesOfLevel(List<List<String>> releaseVersions, String release, int level, List<Release> parents) { List<Release> subReleases = Lists.newArrayList(); if (level < releaseTypes.size()) { for (List<String> releaseVersionSet : releaseVersions) { if (releaseVersionSet.contains(release)) { for (String subRelease : releasesOfType(releaseTypes.get(level), releaseVersionSet)) { List<Release> ancestors = Lists.newArrayList(); ancestors.add(lightweightReleaseNamed(release)); List<Release> subSubReleases = extractSubReleasesOfLevel(releaseVersions, subRelease, level + 1, ancestors); String reportName = getReportNameProvider().forRelease(subRelease); addUniqueRelease(subReleases, Release.ofVersion(subRelease).withChildren(subSubReleases) .withReport(reportName) .withParents(ancestors)); } } } } Collections.sort(subReleases); return subReleases; } private Release lightweightReleaseNamed(String release) { return Release.ofVersion(release).withReport(reportNameProvider.forRelease(release)); } private List<String> releasesOfType(String type, List<String> releaseVersionSet) { List<String> matchingReleases = Lists.newArrayList(); for (String release : releaseVersionSet) { if (releaseIsOfType(release, type)) { matchingReleases.add(release); } } return matchingReleases; } private Set<String> getDistinct(List<List<String>> releaseVersions) { Set<String> distinctVersions = Sets.newHashSet(); for (List<String> releaseVersionSets : releaseVersions) { distinctVersions.addAll(releaseVersionSets); } return distinctVersions; } }