LCOV - code coverage report
Current view: top level - server/account - CachedAccountDetails.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 66 66 100.0 %
Date: 2022-11-19 15:00:39 Functions: 13 13 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2020 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.account;
      16             : 
      17             : import static com.google.common.collect.ImmutableSet.toImmutableSet;
      18             : 
      19             : import com.google.auto.value.AutoValue;
      20             : import com.google.common.base.Enums;
      21             : import com.google.common.base.Strings;
      22             : import com.google.common.collect.ImmutableMap;
      23             : import com.google.common.collect.ImmutableSet;
      24             : import com.google.gerrit.common.UsedAt;
      25             : import com.google.gerrit.entities.Account;
      26             : import com.google.gerrit.entities.NotifyConfig;
      27             : import com.google.gerrit.entities.Project;
      28             : import com.google.gerrit.proto.Protos;
      29             : import com.google.gerrit.server.cache.proto.Cache;
      30             : import com.google.gerrit.server.cache.serialize.CacheSerializer;
      31             : import com.google.gerrit.server.cache.serialize.ObjectIdConverter;
      32             : import com.google.gerrit.server.config.CachedPreferences;
      33             : import java.time.Instant;
      34             : import java.util.Map;
      35             : import org.eclipse.jgit.lib.ObjectId;
      36             : 
      37             : /** Details of an account that are cached persistently in {@link AccountCache}. */
      38             : @UsedAt(UsedAt.Project.GOOGLE)
      39             : @AutoValue
      40         151 : public abstract class CachedAccountDetails {
      41             :   @AutoValue
      42         151 :   public abstract static class Key {
      43             :     static Key create(Account.Id accountId, ObjectId id) {
      44         151 :       return new AutoValue_CachedAccountDetails_Key(accountId, id.copy());
      45             :     }
      46             : 
      47             :     /** Identifier of the account. */
      48             :     abstract Account.Id accountId();
      49             : 
      50             :     /**
      51             :      * Git revision at which the account was loaded. Corresponds to a revision on the account ref
      52             :      * ({@code refs/users/<sharded-id>}).
      53             :      */
      54             :     abstract ObjectId id();
      55             : 
      56             :     /** Serializer used to read this entity from and write it to a persistent storage. */
      57         152 :     enum Serializer implements CacheSerializer<Key> {
      58         152 :       INSTANCE;
      59             : 
      60             :       @Override
      61             :       public byte[] serialize(Key object) {
      62          15 :         return Protos.toByteArray(
      63          15 :             Cache.AccountKeyProto.newBuilder()
      64          15 :                 .setAccountId(object.accountId().get())
      65          15 :                 .setId(ObjectIdConverter.create().toByteString(object.id()))
      66          15 :                 .build());
      67             :       }
      68             : 
      69             :       @Override
      70             :       public Key deserialize(byte[] in) {
      71           1 :         Cache.AccountKeyProto proto = Protos.parseUnchecked(Cache.AccountKeyProto.parser(), in);
      72           1 :         return Key.create(
      73           1 :             Account.id(proto.getAccountId()),
      74           1 :             ObjectIdConverter.create().fromByteString(proto.getId()));
      75             :       }
      76             :     }
      77             :   }
      78             : 
      79             :   /** Essential attributes of the account, such as name or registration time. */
      80             :   abstract Account account();
      81             : 
      82             :   /** Projects that the user has configured to watch. */
      83             :   abstract ImmutableMap<ProjectWatches.ProjectWatchKey, ImmutableSet<NotifyConfig.NotifyType>>
      84             :       projectWatches();
      85             : 
      86             :   /** Preferences that this user has. Serialized as Git-config style string. */
      87             :   abstract CachedPreferences preferences();
      88             : 
      89             :   static CachedAccountDetails create(
      90             :       Account account,
      91             :       ImmutableMap<ProjectWatches.ProjectWatchKey, ImmutableSet<NotifyConfig.NotifyType>>
      92             :           projectWatches,
      93             :       CachedPreferences preferences) {
      94         151 :     return new AutoValue_CachedAccountDetails(account, projectWatches, preferences);
      95             :   }
      96             : 
      97             :   /** Serializer used to read this entity from and write it to a persistent storage. */
      98         152 :   enum Serializer implements CacheSerializer<CachedAccountDetails> {
      99         152 :     INSTANCE;
     100             : 
     101             :     @Override
     102             :     public byte[] serialize(CachedAccountDetails cachedAccountDetails) {
     103          16 :       Cache.AccountDetailsProto.Builder serialized = Cache.AccountDetailsProto.newBuilder();
     104             :       // We don't care about the difference of empty strings and null in the Account entity.
     105          16 :       Account account = cachedAccountDetails.account();
     106             :       Cache.AccountProto.Builder accountProto =
     107          16 :           Cache.AccountProto.newBuilder()
     108          16 :               .setId(account.id().get())
     109          16 :               .setRegisteredOn(account.registeredOn().toEpochMilli())
     110          16 :               .setInactive(account.inactive())
     111          16 :               .setFullName(Strings.nullToEmpty(account.fullName()))
     112          16 :               .setDisplayName(Strings.nullToEmpty(account.displayName()))
     113          16 :               .setPreferredEmail(Strings.nullToEmpty(account.preferredEmail()))
     114          16 :               .setStatus(Strings.nullToEmpty(account.status()))
     115          16 :               .setMetaId(Strings.nullToEmpty(account.metaId()));
     116          16 :       serialized.setAccount(accountProto);
     117             : 
     118             :       for (Map.Entry<ProjectWatches.ProjectWatchKey, ImmutableSet<NotifyConfig.NotifyType>> watch :
     119          16 :           cachedAccountDetails.projectWatches().entrySet()) {
     120             :         Cache.ProjectWatchProto.Builder proto =
     121           1 :             Cache.ProjectWatchProto.newBuilder().setProject(watch.getKey().project().get());
     122           1 :         if (watch.getKey().filter() != null) {
     123           1 :           proto.setFilter(watch.getKey().filter());
     124             :         }
     125           1 :         watch
     126           1 :             .getValue()
     127           1 :             .forEach(
     128             :                 n ->
     129           1 :                     proto.addNotifyType(
     130           1 :                         Enums.stringConverter(NotifyConfig.NotifyType.class).reverse().convert(n)));
     131           1 :         serialized.addProjectWatchProto(proto);
     132           1 :       }
     133             : 
     134          16 :       serialized.setUserPreferences(cachedAccountDetails.preferences().config());
     135          16 :       return Protos.toByteArray(serialized.build());
     136             :     }
     137             : 
     138             :     @Override
     139             :     public CachedAccountDetails deserialize(byte[] in) {
     140             :       Cache.AccountDetailsProto proto =
     141           2 :           Protos.parseUnchecked(Cache.AccountDetailsProto.parser(), in);
     142           2 :       Account account =
     143           2 :           Account.builder(
     144           2 :                   Account.id(proto.getAccount().getId()),
     145           2 :                   Instant.ofEpochMilli(proto.getAccount().getRegisteredOn()))
     146           2 :               .setFullName(Strings.emptyToNull(proto.getAccount().getFullName()))
     147           2 :               .setDisplayName(Strings.emptyToNull(proto.getAccount().getDisplayName()))
     148           2 :               .setPreferredEmail(Strings.emptyToNull(proto.getAccount().getPreferredEmail()))
     149           2 :               .setInactive(proto.getAccount().getInactive())
     150           2 :               .setStatus(Strings.emptyToNull(proto.getAccount().getStatus()))
     151           2 :               .setMetaId(Strings.emptyToNull(proto.getAccount().getMetaId()))
     152           2 :               .build();
     153             : 
     154             :       ImmutableMap.Builder<ProjectWatches.ProjectWatchKey, ImmutableSet<NotifyConfig.NotifyType>>
     155           2 :           projectWatches = ImmutableMap.builder();
     156           2 :       proto.getProjectWatchProtoList().stream()
     157           2 :           .forEach(
     158             :               p ->
     159           1 :                   projectWatches.put(
     160           1 :                       ProjectWatches.ProjectWatchKey.create(
     161           1 :                           Project.nameKey(p.getProject()), p.getFilter()),
     162           1 :                       p.getNotifyTypeList().stream()
     163           1 :                           .map(e -> Enums.stringConverter(NotifyConfig.NotifyType.class).convert(e))
     164           1 :                           .collect(toImmutableSet())));
     165             : 
     166           2 :       return CachedAccountDetails.create(
     167             :           account,
     168           2 :           projectWatches.build(),
     169           2 :           CachedPreferences.fromString(proto.getUserPreferences()));
     170             :     }
     171             :   }
     172             : }

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