protected Response applyImpl()

in java/com/google/gerrit/plugins/codeowners/restapi/AbstractGetCodeOwnersForPath.java [185:334]


  protected Response<CodeOwnersInfo> applyImpl(R rsrc)
      throws AuthException, BadRequestException, PermissionBackendException {
    parseHexOptions();
    validateLimit();

    if (debug) {
      permissionBackend.currentUser().check(checkCodeOwnerCapability.getPermission());
    }

    if (!seed.isPresent()) {
      seed = getDefaultSeed(rsrc);
    }

    codeOwnerMetrics.countCodeOwnerSuggestions.increment(resolveAllUsers);

    // The distance that applies to code owners that are defined in the root code owner
    // configuration.
    int rootDistance = rsrc.getPath().getNameCount();

    int defaultOwnersDistance = rootDistance + 1;
    int globalOwnersDistance = defaultOwnersDistance + 1;
    int maxDistance = globalOwnersDistance;

    CodeOwnerScoring.Builder distanceScoring = CodeOwnerScore.DISTANCE.createScoring(maxDistance);
    CodeOwnerScoring.Builder isExplicitlyMentionedScoring =
        CodeOwnerScore.IS_EXPLICITLY_MENTIONED.createScoring();

    Set<CodeOwner> codeOwners = new HashSet<>();
    ListMultimap<CodeOwner, CodeOwnerAnnotation> annotations = LinkedListMultimap.create();
    AtomicBoolean ownedByAllUsers = new AtomicBoolean(false);
    ImmutableList.Builder<String> debugLogsBuilder = ImmutableList.builder();
    codeOwnerConfigHierarchy.visit(
        rsrc.getBranch(),
        rsrc.getRevision(),
        rsrc.getPath(),
        codeOwnerConfig -> {
          CodeOwnerResolverResult pathCodeOwners =
              codeOwnerResolver.get().resolvePathCodeOwners(codeOwnerConfig, rsrc.getPath());

          debugLogsBuilder.addAll(pathCodeOwners.messages());
          codeOwners.addAll(pathCodeOwners.codeOwners());
          annotations.putAll(pathCodeOwners.annotations());

          int distance =
              codeOwnerConfig.key().branchNameKey().branch().equals(RefNames.REFS_CONFIG)
                  ? defaultOwnersDistance
                  : rootDistance - codeOwnerConfig.key().folderPath().getNameCount();
          pathCodeOwners
              .codeOwners()
              .forEach(
                  localCodeOwner -> {
                    distanceScoring.putValueForCodeOwner(localCodeOwner, distance);
                    isExplicitlyMentionedScoring.putValueForCodeOwner(
                        localCodeOwner, IS_EXPLICITLY_MENTIONED_SCORING_VALUE);
                  });

          if (pathCodeOwners.ownedByAllUsers()) {
            ownedByAllUsers.set(true);
            ImmutableSet<CodeOwner> addedCodeOwners = fillUpWithRandomUsers(codeOwners, limit);
            addedCodeOwners.forEach(
                localCodeOwner -> {
                  distanceScoring.putValueForCodeOwner(localCodeOwner, distance);
                  isExplicitlyMentionedScoring.putValueForCodeOwner(
                      localCodeOwner, NOT_EXPLICITLY_MENTIONED_SCORING_VALUE);
                });

            if (codeOwners.size() < limit) {
              logger.atFine().log(
                  "tried to fill up the suggestion list with random users,"
                      + " but didn't find enough visible accounts"
                      + " (wanted number of suggestions = %d, got = %d",
                  limit, codeOwners.size());
            }
          }

          // We always need to iterate over all relevant OWNERS files (even if the limit has already
          // been reached).
          // This is needed to collect distance scores for code owners that are mentioned in the
          // more distant OWNERS files. Those become relevant if further scores are applied later
          // (e.g. the score for current reviewers of the change).
          return true;
        });

    if (!ownedByAllUsers.get()) {
      CodeOwnerResolverResult globalCodeOwners = getGlobalCodeOwners(rsrc.getBranch().project());

      debugLogsBuilder.add("resolve global code owners");
      debugLogsBuilder.addAll(globalCodeOwners.messages());

      globalCodeOwners
          .codeOwners()
          .forEach(
              codeOwner -> {
                distanceScoring.putValueForCodeOwner(codeOwner, globalOwnersDistance);
                isExplicitlyMentionedScoring.putValueForCodeOwner(
                    codeOwner, IS_EXPLICITLY_MENTIONED_SCORING_VALUE);
              });
      codeOwners.addAll(globalCodeOwners.codeOwners());

      if (globalCodeOwners.ownedByAllUsers()) {
        ownedByAllUsers.set(true);
        ImmutableSet<CodeOwner> addedCodeOwners = fillUpWithRandomUsers(codeOwners, limit);
        addedCodeOwners.forEach(
            codeOwner -> {
              distanceScoring.putValueForCodeOwner(codeOwner, globalOwnersDistance);
              isExplicitlyMentionedScoring.putValueForCodeOwner(
                  codeOwner, NOT_EXPLICITLY_MENTIONED_SCORING_VALUE);
            });
      }
    }

    ImmutableSet<CodeOwner> filteredCodeOwners =
        filterCodeOwners(
            rsrc,
            ImmutableMultimap.copyOf(annotations),
            ImmutableSet.copyOf(codeOwners),
            debugLogsBuilder);
    CodeOwnerScorings codeOwnerScorings =
        createScorings(
            rsrc,
            filteredCodeOwners,
            distanceScoring.build(),
            isExplicitlyMentionedScoring.build());
    ImmutableMap<CodeOwner, Double> scoredCodeOwners =
        codeOwnerScorings.getScorings(filteredCodeOwners);

    ImmutableList<CodeOwner> sortedAndLimitedCodeOwners = sortAndLimit(rsrc, scoredCodeOwners);

    if (highestScoreOnly) {
      Optional<Double> highestScore =
          scoredCodeOwners.values().stream().max(Comparator.naturalOrder());
      if (highestScore.isPresent()) {
        sortedAndLimitedCodeOwners =
            sortedAndLimitedCodeOwners.stream()
                .filter(codeOwner -> scoredCodeOwners.get(codeOwner).equals(highestScore.get()))
                .collect(toImmutableList());
      }
    }

    CodeOwnersInfo codeOwnersInfo = new CodeOwnersInfo();
    codeOwnersInfo.codeOwners =
        codeOwnerJsonFactory.create(getFillOptions()).format(sortedAndLimitedCodeOwners);
    codeOwnersInfo.ownedByAllUsers = ownedByAllUsers.get() ? true : null;

    ImmutableList<String> debugLogs = debugLogsBuilder.build();
    codeOwnersInfo.debugLogs = debug ? debugLogs : null;
    logger.atFine().log("debug logs: %s", debugLogs);

    return Response.ok(codeOwnersInfo);
  }