LCOV - code coverage report
Current view: top level - server/query/account - InternalAccountQuery.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 13 51 25.5 %
Date: 2022-11-19 15:00:39 Functions: 9 16 56.2 %

          Line data    Source code
       1             : // Copyright (C) 2016 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.server.query.account;
      16             : 
      17             : import static java.util.stream.Collectors.toList;
      18             : import static java.util.stream.Collectors.toSet;
      19             : 
      20             : import com.google.common.base.Joiner;
      21             : import com.google.common.collect.ArrayListMultimap;
      22             : import com.google.common.collect.ImmutableList;
      23             : import com.google.common.collect.ImmutableListMultimap;
      24             : import com.google.common.collect.Multimap;
      25             : import com.google.common.flogger.FluentLogger;
      26             : import com.google.gerrit.common.Nullable;
      27             : import com.google.gerrit.common.UsedAt;
      28             : import com.google.gerrit.entities.Project;
      29             : import com.google.gerrit.index.IndexConfig;
      30             : import com.google.gerrit.index.Schema;
      31             : import com.google.gerrit.index.SchemaFieldDefs.SchemaField;
      32             : import com.google.gerrit.index.query.InternalQuery;
      33             : import com.google.gerrit.server.account.AccountState;
      34             : import com.google.gerrit.server.account.externalids.ExternalId;
      35             : import com.google.gerrit.server.account.externalids.ExternalIdKeyFactory;
      36             : import com.google.gerrit.server.index.account.AccountField;
      37             : import com.google.gerrit.server.index.account.AccountIndexCollection;
      38             : import com.google.inject.Inject;
      39             : import java.util.List;
      40             : import java.util.Set;
      41             : 
      42             : /**
      43             :  * Query wrapper for the account index.
      44             :  *
      45             :  * <p>Instances are one-time-use. Other singleton classes should inject a Provider rather than
      46             :  * holding on to a single instance.
      47             :  */
      48             : public class InternalAccountQuery extends InternalQuery<AccountState, InternalAccountQuery> {
      49         108 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      50             : 
      51             :   private final ExternalIdKeyFactory externalIdKeyFactory;
      52             : 
      53             :   @Inject
      54             :   InternalAccountQuery(
      55             :       AccountQueryProcessor queryProcessor,
      56             :       AccountIndexCollection indexes,
      57             :       IndexConfig indexConfig,
      58             :       ExternalIdKeyFactory externalIdKeyFactory) {
      59         108 :     super(queryProcessor, indexes, indexConfig);
      60         108 :     this.externalIdKeyFactory = externalIdKeyFactory;
      61         108 :   }
      62             : 
      63             :   public List<AccountState> byDefault(String query, boolean canSeeSecondaryEmails) {
      64          31 :     return query(AccountPredicates.defaultPredicate(schema(), canSeeSecondaryEmails, query));
      65             :   }
      66             : 
      67             :   public List<AccountState> byExternalId(String scheme, String id) {
      68           0 :     return byExternalId(externalIdKeyFactory.create(scheme, id));
      69             :   }
      70             : 
      71             :   public List<AccountState> byExternalId(ExternalId.Key externalId) {
      72           3 :     return query(AccountPredicates.externalIdIncludingSecondaryEmails(externalId.toString()));
      73             :   }
      74             : 
      75             :   @Nullable
      76             :   @UsedAt(UsedAt.Project.COLLABNET)
      77             :   public AccountState oneByExternalId(ExternalId.Key externalId) {
      78           0 :     List<AccountState> accountStates = byExternalId(externalId);
      79           0 :     if (accountStates.size() == 1) {
      80           0 :       return accountStates.get(0);
      81           0 :     } else if (!accountStates.isEmpty()) {
      82           0 :       StringBuilder msg = new StringBuilder();
      83           0 :       msg.append("Ambiguous external ID ").append(externalId).append(" for accounts: ");
      84           0 :       Joiner.on(", ")
      85           0 :           .appendTo(
      86           0 :               msg, accountStates.stream().map(a -> a.account().id().toString()).collect(toList()));
      87           0 :       logger.atWarning().log("%s", msg);
      88             :     }
      89           0 :     return null;
      90             :   }
      91             : 
      92             :   public List<AccountState> byFullName(String fullName) {
      93          33 :     return query(AccountPredicates.fullName(fullName));
      94             :   }
      95             : 
      96             :   /**
      97             :    * Queries for accounts that have a preferred email that exactly matches the given email.
      98             :    *
      99             :    * @param email preferred email by which accounts should be found
     100             :    * @return list of accounts that have a preferred email that exactly matches the given email
     101             :    */
     102             :   public List<AccountState> byPreferredEmail(String email) {
     103          36 :     if (hasPreferredEmailExact()) {
     104          36 :       return query(AccountPredicates.preferredEmailExact(email));
     105             :     }
     106             : 
     107           0 :     if (!hasPreferredEmail()) {
     108           0 :       return ImmutableList.of();
     109             :     }
     110             : 
     111           0 :     return query(AccountPredicates.preferredEmail(email)).stream()
     112           0 :         .filter(a -> a.account().preferredEmail().equals(email))
     113           0 :         .collect(toList());
     114             :   }
     115             : 
     116             :   /**
     117             :    * Makes multiple queries for accounts by preferred email (exact match).
     118             :    *
     119             :    * @param emails preferred emails by which accounts should be found
     120             :    * @return multimap of the given emails to accounts that have a preferred email that exactly
     121             :    *     matches this email
     122             :    */
     123             :   public Multimap<String, AccountState> byPreferredEmail(List<String> emails) {
     124           0 :     if (hasPreferredEmailExact()) {
     125           0 :       List<List<AccountState>> r =
     126           0 :           query(emails.stream().map(AccountPredicates::preferredEmailExact).collect(toList()));
     127           0 :       Multimap<String, AccountState> accountsByEmail = ArrayListMultimap.create();
     128           0 :       for (int i = 0; i < emails.size(); i++) {
     129           0 :         accountsByEmail.putAll(emails.get(i), r.get(i));
     130             :       }
     131           0 :       return accountsByEmail;
     132             :     }
     133             : 
     134           0 :     if (!hasPreferredEmail()) {
     135           0 :       return ImmutableListMultimap.of();
     136             :     }
     137             : 
     138           0 :     List<List<AccountState>> r =
     139           0 :         query(emails.stream().map(AccountPredicates::preferredEmail).collect(toList()));
     140           0 :     Multimap<String, AccountState> accountsByEmail = ArrayListMultimap.create();
     141           0 :     for (int i = 0; i < emails.size(); i++) {
     142           0 :       String email = emails.get(i);
     143           0 :       Set<AccountState> matchingAccounts =
     144           0 :           r.get(i).stream()
     145           0 :               .filter(a -> a.account().preferredEmail().equals(email))
     146           0 :               .collect(toSet());
     147           0 :       accountsByEmail.putAll(email, matchingAccounts);
     148             :     }
     149           0 :     return accountsByEmail;
     150             :   }
     151             : 
     152             :   public List<AccountState> byWatchedProject(Project.NameKey project) {
     153         103 :     return query(AccountPredicates.watchedProject(project));
     154             :   }
     155             : 
     156             :   private boolean hasField(SchemaField<AccountState, ?> field) {
     157          36 :     Schema<AccountState> s = schema();
     158          36 :     return (s != null && s.hasField(field));
     159             :   }
     160             : 
     161             :   private boolean hasPreferredEmail() {
     162           0 :     return hasField(AccountField.PREFERRED_EMAIL_LOWER_CASE_SPEC);
     163             :   }
     164             : 
     165             :   private boolean hasPreferredEmailExact() {
     166          36 :     return hasField(AccountField.PREFERRED_EMAIL_EXACT_SPEC);
     167             :   }
     168             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750