blob: b15a506717aa5f1a1362baee6a5d85f04ca31ad7 [file] [log] [blame]
// 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.
*
* <p>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.
*
* <p>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.
*
* <p>Method operates on the email provided in the init method.
*
* <p>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.
*
* <p>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.
*
* <p>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<String, FileDiffOutput> listModifiedFiles(int patchSetId);
/** Get the patch list corresponding to this patch set. */
Map<String, FileDiffOutput> 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<ImmutableMap<String, String>> getDiffTemplateData(String sourceDiff) {
ImmutableList.Builder<ImmutableMap<String, String>> result = ImmutableList.builder();
Splitter lineSplitter = Splitter.on(System.getProperty("line.separator"));
for (String diffLine : lineSplitter.split(sourceDiff)) {
ImmutableMap.Builder<String, String> 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();
}
}