public ItemFilter getFilter()

in rest-api/src/jetbrains/buildServer/server/rest/data/finder/impl/ChangeFinder.java [260:430]


  public ItemFilter<SVcsModificationOrChangeDescriptor> getFilter(@NotNull final Locator locator) {
    final MultiCheckerFilter<SVcsModification> result = new MultiCheckerFilter<>();

    //myBuildType, myProject and myBranchName are handled on getting initial collection to filter

    final String vcsRootInstanceLocator = locator.getSingleDimensionValue(VCS_ROOT_INSTANCE);
    if (vcsRootInstanceLocator != null) {
      final VcsRootInstance vcsRootInstance = myVcsRootInstanceFinder.getItem(vcsRootInstanceLocator);
      result.add(item -> {
        return !item.isPersonal() && vcsRootInstance.getId() == item.getVcsRoot().getId(); //todo: check personal change applicability to the root
      });
    }

    final String vcsRootLocator = locator.getSingleDimensionValue(VCS_ROOT);
    if (vcsRootLocator != null) {
      final VcsRoot vcsRoot = myVcsRootFinder.getItem(vcsRootLocator);
      //todo: check personal change applicability to the root
      result.add(item -> !item.isPersonal() && vcsRoot.getId() == item.getVcsRoot().getParent().getId());
    }

    final String sinceChangeLocator = locator.getSingleDimensionValue(SINCE_CHANGE); //todo: deprecate this
    if (sinceChangeLocator != null) {
      final long sinceChangeId = getChangeIdBySinceChangeLocator(sinceChangeLocator);
      result.add(item -> sinceChangeId < item.getId());
    }

    if (locator.isUnused(USERNAME)) {
      final String username = locator.getSingleDimensionValue(USERNAME);
      if (username != null) {
        //todo: is ignoreCase is right here?
        result.add(item -> username.equalsIgnoreCase(item.getUserName()));
      }
    }

    if (locator.isUnused(USER)) {
      final String userLocator = locator.getSingleDimensionValue(USER);
      if (userLocator != null) {
        final SUser user = myUserFinder.getItem(userLocator);
        result.add(item -> item.getCommitters().contains(user));
      }
    }

    //TeamCity API: exclude "fake" personal changes created by TeamCity for personal builds without personal changes
    result.add(item -> !item.isPersonal() || item.getChanges().size() > 0);

    final Boolean personal = locator.getSingleDimensionValueAsBoolean(PERSONAL);
    if (personal != null) {
      result.add(item -> FilterUtil.isIncludedByBooleanFilter(personal, item.isPersonal()));
    }

    if (personal != null && personal) {
      //initial collection can contain changes from any buildType/project
      final String buildTypeLocator = locator.getSingleDimensionValue(BUILD_TYPE);
      if (buildTypeLocator != null) {
        final SBuildType buildType = myBuildTypeFinder.getBuildType(null, buildTypeLocator, false);
        result.add(item -> isPersonalChangeMatchesBuildType(item, buildType));
      }
    }

    if (locator.getUnusedDimensions().contains(BUILD)) {
      final String buildLocator = locator.getSingleDimensionValue(BUILD);
      if (buildLocator != null) {
        final Set<Long> buildChanges = getBuildChangeDescriptors(myBuildFinder.getBuildPromotion(null, buildLocator), locator)
          .map(mord -> mord.getRelatedVcsChange().getId())
          .collect(Collectors.toSet());
        result.add(item -> buildChanges.contains(item.getId()));
      }
    }

    //pre-9.0 dimension compatibility
    if (locator.getUnusedDimensions().contains(PROMOTION)) {
      final Long promotionLocator = locator.getSingleDimensionValueAsLong(PROMOTION);
      if (promotionLocator != null) {
        @SuppressWarnings("ConstantConditions") final Set<Long> buildChanges =
          getBuildChangeDescriptors(myBuildPromotionFinder.getBuildPromotion(promotionLocator), null)
            .map(mord -> mord.getRelatedVcsChange().getId()).collect(Collectors.toSet());
        result.add(item -> buildChanges.contains(item.getId()));
      }
    }

    if (locator.isUnused(BUILD_TYPE)) {
      final String buildTypeLocator = locator.getSingleDimensionValue(BUILD_TYPE); //todo: support multiple buildTypes here
      if (buildTypeLocator != null) {
        SBuildType buildType = myBuildTypeFinder.getBuildType(null, buildTypeLocator, false);

        //todo: this does not include "show changes from dependencies", relates to https://youtrack.jetbrains.com/issue/TW-63704
        result.add(item -> ((VcsModificationEx)item).isRelatedTo(buildType));
      }
    }

    final String projectLocator = locator.getSingleDimensionValue(PROJECT);
    if (projectLocator != null) {
      final SProject project = myProjectFinder.getItem(projectLocator);
      result.add(getInBuildTypesListChecker(project.getOwnBuildTypes().stream()));
    }

    final String affectedProjectLocator = locator.getSingleDimensionValue(AFFECTED_PROJECT);
    if (affectedProjectLocator != null) {
      final SProject affectedProject = myProjectFinder.getItem(affectedProjectLocator);
      result.add(getInBuildTypesListChecker(affectedProject.getBuildTypes().stream()));
    }

    if (locator.isUnused(INTERNAL_VERSION)) {
      final String internalVersion = locator.getSingleDimensionValue(INTERNAL_VERSION);
      if (internalVersion != null) {
        result.add(item -> internalVersion.equals(item.getVersion()));
      }
    }

    if (locator.isUnused(VERSION)) {
      final String displayVersion = locator.getSingleDimensionValue(VERSION);
      ValueCondition condition = ParameterCondition.createValueCondition(displayVersion);
      if (displayVersion != null) {
        result.add(item -> condition.matches(item.getDisplayVersion()));
      }
    }

    final String commentLocatorText = locator.getSingleDimensionValue(COMMENT);
    if (commentLocatorText != null) {
      final String containsText = new Locator(commentLocatorText).getSingleDimensionValue("contains");
      // Preserve legacy behaviour
      if (containsText != null) {
        result.add(item -> item.getDescription().contains(containsText));
        //todo: check unprocessed dimensions
      } else {
        ValueCondition condition = ParameterCondition.createValueCondition(commentLocatorText);
        result.add(item -> condition.matches(item.getDescription()));
      }
    }

    if (locator.getUnusedDimensions().contains(PENDING)) {
      final Boolean pending = locator.getSingleDimensionValueAsBoolean(PENDING);
      if (pending != null) {
        final String buildTypeLocator = locator.getSingleDimensionValue(BUILD_TYPE); //todo: support multiple buildTypes here
        final SBuildType buildType = buildTypeLocator == null ? null : myBuildTypeFinder.getBuildType(null, buildTypeLocator, false);
        final Set<SVcsModification> pendingChanges = getPendingChanges(buildType, locator).map(mcd -> mcd.getSVcsModification()).collect(Collectors.toSet());
        result.add(item -> FilterUtil.isIncludedByBooleanFilter(pending, pendingChanges.contains(item)));
      }
    }

    final String fileLocator = locator.getSingleDimensionValue(FILE);
    if (fileLocator != null) {
      final String pathLocatorText = new Locator(fileLocator).getSingleDimensionValue("path"); //todo: use conditions here
      //todo: check unknown locator dimensions
      if (pathLocatorText != null) {
        final String containsText = new Locator(pathLocatorText).getSingleDimensionValue("contains");
        if (containsText != null) {
          result.add(item -> item.getChanges().stream().anyMatch(vcsFileModification -> vcsFileModification.getFileName().contains(containsText)));
          //todo: check unknown locator dimensions
        } else {
          ValueCondition condition = ParameterCondition.createValueCondition(pathLocatorText);
          result.add(item -> item.getChanges().stream().map(m -> m.getFileName()).anyMatch(condition::matches));
        }
      }
    }

    // See FinderImp.getItemsByLocator(..) and this.createDuplicateChecker(..) for implementation details.
    boolean deduplicate = locator.getSingleDimensionValueAsStrictBoolean(DIMENSION_UNIQUE, locator.isAnyPresent(DIMENSION_ITEM));
    if (deduplicate) {
      final KeyDuplicateChecker<SVcsModification, String> checker = new KeyDuplicateChecker<>(m -> m.getVersion());
      result.add(item -> !checker.checkDuplicateAndRemember(item));
    }

    // include by build should be already handled by this time on the upper level

    if (TeamCityProperties.getBoolean("rest.request.changes.check.enforceChangeViewPermission")) {
      result.add(myPermissionChecker::checkCanView);
    }

    return new UnwrappingFilter<>(result.toItemFilter(), SVcsModificationOrChangeDescriptor::getSVcsModification);
  }