com.google.gerrit.entities.CachedProjectConfig Maven / Gradle / Ivy
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.entities;
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.flogger.FluentLogger;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
/**
 * Cached representation of values parsed from {@link
 * com.google.gerrit.server.project.ProjectConfig}.
 *
 * This class is immutable and thread-safe.
 */
@AutoValue
public abstract class CachedProjectConfig {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
  public abstract Project getProject();
  public abstract ImmutableMap getGroups();
  /** Returns a set of all groups used by this configuration. */
  public ImmutableSet getAllGroupUUIDs() {
    return getGroups().keySet();
  }
  /**
   * Returns the group reference for a {@link AccountGroup.UUID}, if the group is used by at least
   * one rule.
   */
  public Optional getGroup(AccountGroup.UUID uuid) {
    return Optional.ofNullable(getGroups().get(uuid));
  }
  /**
   * Returns the group reference for matching the given {@code name}, if the group is used by at
   * least one rule.
   */
  public Optional getGroupByName(@Nullable String name) {
    if (name == null) {
      return Optional.empty();
    }
    return getGroups().values().stream().filter(g -> name.equals(g.getName())).findAny();
  }
  /** Returns the account section containing visibility information about accounts. */
  public abstract AccountsSection getAccountsSection();
  /** Returns a map of {@link AccessSection}s keyed by their name. */
  public abstract ImmutableSortedMap getAccessSections();
  /** Returns the {@link AccessSection} with to the given name. */
  public Optional getAccessSection(String refName) {
    return Optional.ofNullable(getAccessSections().get(refName));
  }
  /** Returns all {@link AccessSection} names. */
  public ImmutableSet getAccessSectionNames() {
    return ImmutableSet.copyOf(getAccessSections().keySet());
  }
  /**
   * Returns the {@link BranchOrderSection} containing the order in which branches should be shown.
   */
  public abstract Optional getBranchOrderSection();
  /** Returns the {@link ContributorAgreement}s keyed by their name. */
  public abstract ImmutableMap getContributorAgreements();
  /** Returns the {@link NotifyConfig}s keyed by their name. */
  public abstract ImmutableMap getNotifySections();
  /** Returns the {@link LabelType}s keyed by their name. */
  public abstract ImmutableMap getLabelSections();
  /** Returns the {@link SubmitRequirement}s keyed by their name. */
  public abstract ImmutableMap getSubmitRequirementSections();
  /** Returns configured {@link ConfiguredMimeTypes}s. */
  public abstract ConfiguredMimeTypes getMimeTypes();
  /** Returns {@link SubscribeSection} keyed by the {@link Project.NameKey} they reference. */
  public abstract ImmutableMap getSubscribeSections();
  /** Returns {@link StoredCommentLinkInfo} keyed by their name. */
  public abstract ImmutableMap getCommentLinkSections();
  /** Returns the blob ID of the {@code rules.pl} file, if present. */
  public abstract Optional getRulesId();
  // TODO(hiesel): This should not have to be an Optional.
  /** Returns the SHA1 of the {@code refs/meta/config} branch. */
  public abstract Optional getRevision();
  /** Returns the maximum allowed object size. */
  public abstract long getMaxObjectSizeLimit();
  /** Returns {@code true} if received objects should be checked for validity. */
  public abstract boolean getCheckReceivedObjects();
  /** Returns a list of panel sections keyed by title. */
  public abstract ImmutableMap> getExtensionPanelSections();
  public ImmutableList getSubscribeSections(BranchNameKey branch) {
    return filterSubscribeSectionsByBranch(getSubscribeSections().values(), branch);
  }
  public abstract ImmutableMap getPluginConfigs();
  public abstract ImmutableMap getProjectLevelConfigs();
  public abstract ImmutableMap getParsedProjectLevelConfigs();
  public static Builder builder() {
    return new AutoValue_CachedProjectConfig.Builder();
  }
  public abstract Builder toBuilder();
  @AutoValue.Builder
  public abstract static class Builder {
    public abstract Builder setProject(Project value);
    public abstract Builder setAccountsSection(AccountsSection value);
    public abstract Builder setBranchOrderSection(Optional value);
    @CanIgnoreReturnValue
    public Builder addGroup(GroupReference groupReference) {
      AccountGroup.UUID groupUUID =
          Optional.ofNullable(groupReference.getUUID()).orElse(AccountGroup.UUID.EMPTY_UUID);
      groupsBuilder().put(groupUUID, GroupReference.create(groupUUID, groupReference.getName()));
      return this;
    }
    @CanIgnoreReturnValue
    public Builder addAccessSection(AccessSection accessSection) {
      accessSectionsBuilder().put(accessSection.getName(), accessSection);
      return this;
    }
    @CanIgnoreReturnValue
    public Builder addContributorAgreement(ContributorAgreement contributorAgreement) {
      contributorAgreementsBuilder().put(contributorAgreement.getName(), contributorAgreement);
      return this;
    }
    @CanIgnoreReturnValue
    public Builder addNotifySection(NotifyConfig notifyConfig) {
      notifySectionsBuilder().put(notifyConfig.getName(), notifyConfig);
      return this;
    }
    @CanIgnoreReturnValue
    public Builder addLabelSection(LabelType labelType) {
      labelSectionsBuilder().put(labelType.getName(), labelType);
      return this;
    }
    @CanIgnoreReturnValue
    public Builder addSubmitRequirementSection(SubmitRequirement submitRequirement) {
      submitRequirementSectionsBuilder().put(submitRequirement.name(), submitRequirement);
      return this;
    }
    public abstract Builder setMimeTypes(ConfiguredMimeTypes value);
    @CanIgnoreReturnValue
    public Builder addSubscribeSection(SubscribeSection subscribeSection) {
      subscribeSectionsBuilder().put(subscribeSection.project(), subscribeSection);
      return this;
    }
    @CanIgnoreReturnValue
    public Builder addCommentLinkSection(StoredCommentLinkInfo storedCommentLinkInfo) {
      commentLinkSectionsBuilder().put(storedCommentLinkInfo.getName(), storedCommentLinkInfo);
      return this;
    }
    public abstract Builder setRulesId(Optional value);
    public abstract Builder setRevision(Optional value);
    public abstract Builder setMaxObjectSizeLimit(long value);
    public abstract Builder setCheckReceivedObjects(boolean value);
    public abstract ImmutableMap.Builder>
        extensionPanelSectionsBuilder();
    public Builder setExtensionPanelSections(Map> value) {
      value
          .entrySet()
          .forEach(
              e ->
                  extensionPanelSectionsBuilder()
                      .put(e.getKey(), ImmutableList.copyOf(e.getValue())));
      return this;
    }
    abstract ImmutableMap.Builder pluginConfigsBuilder();
    @CanIgnoreReturnValue
    public Builder addPluginConfig(String pluginName, String pluginConfig) {
      pluginConfigsBuilder().put(pluginName, pluginConfig);
      return this;
    }
    abstract ImmutableMap.Builder projectLevelConfigsBuilder();
    abstract ImmutableMap.Builder parsedProjectLevelConfigsBuilder();
    @CanIgnoreReturnValue
    public Builder addProjectLevelConfig(String configFileName, String config) {
      projectLevelConfigsBuilder().put(configFileName, config);
      try {
        parsedProjectLevelConfigsBuilder().put(configFileName, ImmutableConfig.parse(config));
      } catch (ConfigInvalidException e) {
        logger.atInfo().withCause(e).log("Config for %s not parsable", configFileName);
      }
      return this;
    }
    public abstract CachedProjectConfig build();
    protected abstract ImmutableMap.Builder groupsBuilder();
    protected abstract ImmutableSortedMap.Builder accessSectionsBuilder();
    protected abstract ImmutableMap.Builder
        contributorAgreementsBuilder();
    protected abstract ImmutableMap.Builder notifySectionsBuilder();
    protected abstract ImmutableMap.Builder labelSectionsBuilder();
    protected abstract ImmutableMap.Builder
        submitRequirementSectionsBuilder();
    protected abstract ImmutableMap.Builder
        subscribeSectionsBuilder();
    protected abstract ImmutableMap.Builder
        commentLinkSectionsBuilder();
  }
  private static ImmutableList filterSubscribeSectionsByBranch(
      Collection allSubscribeSections, BranchNameKey branch) {
    ImmutableList.Builder ret = ImmutableList.builder();
    for (SubscribeSection s : allSubscribeSections) {
      if (s.appliesTo(branch)) {
        ret.add(s);
      }
    }
    return ret.build();
  }
}