/* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.buildServer.server.rest.data.problem; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import jetbrains.buildServer.server.rest.data.*; import jetbrains.buildServer.server.rest.errors.BadRequestException; import jetbrains.buildServer.server.rest.errors.NotFoundException; import jetbrains.buildServer.server.rest.model.PagerData; import jetbrains.buildServer.serverSide.*; import jetbrains.buildServer.serverSide.mute.CurrentMuteInfo; import jetbrains.buildServer.serverSide.mute.ProblemMutingService; import jetbrains.buildServer.tests.TestName; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * @author Yegor.Yarko * Date: 09.11.13 */ public class TestFinder extends AbstractFinder { private static final String NAME = "name"; public static final String AFFECTED_PROJECT = "affectedProject"; private static final String CURRENT = "currentlyFailing"; public static final String CURRENTLY_INVESTIGATED = "currentlyInvestigated"; public static final String CURRENTLY_MUTED = "currentlyMuted"; @NotNull private final ProjectFinder myProjectFinder; @NotNull private final STestManager myTestManager; @NotNull private final TestName2IndexImpl myTestName2Index; //TeamCIty open API issue @NotNull private final CurrentProblemsManager myCurrentProblemsManager; @NotNull private final ProblemMutingService myProblemMutingService; public TestFinder(final @NotNull ProjectFinder projectFinder, final @NotNull STestManager testManager, final @NotNull TestName2IndexImpl testName2Index, final @NotNull CurrentProblemsManager currentProblemsManager, final @NotNull ProblemMutingService problemMutingService) { super(new String[]{DIMENSION_ID, NAME, AFFECTED_PROJECT, CURRENT, CURRENTLY_INVESTIGATED, CURRENTLY_MUTED, PagerData.START, PagerData.COUNT, DIMENSION_LOOKUP_LIMIT, Locator.LOCATOR_SINGLE_VALUE_UNUSED_NAME}); myTestManager = testManager; myProjectFinder = projectFinder; myTestName2Index = testName2Index; myCurrentProblemsManager = currentProblemsManager; myProblemMutingService = problemMutingService; } public static String getTestLocator(final @NotNull STest test) { return getTestLocator(test.getTestNameId()); } public static String getTestLocator(final long testNameId) { return Locator.createEmptyLocator().setDimension(DIMENSION_ID, String.valueOf(testNameId)).getStringRepresentation(); } @Override @Nullable protected STest findSingleItem(@NotNull final Locator locator) { if (locator.isSingleValue()) { // no dimensions found, assume it's id final Long parsedId = locator.getSingleValueAsLong(); if (parsedId == null) { throw new BadRequestException("Expecting id, found empty value."); } STest item = findTest(parsedId); if (item == null) { throw new NotFoundException("No test can be found by id '" + parsedId + "' on the entire server."); } locator.checkLocatorFullyProcessed(); return item; } // dimension-specific item search Long id = locator.getSingleDimensionValueAsLong(DIMENSION_ID); if (id != null) { STest item = findTest(id); if (item == null) { throw new NotFoundException("No test" + " can be found by " + DIMENSION_ID + " '" + id + "' on the entire server."); } return item; } String nameDimension = locator.getSingleDimensionValue(NAME); if (nameDimension != null) { final Long testNameId = myTestName2Index.findTestNameId(new TestName(nameDimension)); if (testNameId == null) { throw new NotFoundException("No test can be found by " + NAME + " '" + nameDimension + "' on the entire server."); } return findTest(testNameId); } return null; } @Override @NotNull public List getAllItems() { //todo: TeamCity API: find a way to do this ArrayList exampleLocators = new ArrayList(); exampleLocators.add(Locator.getStringLocator(DIMENSION_ID, "XXX")); exampleLocators.add(Locator.getStringLocator(NAME, "XXX")); exampleLocators.add(Locator.getStringLocator(CURRENT, "true", AFFECTED_PROJECT, "XXX")); exampleLocators.add(Locator.getStringLocator(CURRENTLY_MUTED, "true", AFFECTED_PROJECT, "XXX")); throw new BadRequestException("Listing all tests is not supported. Try locator dimensions: " + DataProvider.dumpQuoted(exampleLocators)); } @Override protected List getPrefilteredItems(@NotNull final Locator locator) { final SProject affectedProject; String affectedProjectDimension = locator.getSingleDimensionValue(AFFECTED_PROJECT); if (affectedProjectDimension != null) { affectedProject = myProjectFinder.getProject(affectedProjectDimension); }else{ affectedProject = myProjectFinder.getRootProject(); } Boolean currentDimension = locator.getSingleDimensionValueAsBoolean(CURRENT); if (currentDimension != null && currentDimension) { return getCurrentlyFailingTests(affectedProject); } Boolean currentlyMutedDimension = locator.getSingleDimensionValueAsBoolean(CURRENTLY_MUTED); if (currentlyMutedDimension != null && currentlyMutedDimension) { return getCurrentlyMutedTests(affectedProject); } return super.getPrefilteredItems(locator); } List getCurrentlyMutedTests(final SProject affectedProject) { final Map currentMutes = myProblemMutingService.getTestsCurrentMuteInfo(affectedProject); final HashSet result = new HashSet(currentMutes.size()); for (Map.Entry mutedTestData : currentMutes.entrySet()) { result.add(findTest(mutedTestData.getKey())); } return new ArrayList(result); } private List getCurrentlyFailingTests(@NotNull final SProject affectedProject) { final List failingTestOccurrences = TestOccurrenceFinder.getCurrentOccurences(affectedProject, myCurrentProblemsManager); final HashSet result = new HashSet(failingTestOccurrences.size()); for (STestRun testOccurrence : failingTestOccurrences) { result.add(testOccurrence.getTest()); } return new ArrayList(result); } @Override protected AbstractFilter getFilter(final Locator locator) { if (locator.isSingleValue()) { throw new BadRequestException("Single value locator '" + locator.getSingleValue() + "' is not supported for several items query."); } final Long countFromFilter = locator.getSingleDimensionValueAsLong(PagerData.COUNT); final MultiCheckerFilter result = new MultiCheckerFilter(locator.getSingleDimensionValueAsLong(PagerData.START), countFromFilter != null ? countFromFilter.intValue() : null, locator.getSingleDimensionValueAsLong(DIMENSION_LOOKUP_LIMIT)); final String nameDimension = locator.getSingleDimensionValue(NAME); if (nameDimension != null) { result.add(new FilterConditionChecker() { public boolean isIncluded(@NotNull final STest item) { return nameDimension.equals(item.getName().getAsString()); } }); } final Boolean currentlyInvestigatedDimension = locator.getSingleDimensionValueAsBoolean(CURRENTLY_INVESTIGATED); if (currentlyInvestigatedDimension != null) { result.add(new FilterConditionChecker() { public boolean isIncluded(@NotNull final STest item) { //todo: check investigation in affected Project/buildType only, if set return FilterUtil.isIncludedByBooleanFilter(currentlyInvestigatedDimension, !item.getAllResponsibilities().isEmpty()); } }); } final Boolean currentlyMutedDimension = locator.getSingleDimensionValueAsBoolean(CURRENTLY_MUTED); if (currentlyMutedDimension != null) { result.add(new FilterConditionChecker() { public boolean isIncluded(@NotNull final STest item) { //todo: check mute in affected Project/buildType only, if set return FilterUtil.isIncludedByBooleanFilter(currentlyMutedDimension, item.getCurrentMuteInfo() != null); } }); } return result; } @Nullable public STest findTest(final @NotNull Long testNameId) { return myTestManager.findTest(testNameId, myProjectFinder.getRootProject().getProjectId()); //STest in root project should have all the data across entire server } }