// Copyright (C) 2013 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.server.notedb;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.gerrit.entities.RefNames.changeMetaRef;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_ATTENTION;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_BASE;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_BRANCH;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_CHANGE_ID;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_CHERRY_PICK_OF;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_COMMIT;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_CONTAINS_CONFLICTS;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_COPIED_LABEL;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_CURRENT;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_CUSTOM_KEYED_VALUE;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_GROUPS;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_HASHTAGS;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_LABEL;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_MERGE_STRATEGY;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_NO_BASE_REASON;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_OURS;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_PATCH_SET;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_PATCH_SET_DESCRIPTION;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_PRIVATE;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_REAL_USER;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_REVERT_OF;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_STATUS;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_SUBJECT;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_SUBMISSION_ID;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_SUBMITTED_WITH;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_TAG;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_THEIRS;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_TOPIC;
import static com.google.gerrit.server.notedb.ChangeNoteFooters.FOOTER_WORK_IN_PROGRESS;
import static com.google.gerrit.server.notedb.NoteDbUtil.sanitizeFooter;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.CHANGE_MODIFICATION;
import static java.util.Comparator.naturalOrder;
import static java.util.Objects.requireNonNull;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Iterables;
import com.google.common.collect.Table;
import com.google.common.collect.Table.Cell;
import com.google.common.collect.TreeBasedTable;
import com.google.common.flogger.FluentLogger;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Address;
import com.google.gerrit.entities.AttentionSetUpdate;
import com.google.gerrit.entities.AttentionSetUpdate.Operation;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.SubmissionId;
import com.google.gerrit.entities.SubmitRecord;
import com.google.gerrit.entities.SubmitRequirementResult;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.server.ChangeDraftUpdate;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.ServiceUserClassifier;
import com.google.gerrit.server.approval.PatchSetApprovalUuidGenerator;
import com.google.gerrit.server.experiments.ExperimentFeatures;
import com.google.gerrit.server.experiments.ExperimentFeaturesConstants;
import com.google.gerrit.server.git.validators.TopicValidator;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.gerrit.server.util.AttentionSetUtil;
import com.google.gerrit.server.util.LabelVote;
import com.google.gerrit.server.validators.ValidationException;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.FooterKey;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * A delta to apply to a change.
 *
 * <p>This delta will become two unique commits: one in the AllUsers repo that will contain the
 * draft comments on this change and one in the notes branch that will contain approvals, reviewers,
 * change status, subject, submit records, the change message, and published comments. There are
 * limitations on the set of modifications that can be handled in a single update. In particular,
 * there is a single author and timestamp for each update.
 *
 * <p>This class is not thread-safe.
 *
 * <p>NOTE: This class also serializes the change in a custom storage format, used in NoteDB. All
 * changes to the storage format must be both forward and backward compatible, see comment on {@link
 * ChangeNotesParser}.
 *
 * <p>Such changes include e.g. introducing/removing footers, modifying footer formats, mutations of
 * the attached {@link ChangeRevisionNote}.
 */
public class ChangeUpdate extends AbstractChangeUpdate {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public interface Factory {
    ChangeUpdate create(ChangeNotes notes, CurrentUser user, Instant when);

    ChangeUpdate create(
        ChangeNotes notes, CurrentUser user, Instant when, Comparator<String> labelNameComparator);
  }

  public static final int MAX_CUSTOM_KEY_LENGTH = 100;
  public static final int MAX_CUSTOM_KEYED_VALUE_LENGTH = 1000;
  public static final int MAX_CUSTOM_KEYED_VALUES = 100;

  private final NoteDbUpdateManager.Factory updateManagerFactory;
  private final ChangeDraftUpdate.ChangeDraftUpdateFactory draftUpdateFactory;
  private final DeleteCommentRewriter.Factory deleteCommentRewriterFactory;
  private final ServiceUserClassifier serviceUserClassifier;
  private final PatchSetApprovalUuidGenerator patchSetApprovalUuidGenerator;

  private final Table<String, Account.Id, Optional<PatchSetApproval>> approvals;
  private final List<PatchSetApproval> copiedApprovals = new ArrayList<>();
  private final Map<Account.Id, ReviewerStateInternal> reviewers = new LinkedHashMap<>();
  private final Map<Address, ReviewerStateInternal> reviewersByEmail = new LinkedHashMap<>();
  private final List<HumanComment> comments = new ArrayList<>();
  private final ExperimentFeatures experimentFeatures;

  private String commitSubject;
  private String subject;
  private String changeId;
  private String branch;
  private Change.Status status;
  private ImmutableList<SubmitRecord> submitRecords;
  private String submissionId;
  private String topic;
  private String commit;
  private Map<Account.Id, AttentionSetUpdate> plannedAttentionSetUpdates;
  private boolean ignoreFurtherAttentionSetUpdates;
  private Set<String> hashtags;
  private TreeMap<String, String> customKeyedValues = new TreeMap<>();
  private String changeMessage;
  private String tag;
  private PatchSetState psState;
  private List<String> groups;
  private String pushCert;
  private boolean isAllowWriteToNewtRef;
  private String psDescription;
  private boolean currentPatchSet;
  private Boolean isPrivate;
  private Boolean workInProgress;
  private PatchSet.Conflicts conflicts;
  private Integer revertOf;
  // If null, the update does not modify the field. Otherwise, it updates the field with the
  // new value or resets if cherryPickOf == Optional.empty().
  private Optional<String> cherryPickOf;

  private ChangeDraftUpdate draftUpdate;
  private DeleteCommentRewriter deleteCommentRewriter;
  private DeleteChangeMessageRewriter deleteChangeMessageRewriter;
  private List<SubmitRequirementResult> submitRequirementResults;

  private ImmutableList.Builder<AttentionSetUpdate> attentionSetUpdatesBuilder =
      ImmutableList.builder();

  private final CurrentUser user;

  @SuppressWarnings("UnusedMethod")
  @AssistedInject
  private ChangeUpdate(
      @GerritPersonIdent PersonIdent serverIdent,
      NoteDbUpdateManager.Factory updateManagerFactory,
      ChangeDraftUpdate.ChangeDraftUpdateFactory draftUpdateFactory,
      DeleteCommentRewriter.Factory deleteCommentRewriterFactory,
      ProjectCache projectCache,
      ServiceUserClassifier serviceUserClassifier,
      PatchSetApprovalUuidGenerator patchSetApprovalUuidGenerator,
      ExperimentFeatures experimentFeatures,
      @Assisted ChangeNotes notes,
      @Assisted CurrentUser user,
      @Assisted Instant when,
      ChangeNoteUtil noteUtil) {
    this(
        serverIdent,
        updateManagerFactory,
        draftUpdateFactory,
        deleteCommentRewriterFactory,
        serviceUserClassifier,
        patchSetApprovalUuidGenerator,
        experimentFeatures,
        notes,
        user,
        when,
        projectCache
            .get(notes.getProjectName())
            .orElseThrow(illegalState(notes.getProjectName()))
            .getLabelTypes()
            .nameComparator(),
        noteUtil);
  }

  private static Table<String, Account.Id, Optional<PatchSetApproval>> approvals(
      Comparator<String> nameComparator) {
    return TreeBasedTable.create(nameComparator, naturalOrder());
  }

  @AssistedInject
  private ChangeUpdate(
      @GerritPersonIdent PersonIdent serverIdent,
      NoteDbUpdateManager.Factory updateManagerFactory,
      ChangeDraftUpdate.ChangeDraftUpdateFactory draftUpdateFactory,
      DeleteCommentRewriter.Factory deleteCommentRewriterFactory,
      ServiceUserClassifier serviceUserClassifier,
      PatchSetApprovalUuidGenerator patchSetApprovalUuidGenerator,
      ExperimentFeatures experimentFeatures,
      @Assisted ChangeNotes notes,
      @Assisted CurrentUser user,
      @Assisted Instant when,
      @Assisted Comparator<String> labelNameComparator,
      ChangeNoteUtil noteUtil) {
    super(notes, user, serverIdent, noteUtil, when);
    this.updateManagerFactory = updateManagerFactory;
    this.draftUpdateFactory = draftUpdateFactory;
    this.deleteCommentRewriterFactory = deleteCommentRewriterFactory;
    this.serviceUserClassifier = serviceUserClassifier;
    this.patchSetApprovalUuidGenerator = patchSetApprovalUuidGenerator;
    this.experimentFeatures = experimentFeatures;
    this.approvals = approvals(labelNameComparator);
    this.user = user;
  }

  @CanIgnoreReturnValue
  public ObjectId commit() throws IOException {
    try (RefUpdateContext ctx = RefUpdateContext.open(CHANGE_MODIFICATION)) {
      try (NoteDbUpdateManager updateManager =
          updateManagerFactory.create(getProjectName(), user)) {
        updateManager.add(this);
        updateManager.execute();
      }
    }
    return getResult();
  }

  public void setChangeId(String changeId) {
    String old = getChange().getKey().get();
    checkArgument(
        old.equals(changeId),
        "The Change-Id was already set to %s, so we cannot set this Change-Id: %s",
        old,
        changeId);
    this.changeId = changeId;
  }

  public void setBranch(String branch) {
    this.branch = branch;
  }

  public void setStatus(Change.Status status) {
    checkArgument(status != Change.Status.MERGED, "use merge(RequestId, Iterable<SubmitRecord>)");
    this.status = status;
  }

  public void fixStatusToMerged(SubmissionId submissionId) {
    checkArgument(submissionId != null, "submission id must be set for merged changes");
    this.status = Change.Status.MERGED;
    this.submissionId = submissionId.toString();
  }

  public void putApproval(String label, short value) {
    putApprovalFor(getAccountId(), label, value);
  }

  public void putApprovalFor(Account.Id reviewer, String label, short value) {
    PatchSetApproval psa =
        PatchSetApproval.builder()
            .key(PatchSetApproval.key(getPatchSetId(), reviewer, LabelId.create(label)))
            .value(value)
            .granted(when)
            .uuid(patchSetApprovalUuidGenerator.get(getPatchSetId(), reviewer, label, value, when))
            .build();
    approvals.put(label, reviewer, Optional.of(psa));
  }

  public ImmutableTable<String, Account.Id, Optional<PatchSetApproval>> getApprovals() {
    return ImmutableTable.copyOf(approvals);
  }

  void removeApproval(String label) {
    removeApprovalFor(getAccountId(), label);
  }

  public void removeApprovalFor(Account.Id reviewer, String label) {
    approvals.put(label, reviewer, Optional.empty());
  }

  /**
   * We expect the {@code copied} flag of {@code copiedPatchSetApproval} to be set, since this
   * method is only meant for copied approvals.
   */
  public void putCopiedApproval(PatchSetApproval copiedPatchSetApproval) {
    checkArgument(copiedPatchSetApproval.copied(), "Approval that should be copied is not copied.");
    copiedApprovals.add(copiedPatchSetApproval);
  }

  public void removeCopiedApprovalFor(
      @Nullable Account.Id realUserId, Account.Id reviewerId, String label) {
    PatchSetApproval.Builder psaBuilder =
        PatchSetApproval.builder()
            .copied(true)
            .key(PatchSetApproval.key(getPatchSetId(), reviewerId, LabelId.create(label)))
            .value(0)
            .uuid(Optional.empty())
            .granted(when);

    if (realUserId != null) {
      psaBuilder.realAccountId(realUserId);
    }

    copiedApprovals.add(psaBuilder.build());
  }

  public void merge(SubmissionId submissionId, Iterable<SubmitRecord> submitRecords) {
    this.status = Change.Status.MERGED;
    this.submissionId = submissionId.toString();
    this.submitRecords = ImmutableList.copyOf(submitRecords);
    checkArgument(!this.submitRecords.isEmpty(), "no submit records specified at submit time");
  }

  public void setSubjectForCommit(String commitSubject) {
    this.commitSubject = commitSubject;
  }

  public void setSubject(String subject) {
    this.subject = subject;
  }

  @VisibleForTesting
  ObjectId getCommit() {
    return ObjectId.fromString(commit);
  }

  public void setChangeMessage(String changeMessage) {
    this.changeMessage = changeMessage;
  }

  public void setTag(String tag) {
    this.tag = tag;
  }

  public void setPsDescription(String psDescription) {
    this.psDescription = psDescription;
  }

  public void putSubmitRequirementResults(Collection<SubmitRequirementResult> rs) {
    if (submitRequirementResults == null) {
      submitRequirementResults = new ArrayList<>();
    }
    submitRequirementResults.addAll(rs);
  }

  public void putComment(Comment.Status status, HumanComment c) {
    verifyComment(c);
    createDraftUpdateIfNull();
    if (status == HumanComment.Status.DRAFT) {
      draftUpdate.putDraftComment(c);
    } else {
      comments.add(c);
      draftUpdate.markDraftCommentAsPublished(c);
    }
  }

  public void deleteComment(HumanComment c) {
    verifyComment(c);
    createDraftUpdateIfNull().addDraftCommentForDeletion(c);
  }

  public void deleteCommentByRewritingHistory(String uuid, String newMessage) {
    deleteCommentRewriter =
        deleteCommentRewriterFactory.create(getChange().getId(), uuid, newMessage);
  }

  public void deleteChangeMessageByRewritingHistory(String targetMessageId, String newMessage) {
    deleteChangeMessageRewriter =
        new DeleteChangeMessageRewriter(getChange().getId(), targetMessageId, newMessage);
  }

  @VisibleForTesting
  @CanIgnoreReturnValue
  ChangeDraftUpdate createDraftUpdateIfNull() {
    if (draftUpdate == null) {
      ChangeNotes notes = getNotes();
      if (notes != null) {
        draftUpdate = draftUpdateFactory.create(notes, accountId, realAccountId, authorIdent, when);
      } else {
        // tests will always take the notes != null path above.
        draftUpdate =
            draftUpdateFactory.create(getChange(), accountId, realAccountId, authorIdent, when);
      }
    }
    return draftUpdate;
  }

  public void setTopic(String topic, TopicValidator validator) throws ValidationException {
    validator.validateSize(topic);
    if (isIllegalTopic(topic)) {
      throw new ValidationException("topic can't contain quotation marks.");
    }
    this.topic = Strings.nullToEmpty(topic);
  }

  public void setCommit(RevWalk rw, ObjectId id) throws IOException {
    setCommit(rw, id, null);
  }

  public void setCommit(RevWalk rw, ObjectId id, String pushCert) throws IOException {
    RevCommit commit = rw.parseCommit(id);
    rw.parseBody(commit);
    this.commit = commit.name();
    subject = commit.getShortMessage();
    this.pushCert = pushCert;
  }

  public void setHashtags(Set<String> hashtags) {
    this.hashtags = hashtags;
  }

  public void addCustomKeyedValue(String key, String value) throws ValidationException {
    if (key.length() > MAX_CUSTOM_KEY_LENGTH) {
      throw new ValidationException("Custom Key is too long.");
    }
    if (value.length() > MAX_CUSTOM_KEYED_VALUE_LENGTH) {
      throw new ValidationException("Custom Keyed value is too long.");
    }
    this.customKeyedValues.put(key, value);
  }

  public void deleteCustomKeyedValue(String key) throws ValidationException {
    if (key.length() > MAX_CUSTOM_KEY_LENGTH) {
      throw new ValidationException("Custom Key is too long.");
    }
    this.customKeyedValues.put(key, "");
  }

  /**
   * Adds attention set updates that should be stored in NoteDb.
   *
   * <p>If invoked multiple times with attention set updates for the same user, only the attention
   * set update of the first invocation is stored for this user and further attention set updates
   * for this user are silently ignored. This means if callers invoke this method multiple times
   * with attention set updates for the same user, they must ensure that the first call is being
   * done with the attention set update that should take precedence.
   *
   * @param updates Attention set updates that should be performed. The updates must not have any
   *     timestamp set ({@link AttentionSetUpdate#timestamp()} must return {@code null}). This is
   *     because the timestamp of all performed updates is always the timestamp of when the NoteDb
   *     commit is created. Each of the provided updates must be for a different user, if there are
   *     multiple updates for the same user the update is rejected.
   * @throws IllegalArgumentException thrown if any of the provided updates has a timestamp set, or
   *     if the provided set of updates contains multiple updates for the same user
   */
  public void addToPlannedAttentionSetUpdates(Set<AttentionSetUpdate> updates) {
    if (updates == null || updates.isEmpty() || ignoreFurtherAttentionSetUpdates) {
      // No updates to do. Service users don't change attention set.
      return;
    }
    checkArgument(
        updates.stream().noneMatch(a -> a.timestamp() != null),
        "must not specify timestamp for write");

    checkArgument(
        updates.stream().map(AttentionSetUpdate::account).distinct().count() == updates.size(),
        "must not specify multiple updates for single user");

    if (plannedAttentionSetUpdates == null) {
      plannedAttentionSetUpdates = new HashMap<>();
    }

    // Only add attention set updates for users for which no attention set update has been planned
    // yet.
    updates.stream().forEach(u -> plannedAttentionSetUpdates.putIfAbsent(u.account(), u));
  }

  public void addToPlannedAttentionSetUpdates(AttentionSetUpdate update) {
    addToPlannedAttentionSetUpdates(ImmutableSet.of(update));
  }

  public ImmutableList<AttentionSetUpdate> getAttentionSetUpdates() {
    return attentionSetUpdatesBuilder.build();
  }

  public Map<Account.Id, ReviewerStateInternal> getReviewers() {
    return reviewers;
  }

  public void putReviewer(Account.Id reviewer, ReviewerStateInternal type) {
    checkArgument(type != ReviewerStateInternal.REMOVED, "invalid ReviewerType");
    reviewers.put(reviewer, type);
  }

  public void removeReviewer(Account.Id reviewer) {
    reviewers.put(reviewer, ReviewerStateInternal.REMOVED);
  }

  public void putReviewerByEmail(Address reviewer, ReviewerStateInternal type) {
    checkArgument(type != ReviewerStateInternal.REMOVED, "invalid ReviewerType");
    reviewersByEmail.put(reviewer, type);
  }

  public void removeReviewerByEmail(Address reviewer) {
    reviewersByEmail.put(reviewer, ReviewerStateInternal.REMOVED);
  }

  public void setPatchSetState(PatchSetState psState) {
    this.psState = psState;
  }

  public void setCurrentPatchSet() {
    this.currentPatchSet = true;
  }

  public void setGroups(List<String> groups) {
    requireNonNull(groups, "groups may not be null");
    this.groups = groups;
  }

  public void setRevertOf(int revertOf) {
    int ownId = getId().get();
    checkArgument(ownId != revertOf, "A change cannot revert itself");
    this.revertOf = revertOf;
    rootOnly = true;
  }

  public void setCherryPickOf(String cherryPickOf) {
    checkArgument(cherryPickOf != null, "use resetCherryPickOf");
    this.cherryPickOf = Optional.of(cherryPickOf);
  }

  public void resetCherryPickOf() {
    this.cherryPickOf = Optional.empty();
  }

  /** Returns the tree id for the updated tree */
  @Nullable
  private ObjectId storeRevisionNotes(RevWalk rw, ObjectInserter inserter, ObjectId curr)
      throws ConfigInvalidException, IOException {
    if (submitRequirementResults == null && comments.isEmpty() && pushCert == null) {
      return null;
    }
    RevisionNoteMap<ChangeRevisionNote> rnm = getRevisionNoteMap(rw, curr);

    RevisionNoteBuilder.Cache cache = new RevisionNoteBuilder.Cache(rnm);
    for (HumanComment c : comments) {
      c.tag = tag;
      if (!experimentFeatures.isFeatureEnabled(
          ExperimentFeaturesConstants.ALLOW_FIX_SUGGESTIONS_IN_COMMENTS)) {
        checkState(c.fixSuggestions == null, "feature flag prohibits setting fixSuggestions");
      }
      cache.get(c.getCommitId()).putComment(c);
    }
    if (submitRequirementResults != null) {
      if (submitRequirementResults.isEmpty()) {
        ObjectId latestPsCommitId =
            Iterables.getLast(getNotes().getPatchSets().values()).commitId();
        cache.get(latestPsCommitId).createEmptySubmitRequirementResults();
      } else {
        // Clear any previously stored SRs first. The SRs in this update will overwrite any
        // previously stored SRs (e.g. if the change is abandoned (SRs stored) -> un-abandoned ->
        // merged).
        submitRequirementResults.stream()
            .map(SubmitRequirementResult::patchSetCommitId)
            .distinct()
            .forEach(commit -> cache.get(commit).clearSubmitRequirementResults());
        for (SubmitRequirementResult sr : submitRequirementResults) {
          cache.get(sr.patchSetCommitId()).putSubmitRequirementResult(sr);
        }
      }
    }
    if (pushCert != null) {
      checkState(commit != null);
      cache.get(ObjectId.fromString(commit)).setPushCertificate(pushCert);
    }
    Map<ObjectId, RevisionNoteBuilder> builders = cache.getBuilders();
    checkComments(rnm.revisionNotes, builders);

    for (Map.Entry<ObjectId, RevisionNoteBuilder> e : builders.entrySet()) {
      ObjectId data = inserter.insert(OBJ_BLOB, e.getValue().build(noteUtil.getChangeNoteJson()));
      rnm.noteMap.set(e.getKey(), data);
    }

    return rnm.noteMap.writeTree(inserter);
  }

  private RevisionNoteMap<ChangeRevisionNote> getRevisionNoteMap(RevWalk rw, ObjectId curr)
      throws ConfigInvalidException, IOException {
    if (curr.equals(ObjectId.zeroId())) {
      return RevisionNoteMap.emptyMap();
    }
    // The old ChangeNotes may have already parsed the revision notes. We can reuse them as long as
    // the ref hasn't advanced.
    ChangeNotes notes = getNotes();
    if (notes != null && notes.revisionNoteMap != null) {
      ObjectId idFromNotes = firstNonNull(notes.load().getRevision(), ObjectId.zeroId());
      if (idFromNotes.equals(curr)) {
        return notes.revisionNoteMap;
      }
    }
    NoteMap noteMap = NoteMap.read(rw.getObjectReader(), rw.parseCommit(curr));
    // Even though reading from changes might not be enabled, we need to
    // parse any existing revision notes so we can merge them.
    return RevisionNoteMap.parse(
        noteUtil.getChangeNoteJson(), rw.getObjectReader(), noteMap, HumanComment.Status.PUBLISHED);
  }

  private void checkComments(
      Map<ObjectId, ChangeRevisionNote> existingNotes,
      Map<ObjectId, RevisionNoteBuilder> toUpdate) {
    // Prohibit various kinds of illegal operations on comments.
    Set<Comment.Key> existing = new HashSet<>();
    List<Comment> draftsToFix = new ArrayList<>();
    for (ChangeRevisionNote rn : existingNotes.values()) {
      for (Comment c : rn.getEntities()) {
        existing.add(c.key);
        draftsToFix.add(c);
      }
    }
    if (draftUpdate != null) {
      // Take advantage of an existing update on All-Users to prune any
      // published comments from drafts. NoteDbUpdateManager takes care of
      // ensuring that this update is applied before its dependent draft
      // update.
      //
      // Deleting aggressively in this way, combined with filtering out
      // duplicate published/draft comments in ChangeNotes#getDraftsByChangeAndDraftAuthor,
      // makes up for the fact that updates between the change repo and
      // All-Users are not atomic.
      //
      // TODO(dborowitz): We might want to distinguish between deleted
      // drafts that we're fixing up after the fact by putting them in a
      // separate commit. But note that we don't care much about the commit
      // graph of the draft ref, particularly because the ref is completely
      // deleted when all drafts are gone.
      draftUpdate.addAllDraftCommentsForDeletion(draftsToFix);
    }

    for (RevisionNoteBuilder b : toUpdate.values()) {
      for (Comment c : b.put.values()) {
        if (existing.contains(c.key)) {
          throw new StorageException("Cannot update existing published comment: " + c);
        }
      }
    }
  }

  @Override
  protected String getRefName() {
    return changeMetaRef(getId());
  }

  @Override
  protected boolean bypassMaxUpdates() {
    return isAbandonChange() || isAttentionSetChangeOnly();
  }

  private boolean isAbandonChange() {
    return status != null && status.isClosed();
  }

  private boolean isAttentionSetChangeOnly() {
    return (plannedAttentionSetUpdates != null
        && plannedAttentionSetUpdates.size() > 0
        && doesNotHaveChangesAffectingAttentionSet());
  }

  private boolean doesNotHaveChangesAffectingAttentionSet() {
    return comments.isEmpty()
        && reviewers.isEmpty()
        && reviewersByEmail.isEmpty()
        && approvals.isEmpty()
        && workInProgress == null;
  }

  @Override
  protected CommitBuilder applyImpl(RevWalk rw, ObjectInserter ins, ObjectId curr)
      throws IOException {
    checkState(
        deleteCommentRewriter == null && deleteChangeMessageRewriter == null,
        "cannot update and rewrite ref in one BatchUpdate");

    PatchSet.Id patchSetId = psId != null ? psId : getChange().currentPatchSetId();
    StringBuilder msg = new StringBuilder();
    if (commitSubject != null) {
      msg.append(commitSubject);
    } else {
      msg.append("Update patch set ").append(patchSetId.get());
    }
    msg.append("\n\n");

    if (changeMessage != null) {
      msg.append(changeMessage);
      msg.append("\n\n");
    }

    addPatchSetFooter(msg, patchSetId);

    if (currentPatchSet) {
      addFooter(msg, FOOTER_CURRENT, Boolean.TRUE);
    }

    if (psDescription != null) {
      addFooter(msg, FOOTER_PATCH_SET_DESCRIPTION, psDescription);
    }

    if (changeId != null) {
      addFooter(msg, FOOTER_CHANGE_ID, changeId);
    }

    if (subject != null) {
      addFooter(msg, FOOTER_SUBJECT, subject);
    }

    if (branch != null) {
      addFooter(msg, FOOTER_BRANCH, branch);
    }

    if (status != null) {
      addFooter(msg, FOOTER_STATUS, status.name().toLowerCase(Locale.US));
      if (status.equals(Change.Status.ABANDONED)) {
        clearAttentionSet("Change was abandoned");
      }
      if (status.equals(Change.Status.MERGED)) {
        clearAttentionSet("Change was submitted");
      }
    }

    if (topic != null) {
      addFooter(msg, FOOTER_TOPIC, topic);
    }

    if (commit != null) {
      addFooter(msg, FOOTER_COMMIT, commit);
    }

    Joiner comma = Joiner.on(',');
    if (hashtags != null) {
      addFooter(msg, FOOTER_HASHTAGS, comma.join(hashtags));
    }

    for (Map.Entry<String, String> entry : customKeyedValues.entrySet()) {
      addFooter(msg, FOOTER_CUSTOM_KEYED_VALUE, entry.getKey() + "=" + entry.getValue());
    }

    if (tag != null) {
      addFooter(msg, FOOTER_TAG, tag);
    }

    if (groups != null) {
      addFooter(msg, FOOTER_GROUPS, comma.join(groups));
    }

    for (Map.Entry<Account.Id, ReviewerStateInternal> e : reviewers.entrySet()) {
      addFooter(msg, e.getValue().getFooterKey());
      noteUtil.appendAccountIdIdentString(msg, e.getKey()).append('\n');
    }

    applyReviewerUpdatesToAttentionSet();

    for (Map.Entry<Address, ReviewerStateInternal> e : reviewersByEmail.entrySet()) {
      addFooter(msg, e.getValue().getByEmailFooterKey(), e.getKey().toString());
    }

    for (Table.Cell<String, Account.Id, Optional<PatchSetApproval>> c : approvals.cellSet()) {
      addLabelFooter(msg, c);
    }
    for (PatchSetApproval patchSetApproval : copiedApprovals) {
      addCopiedLabelFooter(msg, patchSetApproval);
    }

    if (submissionId != null) {
      addFooter(msg, FOOTER_SUBMISSION_ID, submissionId);
    }

    if (submitRecords != null) {
      for (SubmitRecord rec : submitRecords) {
        addFooter(msg, FOOTER_SUBMITTED_WITH).append(rec.status);
        if (rec.errorMessage != null) {
          msg.append(' ').append(sanitizeFooter(rec.errorMessage));
        }
        msg.append('\n');
        if (rec.ruleName != null) {
          addFooter(msg, FOOTER_SUBMITTED_WITH).append("Rule-Name: ").append(rec.ruleName);
          msg.append('\n');
        }
        if (rec.labels != null) {
          for (SubmitRecord.Label label : rec.labels) {
            // Label names/values are safe to append without sanitizing.
            addFooter(msg, FOOTER_SUBMITTED_WITH)
                .append(label.status)
                .append(": ")
                .append(label.label);
            if (label.appliedBy != null) {
              msg.append(": ");
              noteUtil.appendAccountIdIdentString(msg, label.appliedBy);
            }
            msg.append('\n');
          }
        }
      }
    }

    if (!Objects.equals(accountId, realAccountId)) {
      addFooter(msg, FOOTER_REAL_USER);
      noteUtil.appendAccountIdIdentString(msg, realAccountId).append('\n');
    }

    if (isPrivate != null) {
      addFooter(msg, FOOTER_PRIVATE, isPrivate);
    }

    if (workInProgress != null) {
      addFooter(msg, FOOTER_WORK_IN_PROGRESS, workInProgress);
      if (workInProgress) {
        clearAttentionSet("Change was marked work in progress");
      } else {
        addAllReviewersToAttentionSet();
      }
    }

    if (conflicts != null) {
      conflicts.base().map(ObjectId::getName).ifPresent(base -> addFooter(msg, FOOTER_BASE, base));
      conflicts.ours().map(ObjectId::getName).ifPresent(ours -> addFooter(msg, FOOTER_OURS, ours));
      conflicts
          .theirs()
          .map(ObjectId::getName)
          .ifPresent(theirs -> addFooter(msg, FOOTER_THEIRS, theirs));
      conflicts
          .mergeStrategy()
          .ifPresent(mergeStrategy -> addFooter(msg, FOOTER_MERGE_STRATEGY, mergeStrategy));
      conflicts
          .noBaseReason()
          .ifPresent(noBaseReason -> addFooter(msg, FOOTER_NO_BASE_REASON, noBaseReason));
      addFooter(msg, FOOTER_CONTAINS_CONFLICTS, conflicts.containsConflicts());
    }

    if (revertOf != null) {
      addFooter(msg, FOOTER_REVERT_OF, revertOf);
    }

    if (cherryPickOf != null) {
      if (cherryPickOf.isPresent()) {
        addFooter(msg, FOOTER_CHERRY_PICK_OF, cherryPickOf.get());
      } else {
        // Update cherryPickOf with an empty value.
        addFooter(msg, FOOTER_CHERRY_PICK_OF).append('\n');
      }
    }

    boolean hasAttentionSeUpdates = updateAttentionSet(msg);
    if (isEmptyWithoutAttentionSet() && !hasAttentionSeUpdates) {
      return NO_OP_UPDATE;
    }

    CommitBuilder cb = new CommitBuilder();
    cb.setMessage(msg.toString());
    try {
      ObjectId treeId = storeRevisionNotes(rw, ins, curr);
      if (treeId != null) {
        logger.atFine().log("change meta tree ID: %s (inserter: %s)", treeId.name(), ins);
        cb.setTreeId(treeId);
      } else {
        logger.atFine().log("no revision notes to write, hence no change meta tree was created");
      }
    } catch (ConfigInvalidException e) {
      throw new StorageException(e);
    }
    return cb;
  }

  private void addLabelFooter(
      StringBuilder msg, Cell<String, Account.Id, Optional<PatchSetApproval>> c) {
    addFooter(msg, FOOTER_LABEL);
    String label = c.getRowKey();
    Account.Id reviewerId = c.getColumnKey();
    // Label names/values are safe to append without sanitizing.
    boolean isRemoval = !c.getValue().isPresent();
    if (isRemoval) {
      msg.append('-').append(label);
      // Since vote removals do not need to be referenced, e.g. by the copy approvals, they do not
      // require a UUID.
    } else {
      short value = c.getValue().get().value();
      msg.append(LabelVote.create(label, value).formatWithEquals());
      msg.append(", ");
      msg.append(c.getValue().get().uuid().get());
    }
    if (!reviewerId.equals(getAccountId())) {
      noteUtil.appendAccountIdIdentString(msg.append(' '), reviewerId);
    }
    msg.append('\n');
  }

  private void addCopiedLabelFooter(StringBuilder msg, PatchSetApproval patchSetApproval) {
    if (patchSetApproval.value() == 0) {
      addFooter(msg, FOOTER_COPIED_LABEL);

      // Mark the copied approval as deleted.
      msg.append('-').append(patchSetApproval.label());

      noteUtil.appendAccountIdIdentString(msg.append(' '), patchSetApproval.accountId());

      // In the non-copied labels, we don't need to pass the real account id since it's already
      // in FOOTER_REAL_USER. Here, we want to retain the original real account id.
      if (!patchSetApproval.realAccountId().equals(patchSetApproval.accountId())) {
        noteUtil.appendAccountIdIdentString(msg.append(","), patchSetApproval.realAccountId());
      }

      msg.append('\n');
      return;
    }
    addFooter(msg, FOOTER_COPIED_LABEL);
    // Label names/values are safe to append without sanitizing.
    msg.append(
        LabelVote.create(patchSetApproval.label(), patchSetApproval.value()).formatWithEquals());
    // Might be copied from the vote that was generated before UUID was introduced.
    if (patchSetApproval.uuid().isPresent()) {
      msg.append(", ");
      msg.append(patchSetApproval.uuid().get());
    }
    Account.Id id = patchSetApproval.accountId();
    noteUtil.appendAccountIdIdentString(msg.append(' '), id);

    // In the non-copied labels, we don't need to pass the real account id since it's already
    // in FOOTER_REAL_USER. Here, we want to retain the original real account id.
    if (!patchSetApproval.realAccountId().equals(patchSetApproval.accountId())) {
      noteUtil.appendAccountIdIdentString(msg.append(","), patchSetApproval.realAccountId());
    }

    // In the non-copied labels, we don't need to pass the tag since it's already in
    // FOOTER_TAG, but in this chase we want to retain the original tag, and not the current tag.
    if (patchSetApproval.tag().isPresent()) {
      msg.append(":\"" + sanitizeFooter(patchSetApproval.tag().get()) + "\"");
    }

    msg.append('\n');
  }

  private void clearAttentionSet(String reason) {
    if (getNotes().getAttentionSet() == null) {
      return;
    }
    AttentionSetUtil.additionsOnly(getNotes().getAttentionSet()).stream()
        .map(
            a ->
                AttentionSetUpdate.createForWrite(
                    a.account(), AttentionSetUpdate.Operation.REMOVE, reason))
        .forEach(this::addToPlannedAttentionSetUpdates);
  }

  private void applyReviewerUpdatesToAttentionSet() {
    if ((workInProgress != null && workInProgress == true)
        || getNotes().getChange().isWorkInProgress()
        || status == Change.Status.MERGED) {
      // Attention set shouldn't change here for changes that are work in progress or are about to
      // be submitted or when the caller is a service user.
      return;
    }

    Set<AttentionSetUpdate> updates = new HashSet<>();
    ImmutableSet<Account.Id> currentReviewers =
        getNotes().getReviewers().byState(ReviewerStateInternal.REVIEWER);
    for (Map.Entry<Account.Id, ReviewerStateInternal> reviewer : reviewers.entrySet()) {
      Account.Id reviewerId = reviewer.getKey();

      ReviewerStateInternal reviewerState = reviewer.getValue();
      // Only add new reviewers to the attention set. Also, don't add the owner because the owner
      // can only be a "dummy" reviewer for legacy reasons.
      if (reviewerState.equals(ReviewerStateInternal.REVIEWER)
          && !currentReviewers.contains(reviewerId)
          && !reviewerId.equals(getChange().getOwner())) {
        updates.add(
            AttentionSetUpdate.createForWrite(
                reviewerId, AttentionSetUpdate.Operation.ADD, "Reviewer was added"));
      }
      boolean reviewerRemoved =
          !reviewerState.equals(ReviewerStateInternal.REVIEWER)
              && currentReviewers.contains(reviewerId);
      boolean ccRemoved = reviewerState.equals(ReviewerStateInternal.REMOVED);
      if (reviewerRemoved || ccRemoved) {
        updates.add(
            AttentionSetUpdate.createForWrite(
                reviewerId, AttentionSetUpdate.Operation.REMOVE, "Reviewer/Cc was removed"));
      }
    }
    addToPlannedAttentionSetUpdates(updates);
  }

  private void addAllReviewersToAttentionSet() {
    getNotes().getReviewers().byState(ReviewerStateInternal.REVIEWER).stream()
        .map(
            r ->
                AttentionSetUpdate.createForWrite(
                    r, AttentionSetUpdate.Operation.ADD, "Change was marked ready for review"))
        .forEach(this::addToPlannedAttentionSetUpdates);
  }

  /**
   * Any updates to the attention set must be done in {@link #addToPlannedAttentionSetUpdates}. This
   * method is called after all the updates are finished to do the updates once and for real.
   *
   * <p>Changing the behaviour of this method might affect the way a ChangeUpdate is considered to
   * be an "Attention Set Change Only". Make sure the {@link #isAttentionSetChangeOnly} logic is
   * amended as well if needed.
   *
   * @return True if one or more attention set updates are appended to the {@code msg}, and false
   *     otherwise.
   */
  private boolean updateAttentionSet(StringBuilder msg) {
    if (plannedAttentionSetUpdates == null) {
      plannedAttentionSetUpdates = new HashMap<>();
    }
    ImmutableMap<Account.Id, String> reasonsForCurrentUsersInAttentionSet =
        AttentionSetUtil.additionsOnly(getNotes().getAttentionSet()).stream()
            .collect(toImmutableMap(AttentionSetUpdate::account, AttentionSetUpdate::reason));

    // Current reviewers/ccs are the reviewers/ccs before the update + the new reviewers/ccs - the
    // deleted reviewers/ccs.
    Set<Account.Id> currentReviewers =
        Stream.concat(
                getNotes().getReviewers().all().stream(),
                reviewers.entrySet().stream()
                    .filter(r -> r.getValue().asReviewerState() != ReviewerState.REMOVED)
                    .map(r -> r.getKey()))
            .collect(Collectors.toSet());
    currentReviewers.removeAll(
        reviewers.entrySet().stream()
            .filter(r -> r.getValue().asReviewerState() == ReviewerState.REMOVED)
            .map(r -> r.getKey())
            .collect(ImmutableSet.toImmutableSet()));

    removeInactiveUsersFromAttentionSet(currentReviewers);

    boolean hasUpdates = false;

    for (AttentionSetUpdate attentionSetUpdate : plannedAttentionSetUpdates.values()) {
      if (attentionSetUpdate.operation() == AttentionSetUpdate.Operation.ADD
          && reasonsForCurrentUsersInAttentionSet.get(attentionSetUpdate.account()) != null
          && reasonsForCurrentUsersInAttentionSet
              .get(attentionSetUpdate.account())
              .equals(attentionSetUpdate.reason())) {
        // Skip users that are already in the attention set with the same reason: no need to re-add
        // them.
        continue;
      }

      if (attentionSetUpdate.operation() == AttentionSetUpdate.Operation.REMOVE
          && !reasonsForCurrentUsersInAttentionSet.containsKey(attentionSetUpdate.account())) {
        // Skip users that are not in the attention set: no need to remove them.
        continue;
      }

      if (attentionSetUpdate.operation() == AttentionSetUpdate.Operation.ADD
          && serviceUserClassifier.isServiceUser(attentionSetUpdate.account())) {
        // Skip adding service users to the attention set.
        continue;
      }

      if (attentionSetUpdate.operation() == AttentionSetUpdate.Operation.ADD
          && approvals.rowKeySet().contains(LabelId.legacySubmit().get())) {
        // On submit, we sometimes can add the person who submitted the change as a reviewer, and in
        // turn it will add that person to the attention set.
        // This ensures we don't add users to the attention set on submit.
        continue;
      }

      // Don't add accounts that are not active in the change to the attention set.
      if (attentionSetUpdate.operation() == AttentionSetUpdate.Operation.ADD
          && !isActiveOnChange(currentReviewers, attentionSetUpdate.account())) {
        continue;
      }

      addFooter(msg, FOOTER_ATTENTION, noteUtil.attentionSetUpdateToJson(attentionSetUpdate));
      attentionSetUpdatesBuilder.add(attentionSetUpdate);
      hasUpdates = true;
    }
    return hasUpdates;
  }

  private void removeInactiveUsersFromAttentionSet(Set<Account.Id> currentReviewers) {
    ImmutableSet<Account.Id> inActiveUsersInTheAttentionSet =
        // get the current attention set.
        getNotes().getAttentionSet().stream()
            .filter(a -> a.operation().equals(Operation.ADD))
            .map(a -> a.account())
            // remove users that are currently being removed from the attention set.
            .filter(
                a ->
                    plannedAttentionSetUpdates.getOrDefault(a, /* defaultValue= */ null) == null
                        || plannedAttentionSetUpdates.get(a).operation().equals(Operation.REMOVE))
            // remove users that are still active on the change.
            .filter(a -> !isActiveOnChange(currentReviewers, a))
            .collect(ImmutableSet.toImmutableSet());

    // We override the flag, as we never want such users in the attention set.
    ignoreFurtherAttentionSetUpdates = false;

    addToPlannedAttentionSetUpdates(
        inActiveUsersInTheAttentionSet.stream()
            .map(
                a ->
                    AttentionSetUpdate.createForWrite(
                        a,
                        Operation.REMOVE,
                        /* reason= */ "Only change owner, uploader, reviewers, and cc can "
                            + "be in the attention set"))
            .collect(ImmutableSet.toImmutableSet()));

    ignoreFurtherAttentionSetUpdates = true;
  }

  /**
   * Returns whether {@code accountId} is active on a change based on the {@code currentReviewers}.
   * Activity is defined as being a part of the reviewers, an uploader, or an owner of a change.
   */
  private boolean isActiveOnChange(Set<Account.Id> currentReviewers, Account.Id accountId) {
    return currentReviewers.contains(accountId)
        || getChange().getOwner().equals(accountId)
        || getNotes().getCurrentPatchSet().uploader().equals(accountId);
  }

  /**
   * When set, default attention set rules are ignored (E.g, adding reviewers -> adds to attention
   * set, etc).
   */
  public void ignoreFurtherAttentionSetUpdates() {
    ignoreFurtherAttentionSetUpdates = true;
  }

  private void addPatchSetFooter(StringBuilder sb, PatchSet.Id ps) {
    addFooter(sb, FOOTER_PATCH_SET).append(ps.get());
    if (psState != null) {
      sb.append(" (").append(psState.name().toLowerCase(Locale.US)).append(')');
    }
    sb.append('\n');
  }

  @Override
  protected Project.NameKey getProjectName() {
    return getChange().getProject();
  }

  @Override
  public boolean isEmpty() {
    return isEmptyWithoutAttentionSet() && plannedAttentionSetUpdates == null;
  }

  private boolean isEmptyWithoutAttentionSet() {
    return commitSubject == null
        && approvals.isEmpty()
        && copiedApprovals.isEmpty()
        && changeMessage == null
        && comments.isEmpty()
        && reviewers.isEmpty()
        && reviewersByEmail.isEmpty()
        && changeId == null
        && branch == null
        && status == null
        && submissionId == null
        && submitRecords == null
        && hashtags == null
        && customKeyedValues.isEmpty()
        && topic == null
        && commit == null
        && psState == null
        && groups == null
        && tag == null
        && psDescription == null
        && !currentPatchSet
        && isPrivate == null
        && workInProgress == null
        && revertOf == null
        && cherryPickOf == null;
  }

  ChangeDraftUpdate getDraftUpdate() {
    return draftUpdate;
  }

  DeleteCommentRewriter getDeleteCommentRewriter() {
    return deleteCommentRewriter;
  }

  DeleteChangeMessageRewriter getDeleteChangeMessageRewriter() {
    return deleteChangeMessageRewriter;
  }

  public void setAllowWriteToNewRef(boolean allow) {
    isAllowWriteToNewtRef = allow;
  }

  @Override
  public boolean allowWriteToNewRef() {
    return isAllowWriteToNewtRef;
  }

  public void setPrivate(boolean isPrivate) {
    this.isPrivate = isPrivate;
  }

  public void setWorkInProgress(boolean workInProgress) {
    this.workInProgress = workInProgress;
  }

  public void setConflicts(PatchSet.Conflicts conflicts) {
    this.conflicts = conflicts;
  }

  @CanIgnoreReturnValue
  private static StringBuilder addFooter(StringBuilder sb, FooterKey footer) {
    return sb.append(footer.getName()).append(": ");
  }

  private static void addFooter(StringBuilder sb, FooterKey footer, Object... values) {
    addFooter(sb, footer);
    for (Object value : values) {
      sb.append(sanitizeFooter(Objects.toString(value)));
    }
    sb.append('\n');
  }

  private static boolean isIllegalTopic(String topic) {
    return (topic != null && topic.contains("\""));
  }
}
