com.google.gerrit.server.mail.send.ChangeEmail Maven / Gradle / Ivy
// Copyright (C) 2016 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.mail.send;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.NotifyConfig.NotifyType;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetInfo;
import com.google.gerrit.exceptions.EmailException;
import com.google.gerrit.extensions.api.changes.RecipientType;
import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.ChangeData;
import java.time.Instant;
import java.util.Map;
/** Populates an email for change related notifications. */
public interface ChangeEmail extends OutgoingEmail.EmailDecorator {
  /** Implementations of params interface populate details specific to the notification type. */
  interface ChangeEmailDecorator {
    /**
     * Stores the reference to the {@link OutgoingEmail} and {@link ChangeEmail} for the subsequent
     * calls.
     *
     * Both init and populateEmailContent can be called multiply times in case of retries. Init
     * is therefore responsible for clearing up any changes which are not idempotent and
     * initializing data for use in populateEmailContent.
     *
     * 
Can be used to adjust any of the behaviour of the {@link
     * ChangeEmail#populateEmailContent}.
     */
    void init(OutgoingEmail email, ChangeEmail changeEmail) throws EmailException;
    /**
     * Populate headers, recipients and body of the email.
     *
     * 
Method operates on the email provided in the init method.
     *
     * 
By default, all the contents and parameters of the email should be set in this method.
     */
    void populateEmailContent() throws EmailException;
    /** If returns false email is not sent to any recipients. */
    default boolean shouldSendMessage() {
      return true;
    }
  }
  /** Mark the email as non-first in the thread to ensure correct headers will be set */
  void markAsReply();
  /** Get change for which the email is being sent. */
  Change getChange();
  /** Get ChangeData for the change corresponding to the email. */
  ChangeData getChangeData();
  /**
   * Get Timestamp of the event causing the email.
   *
   * 
Provided by {@link #setChangeMessage(String, Instant)}.
   */
  @Nullable
  Instant getTimestamp();
  /** Specify PatchSet with which the notification is associated with. */
  void setPatchSet(PatchSet ps);
  /** Get PatchSet if provided. */
  @Nullable
  PatchSet getPatchSet();
  /** Specify PatchSet along with additional data. */
  void setPatchSet(PatchSet ps, PatchSetInfo psi);
  /** Specify the summary of what happened to the change. */
  void setChangeMessage(String cm, Instant t);
  /**
   * Specify if the email should only be sent to attention set.
   *
   * 
Only affects users who have corresponding option enabled in the settings.
   */
  void setEmailOnlyAttentionSetIfEnabled(boolean value);
  /** Get the text of the "cover letter" (processed changeMessage). */
  String getCoverLetter();
  /** Get the patch list corresponding to patch set patchSetId of this change. */
  Map listModifiedFiles(int patchSetId);
  /** Get the patch list corresponding to this patch set. */
  Map listModifiedFiles();
  /** Get the number of added lines in a change. */
  int getInsertionsCount();
  /** Get the number of deleted lines in a change. */
  int getDeletionsCount();
  /** Get the project entity the change is in; null if its been deleted. */
  ProjectState getProjectState();
  /** TO or CC all vested parties (change owner, patch set uploader, author). */
  void addAuthors(RecipientType rt);
  /** BCC any user who has starred this change. */
  void bccStarredBy();
  /** Include users and groups that want notification of events. */
  void includeWatchers(NotifyType type);
  /** Include users and groups that want notification of events. */
  void includeWatchers(NotifyType type, boolean includeWatchersFromNotifyConfig);
  /** Any user who has published comments on this change. */
  void ccAllApprovals();
  /** Users who were added as reviewers to this change. */
  void ccExistingReviewers();
  /** Show patch set as unified difference. */
  String getUnifiedDiff();
  /**
   * Generate a list of maps representing each line of the unified diff. The line maps will have a
   * 'type' key which maps to one of 'common', 'add' or 'remove' and a 'text' key which maps to the
   * line's content.
   *
   * @param sourceDiff the unified diff that we're converting to the map.
   * @return map of 'type' to a line's content.
   */
  static ImmutableList> getDiffTemplateData(String sourceDiff) {
    ImmutableList.Builder> result = ImmutableList.builder();
    Splitter lineSplitter = Splitter.on(System.getProperty("line.separator"));
    for (String diffLine : lineSplitter.split(sourceDiff)) {
      ImmutableMap.Builder lineData = ImmutableMap.builder();
      lineData.put("text", diffLine);
      // Skip empty lines and lines that look like diff headers.
      if (diffLine.isEmpty() || diffLine.startsWith("---") || diffLine.startsWith("+++")) {
        lineData.put("type", "common");
      } else {
        switch (diffLine.charAt(0)) {
          case '+':
            lineData.put("type", "add");
            break;
          case '-':
            lineData.put("type", "remove");
            break;
          default:
            lineData.put("type", "common");
            break;
        }
      }
      result.add(lineData.build());
    }
    return result.build();
  }
}