public ItemFilter getFilter()

in rest-api/src/jetbrains/buildServer/server/rest/data/finder/impl/BuildPromotionFinder.java [364:814]


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

    //checking permissions to view - workaround for TW-45544
    result.add(item -> {
      try {
        ensureCanView(item);
        return true;
      } catch (AccessDeniedException e) {
        return false; //excluding from the lists as secure wrappers usually do
      }
    });

    if (locator.isSingleValue()) {
      try {
        long foundPromotionId = getBuildPromotionByIdOrByBuildId(locator.getSingleValueAsLong()).getId();
        result.add(item -> foundPromotionId == item.getId());
      } catch (NotFoundException e) {
        result.add(item -> false);
      }
    }

    if (locator.isUnused(DEFAULT_FILTERING)) {
      //basically, mark as used if it is not yet processed, but is unset or is set to false
      final Boolean defaultFiltering = locator.getSingleDimensionValueAsBoolean(DEFAULT_FILTERING);
      if (defaultFiltering != null && defaultFiltering) {
        locator.markUnused(DEFAULT_FILTERING);
      }
    }

    final Long id = locator.getSingleDimensionValueAsLong(DIMENSION_ID);
    if (id != null) {
      try {
        long foundPromotionId = getBuildPromotionByIdOrByBuildId(id).getId();
        result.add(item -> foundPromotionId == item.getId());
      } catch (NotFoundException e) {
        result.add(item -> false);
      }
    }
    final Long promotionId = locator.getSingleDimensionValueAsLong(PROMOTION_ID);
    if (promotionId != null) {
      try {
        long foundPromotionId = getBuildPromotion(promotionId).getId();
        result.add(item -> foundPromotionId == item.getId());
      } catch (NotFoundException e) {
        result.add(item -> false);
      }
    }
    final Long promotionIdAlias = locator.getSingleDimensionValueAsLong(PROMOTION_ID_ALIAS);
    if (promotionIdAlias != null) {
      try {
        long foundPromotionId = getBuildPromotion(promotionIdAlias).getId();
        result.add(item -> foundPromotionId == item.getId());
      } catch (NotFoundException e) {
        result.add(item -> false);
      }
    }
    final Long buildId = locator.getSingleDimensionValueAsLong(BUILD_ID);
    if (buildId != null) {
      result.add(item -> buildId.equals(item.getAssociatedBuildId()));
    }

    Locator stateLocator = getStateLocator(locator);

    if (!isStateIncluded(stateLocator, STATE_QUEUED)) {
      result.add(item -> item.getQueuedBuild() == null);
    }

    if (!isStateIncluded(stateLocator, STATE_RUNNING)) {
      result.add(item -> {
        final SBuild associatedBuild = item.getAssociatedBuild();
        return associatedBuild == null || associatedBuild.isFinished();
      });
    }

    if (!isStateIncluded(stateLocator, STATE_FINISHED)) {
      result.add(item -> {
        final SBuild associatedBuild = item.getAssociatedBuild();
        return associatedBuild == null || !associatedBuild.isFinished();
      });
    }

    final Boolean composite = locator.getSingleDimensionValueAsBoolean(COMPOSITE);
    if (composite != null) {
      result.add(item -> FilterUtil.isIncludedByBooleanFilter(composite, item.isCompositeBuild()));
    }

    if (locator.isUnused(PROJECT)) {
      SProject project = getProjectFromDimension(locator, PROJECT);
      if (project != null) {
        result.add(item -> {
          final SBuildType buildType = item.getBuildType();
          return buildType != null && project.equals(buildType.getProject());
        });
      }
    }

    if (locator.isUnused(AFFECTED_PROJECT)) {
      SProject affectedProject = getProjectFromDimension(locator, AFFECTED_PROJECT);
      if (affectedProject != null && !affectedProject.isRootProject()) {
        result.add(item -> {
          final SBuildType buildType = item.getBuildType();
          return buildType != null && ProjectFinder.isSameOrParent(affectedProject, buildType.getProject());
        });
      }
    }

    if (locator.isUnused(BUILD_TYPE)) {
      final String buildTypeLocator = locator.getSingleDimensionValue(BUILD_TYPE);
      if (buildTypeLocator != null) {
        final Set<SBuildType> buildTypes = new HashSet<>(myBuildTypeFinder.getBuildTypes(getProjectFromDimension(locator, PROJECT), buildTypeLocator));
        if (buildTypes.isEmpty()) {
          throw new NotFoundException("No build types found for locator '" + buildTypeLocator + "'");
        }
        //todo: use build types Filter instead
        result.add(item -> buildTypes.contains(item.getParentBuildType()));
      }
    }

    final String branchLocatorValue = locator.getSingleDimensionValue(BRANCH);
    if (branchLocatorValue != null) {
      PagedSearchResult<? extends Branch> branches = null;
      BadRequestException exceptionOnFullSearch = null;
      try {
        branches = myBranchFinder.getItemsIfValidBranchListLocator(locator.lookupSingleDimensionValue(BUILD_TYPE), branchLocatorValue);
      } catch (BadRequestException e) {
        // not a valid branches listing locator
        exceptionOnFullSearch = e;
      }
      if (branches != null) {
        //branches found - use them
        Set<String> branchNames = getBranchNamesSet(branches.getEntries());
        Set<String> branchDisplayNames = getBranchDisplayNamesSet(branches.getEntries());
        boolean defaultBranchIncluded = branches.getEntries().stream().anyMatch(Branch::isDefaultBranch);
        result.add(item -> {
            final Branch buildBranch = BranchData.fromBuild(item);
            return (defaultBranchIncluded && buildBranch.isDefaultBranch()) || branchNames.contains(buildBranch.getName()) || branchDisplayNames.contains(buildBranch.getDisplayName());
        });
      } else {
        //branches not found by locator - try to use filter
        BranchFinder.BranchFilterDetails branchFilterDetails;
        try {
          branchFilterDetails = myBranchFinder.getBranchFilterDetails(branchLocatorValue);
        } catch (LocatorProcessException locatorException) {
          throw new BadRequestException("Invalid sub-locator '" + BRANCH + "': Cannot" +
                                        (exceptionOnFullSearch != null ? " find branches: " + exceptionOnFullSearch.getMessage() +"; and cannot" : "") +
                                        " create filter: " + locatorException.getMessage(), locatorException);
        }
        if (!branchFilterDetails.isAnyBranch()) {
          result.add(item -> branchFilterDetails.isIncluded(item));
        }
      }
    }

    final Boolean branched = locator.getSingleDimensionValueAsBoolean(BRANCHED);
    if (branched != null) {
      result.add(item -> FilterUtil.isIncludedByBooleanFilter(branched, item.getBranch() != null));
    }

    if (locator.isUnused(AGENT)) {
      final String agentLocator = locator.getSingleDimensionValue(AGENT);
      if (agentLocator != null) {
        Set<Integer> agentIds = myAgentFinder.getItemsNotEmpty(agentLocator).getEntries().stream().map(agent -> agent.getId()).filter(i -> i != Agent.UNKNOWN_AGENT_ID).collect(Collectors.toSet());
        result.add(item -> {
          final SQueuedBuild queuedBuild = item.getQueuedBuild(); //for queued build using compatible agents
          if (queuedBuild != null) {
            return queuedBuild.getCanRunOnAgents().stream().anyMatch(agent -> agentIds.contains(agent.getId()));
          }

          final SBuild build = item.getAssociatedBuild();
          if (build != null) {
            return agentIds.contains(build.getAgent().getId());
          }
          return false;
        });
      }
    }

    //compatibility support
    final String tags = locator.getSingleDimensionValue(TAGS);
    if (tags != null) {
      final List<String> tagsList = Arrays.asList(tags.split(","));
      if (tagsList.size() > 0) {
        result.add(item -> item.getTags().containsAll(tagsList));
      }
    }

    if(locator.isUnused(TAG)) {
      result.add(getFilterByTag(locator.getDimensionValue(TAG)));
    }

    final String compatibleAgentLocator = locator.getSingleDimensionValue(COMPATIBLE_AGENT);
    if (compatibleAgentLocator != null) {
      List<SBuildAgent> agents = myAgentFinder.getItems(compatibleAgentLocator).getEntries();
      result.add(build -> agents.stream().anyMatch(agent -> myAgentFinder.canActuallyRun(agent, build)));
    }

    final Long compatibleAgentsCount = locator.getSingleDimensionValueAsLong(COMPATIBLE_AGENTS_COUNT); //experimental, only for queued builds
    if (compatibleAgentsCount != null) {
      result.add(item -> {
          long count = 0;
          for (SBuildAgent agent : myAgentFinder.getItems(null).getEntries()) { //or should process unauthorized as well?
            if (myAgentFinder.canActuallyRun(agent, item)) count++;
            if (count > compatibleAgentsCount) return false;
          }
          return count == compatibleAgentsCount;
      });
    }

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

    final Boolean history = locator.getSingleDimensionValueAsBoolean(HISTORY);
    if (history != null) {
      result.add(item -> FilterUtil.isIncludedByBooleanFilter(history, item.isOutOfChangesSequence()));
    }

    final String userDimension = locator.getSingleDimensionValue(USER);
    if (userDimension != null) {
      final SUser user = myUserFinder.getItem(userDimension);
      result.add(item -> {
          SUser owner = item.getOwner();
          if (owner != null) {
            // if owner is present, consider only it: this is consistent with the builds search in the prefiltering
            return user.getId() == owner.getId();
          }
          SUser actualUser = Util.resolveNull(getTriggeredBy(item), TriggeredBy::getUser);
          return actualUser != null && user.getId() == actualUser.getId();
      });
    }

    final String triggeredDimension = locator.getSingleDimensionValue(TRIGGERED);
    if (triggeredDimension != null) {
      final ItemFilter<TriggeredBy> filter = myTriggerByFinder.getFilter(triggeredDimension);
      result.add(item -> Util.resolveNull(getTriggeredBy(item), filter::isIncluded, false));
    }

    final List<String> properties = locator.getDimensionValue(CommonLocatorDimensionsList.PROPERTY);
    if (!properties.isEmpty()) {
      final Matcher<ParametersProvider> parameterCondition = ParameterCondition.create(properties);
      result.add(item -> {
          if (!Build.canViewRuntimeData(myPermissionChecker, item)) return false;
          //does not correspond to Build.getProperties() which includes less parameters
          return parameterCondition.matches(BuildParametersUtil.getResultingParameters(item)); //TeamCity open API issue
      });
    }

    if (locator.getUnusedDimensions().contains(SNAPSHOT_DEP)) { //performance optimization: do not filter if already processed
      final String snapshotDepDimension = locator.getSingleDimensionValue(SNAPSHOT_DEP);
      if (snapshotDepDimension != null) {
        final Set<BuildPromotion> snapshotRelatedBuilds = new HashSet<>(getSnapshotRelatedBuilds(snapshotDepDimension));
        result.add(item -> snapshotRelatedBuilds.contains(item));
      }
    }

    if (locator.getUnusedDimensions().contains(ARTIFACT_DEP)) { //performance optimization: do not filter if already processed
      final String artifactDepDimension = locator.getSingleDimensionValue(ARTIFACT_DEP);
      if (artifactDepDimension != null) {
        final Set<BuildPromotion> artifactRelatedBuilds = new HashSet<>(getArtifactRelatedBuilds(artifactDepDimension, locator));
        result.add(item -> artifactRelatedBuilds.contains(item));
      }
    }

    if (locator.isUnused(SNAPSHOT_PROBLEM)) {
      final String snapshotDepProblem = locator.getSingleDimensionValue(SNAPSHOT_PROBLEM);
      if (snapshotDepProblem != null) {
        final Set<BuildPromotion> snapshotDepProblemBuilds = new HashSet<>(getSnapshotDepProblemBuilds(snapshotDepProblem));
        result.add(item -> snapshotDepProblemBuilds.contains(item));
      }
    }

    if (locator.getUnusedDimensions().contains(EQUIVALENT)) { //performance optimization: do not filter if already processed
      final String equivalent = locator.getSingleDimensionValue(EQUIVALENT);
      if (equivalent != null) {
        final Set<BuildPromotion> filter = new HashSet<>(((BuildPromotionEx)getItem(equivalent)).getStartedEquivalentPromotions(-1));
        result.add(item -> filter.contains(item));
      }
    }

    if (locator.getUnusedDimensions().contains(METADATA)) { //performance optimization: do not filter if already processed
      final String metadata = locator.getSingleDimensionValue(METADATA);
      if (metadata != null) {
        final Iterator<BuildMetadataEntry> metadataEntries = getBuildMetadataEntryIterator(metadata);
        final Set<Long> buildIds = new HashSet<>();
        while (metadataEntries.hasNext()) {
          BuildMetadataEntry metadataEntry = metadataEntries.next();
          buildIds.add(metadataEntry.getBuildId());
        }
        result.add(item -> {
          if (!Build.canViewRuntimeData(myPermissionChecker, item)) return false;
          return buildIds.contains(item.getAssociatedBuildId());
        });
      }
    }

    if (locator.getUnusedDimensions().contains(ORDERED)) { //performance optimization: do not filter if already processed
      final String graphLocator = locator.getSingleDimensionValue(ORDERED);
      if (graphLocator != null) {
        final GraphFinder<BuildPromotion> graphFinder = new BuildPromotionOrderedFinder(BuildPromotionFinder.this);
        final Set<BuildPromotion> filter = new HashSet<>(graphFinder.getItems(graphLocator).getEntries());
        result.add(filter::contains);
      }
    }

    final String sinceBuildDimension = locator.getSingleDimensionValue(SINCE_BUILD);
    BuildPromotion sinceBuildPromotion = null;
    Long sinceBuildId = null;
    if (sinceBuildDimension != null) {
      try {
        sinceBuildPromotion = getItem(sinceBuildDimension);
        final SQueuedBuild queuedBuild = sinceBuildPromotion.getQueuedBuild();
        if (queuedBuild != null) {
          //compare queued builds by id (triggering sequence)
          final long buildPromotionId = getBuildId(sinceBuildPromotion);
          result.add(item -> buildPromotionId < getBuildId(item));
        } else {
          // for started build, compare by start time
          final SBuild limitingBuild = sinceBuildPromotion.getAssociatedBuild();
          if (limitingBuild != null) {
            final Date startDate = limitingBuild.getStartDate();
            result.add(item -> {
                final SBuild build = item.getAssociatedBuild();
                if (build == null) return true;
                if (startDate.equals(build.getStartDate()) && limitingBuild.getBuildId() != build.getBuildId()) return true;
                return startDate.before(build.getStartDate());
            });
          }
        }
      } catch (NotFoundException e) {
        //build not found by sinceBuild locator, extract id ad filter using it
        sinceBuildId = getBuildId(sinceBuildDimension);
        final long sinceBuildIdFinal = sinceBuildId;
        result.add(item -> sinceBuildIdFinal < getBuildId(item));
      }
    }

    final String untilBuild = locator.getSingleDimensionValue(UNTIL_BUILD);
    if (untilBuild != null) {
      try {
        final BuildPromotion untilBuildPromotion = getItem(untilBuild);
        final SQueuedBuild queuedBuild = untilBuildPromotion.getQueuedBuild();
        if (queuedBuild != null) {
          //compare queued builds by id (triggering sequence)
          final long buildPromotionId = getBuildId(untilBuildPromotion);
          result.add(item -> buildPromotionId >= getBuildId(item));
        } else {
          // for started build, compare by start time
          final SBuild limitingBuild = untilBuildPromotion.getAssociatedBuild();
          if (limitingBuild != null) {
            final Date startDate = limitingBuild.getStartDate();
            result.add(item -> {
                final SBuild build = item.getAssociatedBuild();
                return build == null || !startDate.before(build.getStartDate());
            });
          }
        }
      } catch (NotFoundException e) {
        //build not found by sinceBuild locator, extract id ad filter using it
        final long untilBuildId = getBuildId(untilBuild);
        result.add(item -> untilBuildId >= getBuildId(item));
      }
    }

    TimeCondition.FilterAndLimitingDate<BuildPromotion> queuedFiltering =
      myTimeCondition.processTimeConditions(QUEUED_TIME, locator, TimeCondition.QUEUED_BUILD_TIME, TimeCondition.QUEUED_BUILD_TIME);
    if (queuedFiltering != null) result.add(queuedFiltering.getFilter());

    TimeCondition.FilterAndLimitingDate<BuildPromotion> startedFiltering =
      myTimeCondition.processTimeConditions(STARTED_TIME, locator, TimeCondition.STARTED_BUILD_TIME, TimeCondition.STARTED_BUILD_TIME);

    @Nullable Date sinceStartDate = null;
    if (startedFiltering != null) {
      result.add(startedFiltering.getFilter());
      sinceStartDate = startedFiltering.getLimitingDate();
    }

    //todo: add processing cut of based on assumption of max build time (say, a week); for other times as well
    TimeCondition.FilterAndLimitingDate<BuildPromotion> finishFiltering =
      myTimeCondition.processTimeConditions(FINISHED_TIME, locator, TimeCondition.FINISHED_BUILD_TIME, TimeCondition.FINISHED_BUILD_TIME);
    if (finishFiltering != null) result.add(finishFiltering.getFilter());

    final String revisionLocatorText = locator.getSingleDimensionValue(REVISION);
    if (revisionLocatorText != null) {
      final Locator revisionLocator = new Locator(revisionLocatorText, "version", "internalVersion", "vcsRoot", Locator.LOCATOR_SINGLE_VALUE_UNUSED_NAME);
      final String revision = revisionLocator.getSingleValue();
      if (revision != null) {
        result.add(item -> {
            final List<BuildRevision> buildRevisions = item.getRevisions(); //use getAllrevisions map??
            for (BuildRevision rev : buildRevisions) {
              if (revision.equals(rev.getRevisionDisplayName())) {
                return true;
              }
            }
            return false;
        });
      } else {
        final String vcsRootLocator = revisionLocator.getSingleDimensionValue("vcsRoot");
        final SVcsRoot vcsRoot = vcsRootLocator == null ? null : myVcsRootFinder.getItem(vcsRootLocator);
        final ValueCondition versionCondition = ParameterCondition.createValueCondition(revisionLocator.getSingleDimensionValue("version"));
        final ValueCondition internalVersionCondition = ParameterCondition.createValueCondition(revisionLocator.getSingleDimensionValue("internalVersion"));
        revisionLocator.checkLocatorFullyProcessed();
        if (vcsRoot != null || versionCondition != null || internalVersionCondition != null) {
          result.add(item -> {
              final List<BuildRevision> revisions = item.getRevisions();  //use getAllrevisions map??
              for (BuildRevision rev : revisions) {
                if ((vcsRoot == null || vcsRoot.getId() == rev.getRoot().getParent().getId()) &&
                    (versionCondition == null || versionCondition.matches(rev.getRevisionDisplayName())) &&
                    (internalVersionCondition == null || internalVersionCondition.matches(rev.getRevision()))) {
                  return true;
                }
              }
              return false;
          });
        }
      }
    }

    List<FilterConditionChecker<SBuild>> buildFilters = getBuildFilter(locator);
    if (buildFilters.size() > 0) {
      MultiCheckerFilter<SBuild> buildFilter = MultiCheckerFilter.of(buildFilters);
      result.add(item -> {
          final SBuild build = item.getAssociatedBuild();
          if (build == null) {
            return false;
          }
          return buildFilter.isIncluded(build);
      });
    }

    sinceStartDate = TimeCondition.maxDate(sinceStartDate, DataProvider.parseDate(locator.getSingleDimensionValue(SINCE_DATE))); //see also filtering in getBuildFilter

    final Boolean canceled = locator.getSingleDimensionValueAsBoolean(CANCELED);
    if (canceled != null) {
      result.add(item -> {
          final SBuild build = item.getAssociatedBuild();
          return FilterUtil.isIncludedByBooleanFilter(canceled, build != null && build.getCanceledInfo() != null);
      });
    }

    final Boolean failedToStart = locator.getSingleDimensionValueAsBoolean(FAILED_TO_START);
    if (failedToStart != null) {
      result.add(item -> {
          final SBuild build = item.getAssociatedBuild();
          return FilterUtil.isIncludedByBooleanFilter(failedToStart, build != null && build.isInternalError());
      });
    }

    return getFilterWithProcessingCutOff(result.toItemFilter(), locator.getSingleDimensionValueAsLong(SINCE_BUILD_ID_LOOK_AHEAD_COUNT), sinceBuildPromotion, sinceBuildId, sinceStartDate);
  }