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 : }
|