| // 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(); |
| } |
| } |