Move AccountState::fromAccountConfig to AccountsNoteDbImpl.

This method is storage-specific and only used by AccountUpdate (which
will be refactored next).

This is a part of a series of changes intended to add support for
different account storage systems.

Bug: Google b/274585632
Change-Id: I5ee8f59fbe10ef7d1c8d0b195a2e185ab0795605
Release-Notes: skip
diff --git a/java/com/google/gerrit/server/account/AccountConfig.java b/java/com/google/gerrit/server/account/AccountConfig.java
index 4143f77..f2331e3 100644
--- a/java/com/google/gerrit/server/account/AccountConfig.java
+++ b/java/com/google/gerrit/server/account/AccountConfig.java
@@ -205,7 +205,7 @@
    * Returns the content of the {@code preferences.config} file wrapped as {@link
    * CachedPreferences}.
    */
-  CachedPreferences asCachedPreferences() {
+  public CachedPreferences asCachedPreferences() {
     checkLoaded();
     return CachedPreferences.fromConfig(preferences.getRaw());
   }
diff --git a/java/com/google/gerrit/server/account/AccountState.java b/java/com/google/gerrit/server/account/AccountState.java
index b7a54f4..22f592f 100644
--- a/java/com/google/gerrit/server/account/AccountState.java
+++ b/java/com/google/gerrit/server/account/AccountState.java
@@ -18,7 +18,6 @@
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
-import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.NotifyConfig.NotifyType;
 import com.google.gerrit.extensions.client.DiffPreferencesInfo;
@@ -26,13 +25,11 @@
 import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
 import com.google.gerrit.server.account.ProjectWatches.ProjectWatchKey;
 import com.google.gerrit.server.account.externalids.ExternalId;
-import com.google.gerrit.server.account.externalids.ExternalIdNotes;
 import com.google.gerrit.server.account.externalids.ExternalIds;
 import com.google.gerrit.server.config.CachedPreferences;
 import java.io.IOException;
 import java.util.Collection;
 import java.util.Optional;
-import org.eclipse.jgit.lib.ObjectId;
 
 /**
  * Superset of all information related to an Account. This includes external IDs, project watches,
@@ -43,72 +40,6 @@
  */
 @AutoValue
 public abstract class AccountState {
-  /**
-   * Creates an AccountState from the given account config.
-   *
-   * @param externalIds class to access external IDs
-   * @param accountConfig the account config, must already be loaded
-   * @param defaultPreferences the default preferences for this Gerrit installation
-   * @return the account state, {@link Optional#empty()} if the account doesn't exist
-   * @throws IOException if accessing the external IDs fails
-   */
-  public static Optional<AccountState> fromAccountConfig(
-      ExternalIds externalIds, AccountConfig accountConfig, CachedPreferences defaultPreferences)
-      throws IOException {
-    return fromAccountConfig(externalIds, accountConfig, null, defaultPreferences);
-  }
-
-  /**
-   * Creates an AccountState from the given account config.
-   *
-   * <p>If external ID notes are provided the revision of the external IDs branch from which the
-   * external IDs for the account should be loaded is taken from the external ID notes. If external
-   * ID notes are not given the revision of the external IDs branch is taken from the account
-   * config. Updating external IDs is done via {@link ExternalIdNotes} and if external IDs were
-   * updated the revision of the external IDs branch in account config is outdated. Hence after
-   * updating external IDs the external ID notes must be provided.
-   *
-   * @param externalIds class to access external IDs
-   * @param accountConfig the account config, must already be loaded
-   * @param extIdNotes external ID notes, must already be loaded, may be {@code null}
-   * @param defaultPreferences the default preferences for this Gerrit installation
-   * @return the account state, {@link Optional#empty()} if the account doesn't exist
-   * @throws IOException if accessing the external IDs fails
-   */
-  public static Optional<AccountState> fromAccountConfig(
-      ExternalIds externalIds,
-      AccountConfig accountConfig,
-      @Nullable ExternalIdNotes extIdNotes,
-      CachedPreferences defaultPreferences)
-      throws IOException {
-    if (!accountConfig.getLoadedAccount().isPresent()) {
-      return Optional.empty();
-    }
-    Account account = accountConfig.getLoadedAccount().get();
-
-    Optional<ObjectId> extIdsRev =
-        extIdNotes != null
-            ? Optional.ofNullable(extIdNotes.getRevision())
-            : accountConfig.getExternalIdsRev();
-    ImmutableSet<ExternalId> extIds =
-        extIdsRev.isPresent()
-            ? externalIds.byAccount(account.id(), extIdsRev.get())
-            : ImmutableSet.of();
-
-    // Don't leak references to AccountConfig into the AccountState, since it holds a reference to
-    // an open Repository instance.
-    ImmutableMap<ProjectWatchKey, ImmutableSet<NotifyType>> projectWatches =
-        accountConfig.getProjectWatches();
-
-    return Optional.of(
-        new AutoValue_AccountState(
-            account,
-            extIds,
-            ExternalId.getUserName(extIds),
-            projectWatches,
-            Optional.of(defaultPreferences),
-            Optional.of(accountConfig.asCachedPreferences())));
-  }
 
   /**
    * Creates an AccountState for a given account with no external IDs, no project watches and
@@ -157,6 +88,18 @@
         Optional.empty());
   }
 
+  /** Creates an AccountState instance containing the given data. */
+  public static AccountState withState(
+      Account account,
+      ImmutableSet<ExternalId> externalIds,
+      Optional<String> userName,
+      ImmutableMap<ProjectWatches.ProjectWatchKey, ImmutableSet<NotifyType>> projectWatches,
+      Optional<CachedPreferences> defaultPreferences,
+      Optional<CachedPreferences> userPreferences) {
+    return new AutoValue_AccountState(
+        account, externalIds, userName, projectWatches, defaultPreferences, userPreferences);
+  }
+
   /** Get the cached account metadata. */
   public abstract Account account();
   /** The external identities that identify the account holder. */
diff --git a/java/com/google/gerrit/server/account/AccountsUpdate.java b/java/com/google/gerrit/server/account/AccountsUpdate.java
index 7dd4828..e801b14 100644
--- a/java/com/google/gerrit/server/account/AccountsUpdate.java
+++ b/java/com/google/gerrit/server/account/AccountsUpdate.java
@@ -39,6 +39,7 @@
 import com.google.gerrit.server.account.externalids.ExternalIdNotes;
 import com.google.gerrit.server.account.externalids.ExternalIdNotes.ExternalIdNotesLoader;
 import com.google.gerrit.server.account.externalids.ExternalIds;
+import com.google.gerrit.server.account.storage.notedb.AccountsNoteDbImpl;
 import com.google.gerrit.server.config.AllUsersName;
 import com.google.gerrit.server.config.CachedPreferences;
 import com.google.gerrit.server.config.VersionedDefaultPreferences;
@@ -407,7 +408,7 @@
       CachedPreferences defaultPreferences =
           CachedPreferences.fromConfig(VersionedDefaultPreferences.get(repo, allUsersName));
       Optional<AccountState> accountState =
-          AccountState.fromAccountConfig(externalIds, accountConfig, defaultPreferences);
+          AccountsNoteDbImpl.getFromAccountConfig(externalIds, accountConfig, defaultPreferences);
       if (!accountState.isPresent()) {
         return null;
       }
@@ -682,7 +683,7 @@
     }
 
     Optional<AccountState> getAccountState() throws IOException {
-      return AccountState.fromAccountConfig(
+      return AccountsNoteDbImpl.getFromAccountConfig(
           externalIds, accountConfig, externalIdNotes, defaultPreferences);
     }
   }
diff --git a/java/com/google/gerrit/server/account/storage/notedb/AccountsNoteDbImpl.java b/java/com/google/gerrit/server/account/storage/notedb/AccountsNoteDbImpl.java
index 732b088..ce8cd4d 100644
--- a/java/com/google/gerrit/server/account/storage/notedb/AccountsNoteDbImpl.java
+++ b/java/com/google/gerrit/server/account/storage/notedb/AccountsNoteDbImpl.java
@@ -18,14 +18,21 @@
 import static java.util.stream.Collectors.toList;
 import static java.util.stream.Collectors.toSet;
 
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.Account;
+import com.google.gerrit.entities.NotifyConfig;
 import com.google.gerrit.metrics.Description;
 import com.google.gerrit.metrics.MetricMaker;
 import com.google.gerrit.metrics.Timer0;
 import com.google.gerrit.server.account.AccountConfig;
 import com.google.gerrit.server.account.AccountState;
 import com.google.gerrit.server.account.Accounts;
+import com.google.gerrit.server.account.ProjectWatches;
+import com.google.gerrit.server.account.externalids.ExternalId;
+import com.google.gerrit.server.account.externalids.ExternalIdNotes;
 import com.google.gerrit.server.account.externalids.ExternalIds;
 import com.google.gerrit.server.config.AllUsersName;
 import com.google.gerrit.server.config.CachedPreferences;
@@ -41,6 +48,7 @@
 import java.util.stream.Stream;
 import javax.inject.Singleton;
 import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.Repository;
 
 @Singleton
@@ -124,6 +132,73 @@
     }
   }
 
+  /**
+   * Creates an AccountState from the given account config.
+   *
+   * @param externalIds class to access external IDs
+   * @param accountConfig the account config, must already be loaded
+   * @param defaultPreferences the default preferences for this Gerrit installation
+   * @return the account state, {@link Optional#empty()} if the account doesn't exist
+   * @throws IOException if accessing the external IDs fails
+   */
+  public static Optional<AccountState> getFromAccountConfig(
+      ExternalIds externalIds, AccountConfig accountConfig, CachedPreferences defaultPreferences)
+      throws IOException {
+    return getFromAccountConfig(externalIds, accountConfig, null, defaultPreferences);
+  }
+
+  /**
+   * Creates an AccountState from the given account config.
+   *
+   * <p>If external ID notes are provided the revision of the external IDs branch from which the
+   * external IDs for the account should be loaded is taken from the external ID notes. If external
+   * ID notes are not given the revision of the external IDs branch is taken from the account
+   * config. Updating external IDs is done via {@link ExternalIdNotes} and if external IDs were
+   * updated the revision of the external IDs branch in account config is outdated. Hence after
+   * updating external IDs the external ID notes must be provided.
+   *
+   * @param externalIds class to access external IDs
+   * @param accountConfig the account config, must already be loaded
+   * @param extIdNotes external ID notes, must already be loaded, may be {@code null}
+   * @param defaultPreferences the default preferences for this Gerrit installation
+   * @return the account state, {@link Optional#empty()} if the account doesn't exist
+   * @throws IOException if accessing the external IDs fails
+   */
+  public static Optional<AccountState> getFromAccountConfig(
+      ExternalIds externalIds,
+      AccountConfig accountConfig,
+      @Nullable ExternalIdNotes extIdNotes,
+      CachedPreferences defaultPreferences)
+      throws IOException {
+    if (!accountConfig.getLoadedAccount().isPresent()) {
+      return Optional.empty();
+    }
+    Account account = accountConfig.getLoadedAccount().get();
+
+    Optional<ObjectId> extIdsRev =
+        extIdNotes != null
+            ? Optional.ofNullable(extIdNotes.getRevision())
+            : accountConfig.getExternalIdsRev();
+    ImmutableSet<ExternalId> extIds =
+        extIdsRev.isPresent()
+            ? externalIds.byAccount(account.id(), extIdsRev.get())
+            : ImmutableSet.of();
+
+    // Don't leak references to AccountConfig into the AccountState, since it holds a reference to
+    // an open Repository instance.
+    ImmutableMap<ProjectWatches.ProjectWatchKey, ImmutableSet<NotifyConfig.NotifyType>>
+        projectWatches = accountConfig.getProjectWatches();
+
+    return Optional.of(
+        AccountState.withState(
+            account,
+            extIds,
+            ExternalId.getUserName(extIds),
+            projectWatches,
+            Optional.of(defaultPreferences),
+            Optional.of(accountConfig.asCachedPreferences())));
+  }
+
   private Stream<Account.Id> readUserRefs() throws IOException {
     try (Repository repo = repoManager.openRepository(allUsersName)) {
       return AccountsNoteDbRepoReader.readAllIds(repo);
@@ -141,6 +216,6 @@
               VersionedDefaultPreferences.get(allUsersRepository, allUsersName));
     }
 
-    return AccountState.fromAccountConfig(externalIds, cfg, defaultPreferences);
+    return getFromAccountConfig(externalIds, cfg, defaultPreferences);
   }
 }