LCOV - code coverage report
Current view: top level - server/events - StreamEventsApiListener.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 241 278 86.7 %
Date: 2022-11-19 15:00:39 Functions: 53 53 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2016 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.server.events;
      16             : 
      17             : import static com.google.gerrit.server.project.ProjectCache.illegalState;
      18             : 
      19             : import com.google.common.base.Supplier;
      20             : import com.google.common.base.Suppliers;
      21             : import com.google.common.collect.Sets;
      22             : import com.google.common.flogger.FluentLogger;
      23             : import com.google.gerrit.common.Nullable;
      24             : import com.google.gerrit.entities.Account;
      25             : import com.google.gerrit.entities.BranchNameKey;
      26             : import com.google.gerrit.entities.Change;
      27             : import com.google.gerrit.entities.LabelTypes;
      28             : import com.google.gerrit.entities.PatchSet;
      29             : import com.google.gerrit.entities.Project;
      30             : import com.google.gerrit.exceptions.StorageException;
      31             : import com.google.gerrit.extensions.common.AccountInfo;
      32             : import com.google.gerrit.extensions.common.ApprovalInfo;
      33             : import com.google.gerrit.extensions.common.ChangeInfo;
      34             : import com.google.gerrit.extensions.common.RevisionInfo;
      35             : import com.google.gerrit.extensions.events.AssigneeChangedListener;
      36             : import com.google.gerrit.extensions.events.ChangeAbandonedListener;
      37             : import com.google.gerrit.extensions.events.ChangeDeletedListener;
      38             : import com.google.gerrit.extensions.events.ChangeMergedListener;
      39             : import com.google.gerrit.extensions.events.ChangeRestoredListener;
      40             : import com.google.gerrit.extensions.events.CommentAddedListener;
      41             : import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
      42             : import com.google.gerrit.extensions.events.HashtagsEditedListener;
      43             : import com.google.gerrit.extensions.events.HeadUpdatedListener;
      44             : import com.google.gerrit.extensions.events.NewProjectCreatedListener;
      45             : import com.google.gerrit.extensions.events.PrivateStateChangedListener;
      46             : import com.google.gerrit.extensions.events.ReviewerAddedListener;
      47             : import com.google.gerrit.extensions.events.ReviewerDeletedListener;
      48             : import com.google.gerrit.extensions.events.RevisionCreatedListener;
      49             : import com.google.gerrit.extensions.events.TopicEditedListener;
      50             : import com.google.gerrit.extensions.events.VoteDeletedListener;
      51             : import com.google.gerrit.extensions.events.WorkInProgressStateChangedListener;
      52             : import com.google.gerrit.extensions.registration.DynamicSet;
      53             : import com.google.gerrit.server.PatchSetUtil;
      54             : import com.google.gerrit.server.data.AccountAttribute;
      55             : import com.google.gerrit.server.data.ApprovalAttribute;
      56             : import com.google.gerrit.server.data.ChangeAttribute;
      57             : import com.google.gerrit.server.data.PatchSetAttribute;
      58             : import com.google.gerrit.server.git.GitRepositoryManager;
      59             : import com.google.gerrit.server.notedb.ChangeNotes;
      60             : import com.google.gerrit.server.plugincontext.PluginItemContext;
      61             : import com.google.gerrit.server.project.NoSuchChangeException;
      62             : import com.google.gerrit.server.project.ProjectCache;
      63             : import com.google.inject.AbstractModule;
      64             : import com.google.inject.Inject;
      65             : import com.google.inject.Singleton;
      66             : import java.io.IOException;
      67             : import java.util.Collection;
      68             : import java.util.HashMap;
      69             : import java.util.Map;
      70             : import org.eclipse.jgit.lib.ObjectId;
      71             : import org.eclipse.jgit.lib.Repository;
      72             : import org.eclipse.jgit.revwalk.RevWalk;
      73             : 
      74             : @Singleton
      75             : public class StreamEventsApiListener
      76             :     implements AssigneeChangedListener,
      77             :         ChangeAbandonedListener,
      78             :         ChangeDeletedListener,
      79             :         ChangeMergedListener,
      80             :         ChangeRestoredListener,
      81             :         WorkInProgressStateChangedListener,
      82             :         PrivateStateChangedListener,
      83             :         CommentAddedListener,
      84             :         GitReferenceUpdatedListener,
      85             :         HashtagsEditedListener,
      86             :         NewProjectCreatedListener,
      87             :         ReviewerAddedListener,
      88             :         ReviewerDeletedListener,
      89             :         RevisionCreatedListener,
      90             :         TopicEditedListener,
      91             :         VoteDeletedListener,
      92             :         HeadUpdatedListener {
      93         138 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      94             : 
      95         138 :   public static class StreamEventsApiListenerModule extends AbstractModule {
      96             :     @Override
      97             :     protected void configure() {
      98         138 :       DynamicSet.bind(binder(), AssigneeChangedListener.class).to(StreamEventsApiListener.class);
      99         138 :       DynamicSet.bind(binder(), ChangeAbandonedListener.class).to(StreamEventsApiListener.class);
     100         138 :       DynamicSet.bind(binder(), ChangeDeletedListener.class).to(StreamEventsApiListener.class);
     101         138 :       DynamicSet.bind(binder(), ChangeMergedListener.class).to(StreamEventsApiListener.class);
     102         138 :       DynamicSet.bind(binder(), ChangeRestoredListener.class).to(StreamEventsApiListener.class);
     103         138 :       DynamicSet.bind(binder(), CommentAddedListener.class).to(StreamEventsApiListener.class);
     104         138 :       DynamicSet.bind(binder(), GitReferenceUpdatedListener.class)
     105         138 :           .to(StreamEventsApiListener.class);
     106         138 :       DynamicSet.bind(binder(), HashtagsEditedListener.class).to(StreamEventsApiListener.class);
     107         138 :       DynamicSet.bind(binder(), NewProjectCreatedListener.class).to(StreamEventsApiListener.class);
     108         138 :       DynamicSet.bind(binder(), PrivateStateChangedListener.class)
     109         138 :           .to(StreamEventsApiListener.class);
     110         138 :       DynamicSet.bind(binder(), ReviewerAddedListener.class).to(StreamEventsApiListener.class);
     111         138 :       DynamicSet.bind(binder(), ReviewerDeletedListener.class).to(StreamEventsApiListener.class);
     112         138 :       DynamicSet.bind(binder(), RevisionCreatedListener.class).to(StreamEventsApiListener.class);
     113         138 :       DynamicSet.bind(binder(), TopicEditedListener.class).to(StreamEventsApiListener.class);
     114         138 :       DynamicSet.bind(binder(), VoteDeletedListener.class).to(StreamEventsApiListener.class);
     115         138 :       DynamicSet.bind(binder(), WorkInProgressStateChangedListener.class)
     116         138 :           .to(StreamEventsApiListener.class);
     117         138 :       DynamicSet.bind(binder(), HeadUpdatedListener.class).to(StreamEventsApiListener.class);
     118         138 :     }
     119             :   }
     120             : 
     121             :   private final PluginItemContext<EventDispatcher> dispatcher;
     122             :   private final EventFactory eventFactory;
     123             :   private final ProjectCache projectCache;
     124             :   private final GitRepositoryManager repoManager;
     125             :   private final PatchSetUtil psUtil;
     126             :   private final ChangeNotes.Factory changeNotesFactory;
     127             : 
     128             :   @Inject
     129             :   StreamEventsApiListener(
     130             :       PluginItemContext<EventDispatcher> dispatcher,
     131             :       EventFactory eventFactory,
     132             :       ProjectCache projectCache,
     133             :       GitRepositoryManager repoManager,
     134             :       PatchSetUtil psUtil,
     135         138 :       ChangeNotes.Factory changeNotesFactory) {
     136         138 :     this.dispatcher = dispatcher;
     137         138 :     this.eventFactory = eventFactory;
     138         138 :     this.projectCache = projectCache;
     139         138 :     this.repoManager = repoManager;
     140         138 :     this.psUtil = psUtil;
     141         138 :     this.changeNotesFactory = changeNotesFactory;
     142         138 :   }
     143             : 
     144             :   private ChangeNotes getNotes(ChangeInfo info) {
     145             :     try {
     146          95 :       return changeNotesFactory.createChecked(
     147          95 :           Project.nameKey(info.project), Change.id(info._number));
     148           0 :     } catch (NoSuchChangeException e) {
     149           0 :       throw new StorageException(e);
     150             :     }
     151             :   }
     152             : 
     153             :   private PatchSet getPatchSet(ChangeNotes notes, RevisionInfo info) {
     154          95 :     return psUtil.get(notes, PatchSet.Id.fromRef(info.ref));
     155             :   }
     156             : 
     157             :   private Supplier<ChangeAttribute> changeAttributeSupplier(Change change, ChangeNotes notes) {
     158          95 :     return Suppliers.memoize(
     159             :         () -> {
     160             :           try {
     161           8 :             return eventFactory.asChangeAttribute(change, notes);
     162           0 :           } catch (StorageException e) {
     163           0 :             throw new RuntimeException(e);
     164             :           }
     165             :         });
     166             :   }
     167             : 
     168             :   private Supplier<AccountAttribute> accountAttributeSupplier(AccountInfo account) {
     169         138 :     return Suppliers.memoize(
     170             :         () ->
     171           2 :             account != null
     172           2 :                 ? eventFactory.asAccountAttribute(Account.id(account._accountId))
     173           0 :                 : null);
     174             :   }
     175             : 
     176             :   private Supplier<PatchSetAttribute> patchSetAttributeSupplier(
     177             :       final Change change, PatchSet patchSet) {
     178          95 :     return Suppliers.memoize(
     179             :         () -> {
     180           1 :           try (Repository repo = repoManager.openRepository(change.getProject());
     181           1 :               RevWalk revWalk = new RevWalk(repo)) {
     182           1 :             return eventFactory.asPatchSetAttribute(revWalk, change, patchSet);
     183           0 :           } catch (IOException e) {
     184           0 :             throw new RuntimeException(e);
     185             :           }
     186             :         });
     187             :   }
     188             : 
     189             :   private static Map<String, Short> convertApprovalsMap(Map<String, ApprovalInfo> approvals) {
     190          61 :     Map<String, Short> result = new HashMap<>();
     191          61 :     for (Map.Entry<String, ApprovalInfo> e : approvals.entrySet()) {
     192          61 :       Short value = e.getValue().value == null ? null : e.getValue().value.shortValue();
     193          61 :       result.put(e.getKey(), value);
     194          61 :     }
     195          61 :     return result;
     196             :   }
     197             : 
     198             :   private ApprovalAttribute getApprovalAttribute(
     199             :       LabelTypes labelTypes, Map.Entry<String, Short> approval, Map<String, Short> oldApprovals) {
     200           1 :     ApprovalAttribute a = new ApprovalAttribute();
     201           1 :     a.type = approval.getKey();
     202             : 
     203           1 :     if (oldApprovals != null && !oldApprovals.isEmpty()) {
     204           1 :       if (oldApprovals.get(approval.getKey()) != null) {
     205           0 :         a.oldValue = Short.toString(oldApprovals.get(approval.getKey()));
     206             :       }
     207             :     }
     208           1 :     labelTypes.byLabel(approval.getKey()).ifPresent(lt -> a.description = lt.getName());
     209           1 :     if (approval.getValue() != null) {
     210           1 :       a.value = Short.toString(approval.getValue());
     211             :     }
     212           1 :     return a;
     213             :   }
     214             : 
     215             :   private Supplier<ApprovalAttribute[]> approvalsAttributeSupplier(
     216             :       final Change change,
     217             :       Map<String, ApprovalInfo> newApprovals,
     218             :       final Map<String, ApprovalInfo> oldApprovals) {
     219          61 :     final Map<String, Short> approvals = convertApprovalsMap(newApprovals);
     220          61 :     return Suppliers.memoize(
     221             :         () -> {
     222           1 :           Project.NameKey nameKey = change.getProject();
     223           1 :           LabelTypes labelTypes =
     224           1 :               projectCache.get(nameKey).orElseThrow(illegalState(nameKey)).getLabelTypes();
     225           1 :           if (approvals.size() > 0) {
     226           1 :             ApprovalAttribute[] r = new ApprovalAttribute[approvals.size()];
     227           1 :             int i = 0;
     228           1 :             for (Map.Entry<String, Short> approval : approvals.entrySet()) {
     229           1 :               r[i++] =
     230           1 :                   getApprovalAttribute(labelTypes, approval, convertApprovalsMap(oldApprovals));
     231           1 :             }
     232           1 :             return r;
     233             :           }
     234           0 :           return null;
     235             :         });
     236             :   }
     237             : 
     238             :   @Nullable
     239             :   String[] hashtagArray(Collection<String> hashtags) {
     240           1 :     if (hashtags != null && !hashtags.isEmpty()) {
     241           1 :       return Sets.newHashSet(hashtags).toArray(new String[hashtags.size()]);
     242             :     }
     243           1 :     return null;
     244             :   }
     245             : 
     246             :   @Override
     247             :   public void onAssigneeChanged(AssigneeChangedListener.Event ev) {
     248             :     try {
     249           3 :       ChangeNotes notes = getNotes(ev.getChange());
     250           3 :       Change change = notes.getChange();
     251           3 :       AssigneeChangedEvent event = new AssigneeChangedEvent(change);
     252             : 
     253           3 :       event.change = changeAttributeSupplier(change, notes);
     254           3 :       event.changer = accountAttributeSupplier(ev.getWho());
     255           3 :       event.oldAssignee = accountAttributeSupplier(ev.getOldAssignee());
     256             : 
     257           3 :       dispatcher.run(d -> d.postEvent(change, event));
     258           0 :     } catch (StorageException e) {
     259           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     260           3 :     }
     261           3 :   }
     262             : 
     263             :   @Override
     264             :   public void onTopicEdited(TopicEditedListener.Event ev) {
     265             :     try {
     266          26 :       ChangeNotes notes = getNotes(ev.getChange());
     267          26 :       Change change = notes.getChange();
     268          26 :       TopicChangedEvent event = new TopicChangedEvent(change);
     269             : 
     270          26 :       event.change = changeAttributeSupplier(change, notes);
     271          26 :       event.changer = accountAttributeSupplier(ev.getWho());
     272          26 :       event.oldTopic = ev.getOldTopic();
     273             : 
     274          26 :       dispatcher.run(d -> d.postEvent(change, event));
     275           0 :     } catch (StorageException e) {
     276           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     277          26 :     }
     278          26 :   }
     279             : 
     280             :   @Override
     281             :   public void onRevisionCreated(RevisionCreatedListener.Event ev) {
     282             :     try {
     283          95 :       ChangeNotes notes = getNotes(ev.getChange());
     284          95 :       Change change = notes.getChange();
     285          95 :       PatchSet patchSet = getPatchSet(notes, ev.getRevision());
     286          95 :       PatchSetCreatedEvent event = new PatchSetCreatedEvent(change);
     287             : 
     288          95 :       event.change = changeAttributeSupplier(change, notes);
     289          95 :       event.patchSet = patchSetAttributeSupplier(change, patchSet);
     290          95 :       event.uploader = accountAttributeSupplier(ev.getWho());
     291             : 
     292          95 :       dispatcher.run(d -> d.postEvent(change, event));
     293           0 :     } catch (StorageException e) {
     294           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     295          95 :     }
     296          95 :   }
     297             : 
     298             :   @Override
     299             :   public void onReviewerDeleted(ReviewerDeletedListener.Event ev) {
     300             :     try {
     301          12 :       ChangeNotes notes = getNotes(ev.getChange());
     302          12 :       Change change = notes.getChange();
     303          12 :       ReviewerDeletedEvent event = new ReviewerDeletedEvent(change);
     304          12 :       event.change = changeAttributeSupplier(change, notes);
     305          12 :       event.patchSet = patchSetAttributeSupplier(change, psUtil.current(notes));
     306          12 :       event.reviewer = accountAttributeSupplier(ev.getReviewer());
     307          12 :       event.remover = accountAttributeSupplier(ev.getWho());
     308          12 :       event.comment = ev.getComment();
     309          12 :       event.approvals =
     310          12 :           approvalsAttributeSupplier(change, ev.getNewApprovals(), ev.getOldApprovals());
     311             : 
     312          12 :       dispatcher.run(d -> d.postEvent(change, event));
     313           0 :     } catch (StorageException e) {
     314           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     315          12 :     }
     316          12 :   }
     317             : 
     318             :   @Override
     319             :   public void onReviewersAdded(ReviewerAddedListener.Event ev) {
     320             :     try {
     321          26 :       ChangeNotes notes = getNotes(ev.getChange());
     322          26 :       Change change = notes.getChange();
     323          26 :       ReviewerAddedEvent event = new ReviewerAddedEvent(change);
     324             : 
     325          26 :       event.change = changeAttributeSupplier(change, notes);
     326          26 :       event.patchSet = patchSetAttributeSupplier(change, psUtil.current(notes));
     327          26 :       event.adder = accountAttributeSupplier(ev.getWho());
     328          26 :       for (AccountInfo reviewer : ev.getReviewers()) {
     329          26 :         event.reviewer = accountAttributeSupplier(reviewer);
     330          26 :         dispatcher.run(d -> d.postEvent(event));
     331          26 :       }
     332           0 :     } catch (StorageException e) {
     333           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     334          26 :     }
     335          26 :   }
     336             : 
     337             :   @Override
     338             :   public void onNewProjectCreated(NewProjectCreatedListener.Event ev) {
     339         135 :     ProjectCreatedEvent event = new ProjectCreatedEvent();
     340         135 :     event.projectName = ev.getProjectName();
     341         135 :     event.headName = ev.getHeadName();
     342             : 
     343         135 :     dispatcher.run(d -> d.postEvent(event.getProjectNameKey(), event));
     344         135 :   }
     345             : 
     346             :   @Override
     347             :   public void onHeadUpdated(HeadUpdatedListener.Event ev) {
     348           1 :     ProjectHeadUpdatedEvent event = new ProjectHeadUpdatedEvent();
     349           1 :     event.projectName = ev.getProjectName();
     350           1 :     event.oldHead = ev.getOldHeadName();
     351           1 :     event.newHead = ev.getNewHeadName();
     352             : 
     353           1 :     dispatcher.run(d -> d.postEvent(event.getProjectNameKey(), event));
     354           1 :   }
     355             : 
     356             :   @Override
     357             :   public void onHashtagsEdited(HashtagsEditedListener.Event ev) {
     358             :     try {
     359           1 :       ChangeNotes notes = getNotes(ev.getChange());
     360           1 :       Change change = notes.getChange();
     361           1 :       HashtagsChangedEvent event = new HashtagsChangedEvent(change);
     362             : 
     363           1 :       event.change = changeAttributeSupplier(change, notes);
     364           1 :       event.editor = accountAttributeSupplier(ev.getWho());
     365           1 :       event.hashtags = hashtagArray(ev.getHashtags());
     366           1 :       event.added = hashtagArray(ev.getAddedHashtags());
     367           1 :       event.removed = hashtagArray(ev.getRemovedHashtags());
     368             : 
     369           1 :       dispatcher.run(d -> d.postEvent(change, event));
     370           0 :     } catch (StorageException e) {
     371           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     372           1 :     }
     373           1 :   }
     374             : 
     375             :   @Override
     376             :   public void onGitReferenceUpdated(GitReferenceUpdatedListener.Event ev) {
     377         138 :     RefUpdatedEvent event = new RefUpdatedEvent();
     378         138 :     if (ev.getUpdater() != null) {
     379         138 :       event.submitter = accountAttributeSupplier(ev.getUpdater());
     380             :     }
     381         138 :     final BranchNameKey refName = BranchNameKey.create(ev.getProjectName(), ev.getRefName());
     382         138 :     event.refUpdate =
     383         138 :         Suppliers.memoize(
     384             :             () ->
     385         115 :                 eventFactory.asRefUpdateAttribute(
     386         115 :                     ObjectId.fromString(ev.getOldObjectId()),
     387         115 :                     ObjectId.fromString(ev.getNewObjectId()),
     388             :                     refName));
     389         138 :     dispatcher.run(d -> d.postEvent(refName, event));
     390         138 :   }
     391             : 
     392             :   @Override
     393             :   public void onCommentAdded(CommentAddedListener.Event ev) {
     394             :     try {
     395          61 :       ChangeNotes notes = getNotes(ev.getChange());
     396          61 :       Change change = notes.getChange();
     397          61 :       PatchSet ps = getPatchSet(notes, ev.getRevision());
     398          61 :       CommentAddedEvent event = new CommentAddedEvent(change);
     399             : 
     400          61 :       event.change = changeAttributeSupplier(change, notes);
     401          61 :       event.author = accountAttributeSupplier(ev.getWho());
     402          61 :       event.patchSet = patchSetAttributeSupplier(change, ps);
     403          61 :       event.comment = ev.getComment();
     404          61 :       event.approvals = approvalsAttributeSupplier(change, ev.getApprovals(), ev.getOldApprovals());
     405             : 
     406          61 :       dispatcher.run(d -> d.postEvent(change, event));
     407           0 :     } catch (StorageException e) {
     408           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     409          61 :     }
     410          61 :   }
     411             : 
     412             :   @Override
     413             :   public void onChangeRestored(ChangeRestoredListener.Event ev) {
     414             :     try {
     415           7 :       ChangeNotes notes = getNotes(ev.getChange());
     416           7 :       Change change = notes.getChange();
     417           7 :       ChangeRestoredEvent event = new ChangeRestoredEvent(change);
     418             : 
     419           7 :       event.change = changeAttributeSupplier(change, notes);
     420           7 :       event.restorer = accountAttributeSupplier(ev.getWho());
     421           7 :       event.patchSet = patchSetAttributeSupplier(change, psUtil.current(notes));
     422           7 :       event.reason = ev.getReason();
     423             : 
     424           7 :       dispatcher.run(d -> d.postEvent(change, event));
     425           0 :     } catch (StorageException e) {
     426           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     427           7 :     }
     428           7 :   }
     429             : 
     430             :   @Override
     431             :   public void onChangeMerged(ChangeMergedListener.Event ev) {
     432             :     try {
     433          51 :       ChangeNotes notes = getNotes(ev.getChange());
     434          51 :       Change change = notes.getChange();
     435          51 :       ChangeMergedEvent event = new ChangeMergedEvent(change);
     436             : 
     437          51 :       event.change = changeAttributeSupplier(change, notes);
     438          51 :       event.submitter = accountAttributeSupplier(ev.getWho());
     439          51 :       event.patchSet = patchSetAttributeSupplier(change, psUtil.current(notes));
     440          51 :       event.newRev = ev.getNewRevisionId();
     441             : 
     442          51 :       dispatcher.run(d -> d.postEvent(change, event));
     443           0 :     } catch (StorageException e) {
     444           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     445          51 :     }
     446          51 :   }
     447             : 
     448             :   @Override
     449             :   public void onChangeAbandoned(ChangeAbandonedListener.Event ev) {
     450             :     try {
     451          16 :       ChangeNotes notes = getNotes(ev.getChange());
     452          16 :       Change change = notes.getChange();
     453          16 :       ChangeAbandonedEvent event = new ChangeAbandonedEvent(change);
     454             : 
     455          16 :       event.change = changeAttributeSupplier(change, notes);
     456          16 :       event.abandoner = accountAttributeSupplier(ev.getWho());
     457          16 :       event.patchSet = patchSetAttributeSupplier(change, psUtil.current(notes));
     458          16 :       event.reason = ev.getReason();
     459             : 
     460          16 :       dispatcher.run(d -> d.postEvent(change, event));
     461           0 :     } catch (StorageException e) {
     462           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     463          16 :     }
     464          16 :   }
     465             : 
     466             :   @Override
     467             :   public void onWorkInProgressStateChanged(WorkInProgressStateChangedListener.Event ev) {
     468             :     try {
     469           8 :       ChangeNotes notes = getNotes(ev.getChange());
     470           8 :       Change change = notes.getChange();
     471           8 :       PatchSet patchSet = getPatchSet(notes, ev.getRevision());
     472           8 :       WorkInProgressStateChangedEvent event = new WorkInProgressStateChangedEvent(change);
     473             : 
     474           8 :       event.change = changeAttributeSupplier(change, notes);
     475           8 :       event.changer = accountAttributeSupplier(ev.getWho());
     476           8 :       event.patchSet = patchSetAttributeSupplier(change, patchSet);
     477             : 
     478           8 :       dispatcher.run(d -> d.postEvent(change, event));
     479           0 :     } catch (StorageException e) {
     480           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     481           8 :     }
     482           8 :   }
     483             : 
     484             :   @Override
     485             :   public void onPrivateStateChanged(PrivateStateChangedListener.Event ev) {
     486             :     try {
     487          12 :       ChangeNotes notes = getNotes(ev.getChange());
     488          12 :       Change change = notes.getChange();
     489          12 :       PatchSet patchSet = getPatchSet(notes, ev.getRevision());
     490          12 :       PrivateStateChangedEvent event = new PrivateStateChangedEvent(change);
     491             : 
     492          12 :       event.change = changeAttributeSupplier(change, notes);
     493          12 :       event.changer = accountAttributeSupplier(ev.getWho());
     494          12 :       event.patchSet = patchSetAttributeSupplier(change, patchSet);
     495             : 
     496          12 :       dispatcher.run(d -> d.postEvent(change, event));
     497           0 :     } catch (StorageException e) {
     498           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     499          12 :     }
     500          12 :   }
     501             : 
     502             :   @Override
     503             :   public void onVoteDeleted(VoteDeletedListener.Event ev) {
     504             :     try {
     505           9 :       ChangeNotes notes = getNotes(ev.getChange());
     506           9 :       Change change = notes.getChange();
     507           9 :       VoteDeletedEvent event = new VoteDeletedEvent(change);
     508             : 
     509           9 :       event.change = changeAttributeSupplier(change, notes);
     510           9 :       event.patchSet = patchSetAttributeSupplier(change, psUtil.current(notes));
     511           9 :       event.comment = ev.getMessage();
     512           9 :       event.reviewer = accountAttributeSupplier(ev.getReviewer());
     513           9 :       event.remover = accountAttributeSupplier(ev.getWho());
     514           9 :       event.approvals = approvalsAttributeSupplier(change, ev.getApprovals(), ev.getOldApprovals());
     515             : 
     516           9 :       dispatcher.run(d -> d.postEvent(change, event));
     517           0 :     } catch (StorageException e) {
     518           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     519           9 :     }
     520           9 :   }
     521             : 
     522             :   @Override
     523             :   public void onChangeDeleted(ChangeDeletedListener.Event ev) {
     524             :     try {
     525           7 :       ChangeNotes notes = getNotes(ev.getChange());
     526           7 :       Change change = notes.getChange();
     527           7 :       ChangeDeletedEvent event = new ChangeDeletedEvent(change);
     528             : 
     529           7 :       event.change = changeAttributeSupplier(change, notes);
     530           7 :       event.deleter = accountAttributeSupplier(ev.getWho());
     531             : 
     532           7 :       dispatcher.run(d -> d.postEvent(change, event));
     533           0 :     } catch (StorageException e) {
     534           0 :       logger.atSevere().withCause(e).log("Failed to dispatch event");
     535           7 :     }
     536           7 :   }
     537             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750