Line data Source code
1 : // Copyright (C) 2013 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.api.changes;
16 :
17 : import static com.google.gerrit.server.api.ApiUtil.asRestApiException;
18 :
19 : import com.google.common.collect.ImmutableListMultimap;
20 : import com.google.common.collect.ListMultimap;
21 : import com.google.gerrit.common.Nullable;
22 : import com.google.gerrit.extensions.api.changes.AbandonInput;
23 : import com.google.gerrit.extensions.api.changes.ApplyPatchPatchSetInput;
24 : import com.google.gerrit.extensions.api.changes.AssigneeInput;
25 : import com.google.gerrit.extensions.api.changes.AttentionSetApi;
26 : import com.google.gerrit.extensions.api.changes.AttentionSetInput;
27 : import com.google.gerrit.extensions.api.changes.ChangeApi;
28 : import com.google.gerrit.extensions.api.changes.ChangeEditApi;
29 : import com.google.gerrit.extensions.api.changes.ChangeMessageApi;
30 : import com.google.gerrit.extensions.api.changes.Changes;
31 : import com.google.gerrit.extensions.api.changes.FixInput;
32 : import com.google.gerrit.extensions.api.changes.HashtagsInput;
33 : import com.google.gerrit.extensions.api.changes.IncludedInInfo;
34 : import com.google.gerrit.extensions.api.changes.MoveInput;
35 : import com.google.gerrit.extensions.api.changes.RebaseInput;
36 : import com.google.gerrit.extensions.api.changes.RestoreInput;
37 : import com.google.gerrit.extensions.api.changes.RevertInput;
38 : import com.google.gerrit.extensions.api.changes.ReviewerApi;
39 : import com.google.gerrit.extensions.api.changes.ReviewerInfo;
40 : import com.google.gerrit.extensions.api.changes.ReviewerInput;
41 : import com.google.gerrit.extensions.api.changes.ReviewerResult;
42 : import com.google.gerrit.extensions.api.changes.RevisionApi;
43 : import com.google.gerrit.extensions.api.changes.SubmittedTogetherInfo;
44 : import com.google.gerrit.extensions.api.changes.SubmittedTogetherOption;
45 : import com.google.gerrit.extensions.api.changes.TopicInput;
46 : import com.google.gerrit.extensions.client.ListChangesOption;
47 : import com.google.gerrit.extensions.common.AccountInfo;
48 : import com.google.gerrit.extensions.common.ChangeInfo;
49 : import com.google.gerrit.extensions.common.ChangeInfoDifference;
50 : import com.google.gerrit.extensions.common.ChangeMessageInfo;
51 : import com.google.gerrit.extensions.common.CommentInfo;
52 : import com.google.gerrit.extensions.common.CommitMessageInput;
53 : import com.google.gerrit.extensions.common.Input;
54 : import com.google.gerrit.extensions.common.InputWithMessage;
55 : import com.google.gerrit.extensions.common.MergePatchSetInput;
56 : import com.google.gerrit.extensions.common.PureRevertInfo;
57 : import com.google.gerrit.extensions.common.RevertSubmissionInfo;
58 : import com.google.gerrit.extensions.common.RobotCommentInfo;
59 : import com.google.gerrit.extensions.common.SubmitRequirementInput;
60 : import com.google.gerrit.extensions.common.SubmitRequirementResultInfo;
61 : import com.google.gerrit.extensions.common.SuggestedReviewerInfo;
62 : import com.google.gerrit.extensions.registration.DynamicMap;
63 : import com.google.gerrit.extensions.restapi.BadRequestException;
64 : import com.google.gerrit.extensions.restapi.IdString;
65 : import com.google.gerrit.extensions.restapi.Response;
66 : import com.google.gerrit.extensions.restapi.RestApiException;
67 : import com.google.gerrit.server.DynamicOptions;
68 : import com.google.gerrit.server.change.ChangeMessageResource;
69 : import com.google.gerrit.server.change.ChangeResource;
70 : import com.google.gerrit.server.change.WorkInProgressOp;
71 : import com.google.gerrit.server.restapi.change.Abandon;
72 : import com.google.gerrit.server.restapi.change.AddToAttentionSet;
73 : import com.google.gerrit.server.restapi.change.ApplyPatch;
74 : import com.google.gerrit.server.restapi.change.AttentionSet;
75 : import com.google.gerrit.server.restapi.change.ChangeIncludedIn;
76 : import com.google.gerrit.server.restapi.change.ChangeMessages;
77 : import com.google.gerrit.server.restapi.change.Check;
78 : import com.google.gerrit.server.restapi.change.CheckSubmitRequirement;
79 : import com.google.gerrit.server.restapi.change.CreateMergePatchSet;
80 : import com.google.gerrit.server.restapi.change.DeleteAssignee;
81 : import com.google.gerrit.server.restapi.change.DeleteChange;
82 : import com.google.gerrit.server.restapi.change.DeletePrivate;
83 : import com.google.gerrit.server.restapi.change.GetAssignee;
84 : import com.google.gerrit.server.restapi.change.GetChange;
85 : import com.google.gerrit.server.restapi.change.GetHashtags;
86 : import com.google.gerrit.server.restapi.change.GetMetaDiff;
87 : import com.google.gerrit.server.restapi.change.GetPastAssignees;
88 : import com.google.gerrit.server.restapi.change.GetPureRevert;
89 : import com.google.gerrit.server.restapi.change.GetTopic;
90 : import com.google.gerrit.server.restapi.change.Index;
91 : import com.google.gerrit.server.restapi.change.ListChangeComments;
92 : import com.google.gerrit.server.restapi.change.ListChangeDrafts;
93 : import com.google.gerrit.server.restapi.change.ListChangeRobotComments;
94 : import com.google.gerrit.server.restapi.change.ListReviewers;
95 : import com.google.gerrit.server.restapi.change.Move;
96 : import com.google.gerrit.server.restapi.change.PostHashtags;
97 : import com.google.gerrit.server.restapi.change.PostPrivate;
98 : import com.google.gerrit.server.restapi.change.PostReviewers;
99 : import com.google.gerrit.server.restapi.change.PutAssignee;
100 : import com.google.gerrit.server.restapi.change.PutMessage;
101 : import com.google.gerrit.server.restapi.change.PutTopic;
102 : import com.google.gerrit.server.restapi.change.Rebase;
103 : import com.google.gerrit.server.restapi.change.Restore;
104 : import com.google.gerrit.server.restapi.change.Revert;
105 : import com.google.gerrit.server.restapi.change.RevertSubmission;
106 : import com.google.gerrit.server.restapi.change.Reviewers;
107 : import com.google.gerrit.server.restapi.change.Revisions;
108 : import com.google.gerrit.server.restapi.change.SetReadyForReview;
109 : import com.google.gerrit.server.restapi.change.SetWorkInProgress;
110 : import com.google.gerrit.server.restapi.change.SubmittedTogether;
111 : import com.google.gerrit.server.restapi.change.SuggestChangeReviewers;
112 : import com.google.gerrit.util.cli.CmdLineParser;
113 : import com.google.inject.Inject;
114 : import com.google.inject.Injector;
115 : import com.google.inject.Provider;
116 : import com.google.inject.Singleton;
117 : import com.google.inject.assistedinject.Assisted;
118 : import java.util.EnumSet;
119 : import java.util.List;
120 : import java.util.Map;
121 : import java.util.Set;
122 : import org.kohsuke.args4j.CmdLineException;
123 :
124 : class ChangeApiImpl implements ChangeApi {
125 : interface Factory {
126 : ChangeApiImpl create(ChangeResource change);
127 : }
128 :
129 : private final Changes changeApi;
130 : private final Reviewers reviewers;
131 : private final Revisions revisions;
132 : private final ReviewerApiImpl.Factory reviewerApi;
133 : private final RevisionApiImpl.Factory revisionApi;
134 : private final ChangeMessageApiImpl.Factory changeMessageApi;
135 : private final ChangeMessages changeMessages;
136 : private final SuggestChangeReviewers suggestReviewers;
137 : private final ListReviewers listReviewers;
138 : private final ChangeResource change;
139 : private final Abandon abandon;
140 : private final Revert revert;
141 : private final RevertSubmission revertSubmission;
142 : private final Restore restore;
143 : private final CreateMergePatchSet updateByMerge;
144 : private final ApplyPatch applyPatch;
145 : private final Provider<SubmittedTogether> submittedTogether;
146 : private final Rebase.CurrentRevision rebase;
147 : private final DeleteChange deleteChange;
148 : private final GetTopic getTopic;
149 : private final PutTopic putTopic;
150 : private final ChangeIncludedIn includedIn;
151 : private final PostReviewers postReviewers;
152 : private final Provider<GetChange> getChangeProvider;
153 : private final Provider<GetMetaDiff> getMetaDiffProvider;
154 : private final PostHashtags postHashtags;
155 : private final GetHashtags getHashtags;
156 : private final AttentionSet attentionSet;
157 : private final AttentionSetApiImpl.Factory attentionSetApi;
158 : private final AddToAttentionSet addToAttentionSet;
159 : private final PutAssignee putAssignee;
160 : private final GetAssignee getAssignee;
161 : private final GetPastAssignees getPastAssignees;
162 : private final DeleteAssignee deleteAssignee;
163 : private final Provider<ListChangeComments> listCommentsProvider;
164 : private final ListChangeRobotComments listChangeRobotComments;
165 : private final Provider<ListChangeDrafts> listDraftsProvider;
166 : private final ChangeEditApiImpl.Factory changeEditApi;
167 : private final Check check;
168 : private final Provider<CheckSubmitRequirement> checkSubmitRequirementProvider;
169 : private final Index index;
170 : private final Move move;
171 : private final PostPrivate postPrivate;
172 : private final DeletePrivate deletePrivate;
173 : private final SetWorkInProgress setWip;
174 : private final SetReadyForReview setReady;
175 : private final PutMessage putMessage;
176 : private final Provider<GetPureRevert> getPureRevertProvider;
177 : private final DynamicOptionParser dynamicOptionParser;
178 : private final Injector injector;
179 : private final DynamicMap<DynamicOptions.DynamicBean> dynamicBeans;
180 :
181 : @Inject
182 : ChangeApiImpl(
183 : Changes changeApi,
184 : Reviewers reviewers,
185 : Revisions revisions,
186 : ReviewerApiImpl.Factory reviewerApi,
187 : RevisionApiImpl.Factory revisionApi,
188 : ChangeMessageApiImpl.Factory changeMessageApi,
189 : ChangeMessages changeMessages,
190 : SuggestChangeReviewers suggestReviewers,
191 : ListReviewers listReviewers,
192 : Abandon abandon,
193 : Revert revert,
194 : RevertSubmission revertSubmission,
195 : Restore restore,
196 : CreateMergePatchSet updateByMerge,
197 : ApplyPatch applyPatch,
198 : Provider<SubmittedTogether> submittedTogether,
199 : Rebase.CurrentRevision rebase,
200 : DeleteChange deleteChange,
201 : GetTopic getTopic,
202 : PutTopic putTopic,
203 : ChangeIncludedIn includedIn,
204 : PostReviewers postReviewers,
205 : Provider<GetChange> getChangeProvider,
206 : Provider<GetMetaDiff> getMetaDiffProvider,
207 : PostHashtags postHashtags,
208 : GetHashtags getHashtags,
209 : AttentionSet attentionSet,
210 : AttentionSetApiImpl.Factory attentionSetApi,
211 : AddToAttentionSet addToAttentionSet,
212 : PutAssignee putAssignee,
213 : GetAssignee getAssignee,
214 : GetPastAssignees getPastAssignees,
215 : DeleteAssignee deleteAssignee,
216 : Provider<ListChangeComments> listCommentsProvider,
217 : ListChangeRobotComments listChangeRobotComments,
218 : Provider<ListChangeDrafts> listDraftsProvider,
219 : ChangeEditApiImpl.Factory changeEditApi,
220 : Check check,
221 : Provider<CheckSubmitRequirement> checkSubmitRequirement,
222 : Index index,
223 : Move move,
224 : PostPrivate postPrivate,
225 : DeletePrivate deletePrivate,
226 : SetWorkInProgress setWip,
227 : SetReadyForReview setReady,
228 : PutMessage putMessage,
229 : Provider<GetPureRevert> getPureRevertProvider,
230 : DynamicOptionParser dynamicOptionParser,
231 : @Assisted ChangeResource change,
232 : Injector injector,
233 91 : DynamicMap<DynamicOptions.DynamicBean> dynamicBeans) {
234 91 : this.changeApi = changeApi;
235 91 : this.revert = revert;
236 91 : this.revertSubmission = revertSubmission;
237 91 : this.reviewers = reviewers;
238 91 : this.revisions = revisions;
239 91 : this.reviewerApi = reviewerApi;
240 91 : this.revisionApi = revisionApi;
241 91 : this.changeMessageApi = changeMessageApi;
242 91 : this.changeMessages = changeMessages;
243 91 : this.suggestReviewers = suggestReviewers;
244 91 : this.listReviewers = listReviewers;
245 91 : this.abandon = abandon;
246 91 : this.restore = restore;
247 91 : this.updateByMerge = updateByMerge;
248 91 : this.applyPatch = applyPatch;
249 91 : this.submittedTogether = submittedTogether;
250 91 : this.rebase = rebase;
251 91 : this.deleteChange = deleteChange;
252 91 : this.getTopic = getTopic;
253 91 : this.putTopic = putTopic;
254 91 : this.includedIn = includedIn;
255 91 : this.postReviewers = postReviewers;
256 91 : this.getChangeProvider = getChangeProvider;
257 91 : this.getMetaDiffProvider = getMetaDiffProvider;
258 91 : this.postHashtags = postHashtags;
259 91 : this.getHashtags = getHashtags;
260 91 : this.attentionSet = attentionSet;
261 91 : this.attentionSetApi = attentionSetApi;
262 91 : this.addToAttentionSet = addToAttentionSet;
263 91 : this.putAssignee = putAssignee;
264 91 : this.getAssignee = getAssignee;
265 91 : this.getPastAssignees = getPastAssignees;
266 91 : this.deleteAssignee = deleteAssignee;
267 91 : this.listCommentsProvider = listCommentsProvider;
268 91 : this.listChangeRobotComments = listChangeRobotComments;
269 91 : this.listDraftsProvider = listDraftsProvider;
270 91 : this.changeEditApi = changeEditApi;
271 91 : this.check = check;
272 91 : this.checkSubmitRequirementProvider = checkSubmitRequirement;
273 91 : this.index = index;
274 91 : this.move = move;
275 91 : this.postPrivate = postPrivate;
276 91 : this.deletePrivate = deletePrivate;
277 91 : this.setWip = setWip;
278 91 : this.setReady = setReady;
279 91 : this.putMessage = putMessage;
280 91 : this.getPureRevertProvider = getPureRevertProvider;
281 91 : this.dynamicOptionParser = dynamicOptionParser;
282 91 : this.change = change;
283 91 : this.injector = injector;
284 91 : this.dynamicBeans = dynamicBeans;
285 91 : }
286 :
287 : @Override
288 : public String id() {
289 8 : return Integer.toString(change.getId().get());
290 : }
291 :
292 : @Override
293 : public RevisionApi revision(String id) throws RestApiException {
294 : try {
295 79 : return revisionApi.create(revisions.parse(change, IdString.fromDecoded(id)));
296 0 : } catch (Exception e) {
297 0 : throw asRestApiException("Cannot parse revision", e);
298 : }
299 : }
300 :
301 : @Override
302 : public ReviewerApi reviewer(String id) throws RestApiException {
303 : try {
304 15 : return reviewerApi.create(reviewers.parse(change, IdString.fromDecoded(id)));
305 1 : } catch (Exception e) {
306 1 : throw asRestApiException("Cannot parse reviewer", e);
307 : }
308 : }
309 :
310 : @Override
311 : public void abandon(AbandonInput in) throws RestApiException {
312 : try {
313 19 : abandon.apply(change, in);
314 1 : } catch (Exception e) {
315 1 : throw asRestApiException("Cannot abandon change", e);
316 19 : }
317 19 : }
318 :
319 : @Override
320 : public void restore(RestoreInput in) throws RestApiException {
321 : try {
322 6 : restore.apply(change, in);
323 1 : } catch (Exception e) {
324 1 : throw asRestApiException("Cannot restore change", e);
325 6 : }
326 6 : }
327 :
328 : @Override
329 : public void move(MoveInput in) throws RestApiException {
330 : try {
331 2 : move.apply(change, in);
332 1 : } catch (Exception e) {
333 1 : throw asRestApiException("Cannot move change", e);
334 2 : }
335 2 : }
336 :
337 : @Override
338 : public void setPrivate(boolean value, @Nullable String message) throws RestApiException {
339 : try {
340 15 : InputWithMessage input = new InputWithMessage(message);
341 15 : if (value) {
342 15 : postPrivate.apply(change, input);
343 : } else {
344 1 : deletePrivate.apply(change, input);
345 : }
346 2 : } catch (Exception e) {
347 2 : throw asRestApiException("Cannot change private status", e);
348 15 : }
349 15 : }
350 :
351 : @Override
352 : public void setWorkInProgress(@Nullable String message) throws RestApiException {
353 : try {
354 10 : setWip.apply(change, new WorkInProgressOp.Input(message));
355 1 : } catch (Exception e) {
356 1 : throw asRestApiException("Cannot set work in progress state", e);
357 10 : }
358 10 : }
359 :
360 : @Override
361 : public void setReadyForReview(@Nullable String message) throws RestApiException {
362 : try {
363 7 : setReady.apply(change, new WorkInProgressOp.Input(message));
364 1 : } catch (Exception e) {
365 1 : throw asRestApiException("Cannot set ready for review state", e);
366 7 : }
367 7 : }
368 :
369 : @Override
370 : public ChangeApi revert(RevertInput in) throws RestApiException {
371 : try {
372 14 : return changeApi.id(revert.apply(change, in).value()._number);
373 2 : } catch (Exception e) {
374 2 : throw asRestApiException("Cannot revert change", e);
375 : }
376 : }
377 :
378 : @Override
379 : public RevertSubmissionInfo revertSubmission(RevertInput in) throws RestApiException {
380 : try {
381 1 : return revertSubmission.apply(change, in).value();
382 2 : } catch (Exception e) {
383 2 : throw asRestApiException("Cannot revert a change submission", e);
384 : }
385 : }
386 :
387 : @Override
388 : public ChangeInfo createMergePatchSet(MergePatchSetInput in) throws RestApiException {
389 : try {
390 1 : return updateByMerge.apply(change, in).value();
391 1 : } catch (Exception e) {
392 1 : throw asRestApiException("Cannot update change by merge", e);
393 : }
394 : }
395 :
396 : @Override
397 : public ChangeInfo applyPatch(ApplyPatchPatchSetInput in) throws RestApiException {
398 : try {
399 1 : return applyPatch.apply(change, in).value();
400 1 : } catch (Exception e) {
401 1 : throw asRestApiException("Cannot apply patch", e);
402 : }
403 : }
404 :
405 : @Override
406 : public SubmittedTogetherInfo submittedTogether(
407 : EnumSet<ListChangesOption> listOptions, EnumSet<SubmittedTogetherOption> submitOptions)
408 : throws RestApiException {
409 : try {
410 10 : return submittedTogether
411 10 : .get()
412 10 : .addListChangesOption(listOptions)
413 10 : .addSubmittedTogetherOption(submitOptions)
414 10 : .applyInfo(change);
415 0 : } catch (Exception e) {
416 0 : throw asRestApiException("Cannot query submittedTogether", e);
417 : }
418 : }
419 :
420 : @Override
421 : public void rebase(RebaseInput in) throws RestApiException {
422 : try {
423 4 : rebase.apply(change, in);
424 1 : } catch (Exception e) {
425 1 : throw asRestApiException("Cannot rebase change", e);
426 4 : }
427 4 : }
428 :
429 : @Override
430 : public void delete() throws RestApiException {
431 : try {
432 9 : deleteChange.apply(change, null);
433 1 : } catch (Exception e) {
434 1 : throw asRestApiException("Cannot delete change", e);
435 9 : }
436 9 : }
437 :
438 : @Override
439 : public String topic() throws RestApiException {
440 : try {
441 3 : return getTopic.apply(change).value();
442 0 : } catch (Exception e) {
443 0 : throw asRestApiException("Cannot get topic", e);
444 : }
445 : }
446 :
447 : @Override
448 : public void topic(String topic) throws RestApiException {
449 11 : TopicInput in = new TopicInput();
450 11 : in.topic = topic;
451 : try {
452 11 : putTopic.apply(change, in);
453 1 : } catch (Exception e) {
454 1 : throw asRestApiException("Cannot set topic", e);
455 11 : }
456 11 : }
457 :
458 : @Override
459 : public IncludedInInfo includedIn() throws RestApiException {
460 : try {
461 1 : return includedIn.apply(change).value();
462 0 : } catch (Exception e) {
463 0 : throw asRestApiException("Could not extract IncludedIn data", e);
464 : }
465 : }
466 :
467 : @Override
468 : public ReviewerResult addReviewer(ReviewerInput in) throws RestApiException {
469 : try {
470 30 : return postReviewers.apply(change, in).value();
471 0 : } catch (Exception e) {
472 0 : throw asRestApiException("Cannot add change reviewer", e);
473 : }
474 : }
475 :
476 : @Override
477 : public SuggestedReviewersRequest suggestReviewers() throws RestApiException {
478 1 : return new SuggestedReviewersRequest() {
479 : @Override
480 : public List<SuggestedReviewerInfo> get() throws RestApiException {
481 1 : return ChangeApiImpl.this.suggestReviewers(this);
482 : }
483 : };
484 : }
485 :
486 : private List<SuggestedReviewerInfo> suggestReviewers(SuggestedReviewersRequest r)
487 : throws RestApiException {
488 : try {
489 1 : suggestReviewers.setQuery(r.getQuery());
490 1 : suggestReviewers.setLimit(r.getLimit());
491 1 : suggestReviewers.setExcludeGroups(r.getExcludeGroups());
492 1 : suggestReviewers.setReviewerState(r.getReviewerState());
493 1 : return suggestReviewers.apply(change).value();
494 1 : } catch (Exception e) {
495 1 : throw asRestApiException("Cannot retrieve suggested reviewers", e);
496 : }
497 : }
498 :
499 : @Override
500 : public List<ReviewerInfo> reviewers() throws RestApiException {
501 : try {
502 2 : return listReviewers.apply(change).value();
503 0 : } catch (Exception e) {
504 0 : throw asRestApiException("Cannot retrieve reviewers", e);
505 : }
506 : }
507 :
508 : @Override
509 : public ChangeInfo get(
510 : EnumSet<ListChangesOption> options, ImmutableListMultimap<String, String> pluginOptions)
511 : throws RestApiException {
512 67 : try (DynamicOptions dynamicOptions = new DynamicOptions(injector, dynamicBeans)) {
513 67 : GetChange getChange = getChangeProvider.get();
514 67 : options.forEach(getChange::addOption);
515 67 : dynamicOptionParser.parseDynamicOptions(getChange, pluginOptions, dynamicOptions);
516 67 : return getChange.apply(change).value();
517 0 : } catch (Exception e) {
518 0 : throw asRestApiException("Cannot retrieve change", e);
519 : }
520 : }
521 :
522 : @Override
523 : public ChangeInfoDifference metaDiff(
524 : @Nullable String oldMetaRevId,
525 : @Nullable String newMetaRevId,
526 : EnumSet<ListChangesOption> options,
527 : ImmutableListMultimap<String, String> pluginOptions)
528 : throws RestApiException {
529 1 : try (DynamicOptions dynamicOptions = new DynamicOptions(injector, dynamicBeans)) {
530 1 : GetMetaDiff metaDiff = getMetaDiffProvider.get();
531 1 : metaDiff.setOldMetaRevId(oldMetaRevId);
532 1 : metaDiff.setNewMetaRevId(newMetaRevId);
533 1 : options.forEach(metaDiff::addOption);
534 1 : dynamicOptionParser.parseDynamicOptions(metaDiff, pluginOptions, dynamicOptions);
535 1 : return metaDiff.apply(change).value();
536 0 : } catch (Exception e) {
537 0 : throw asRestApiException("Cannot retrieve metaDiff", e);
538 : }
539 : }
540 :
541 : @Override
542 : public ChangeEditApi edit() throws RestApiException {
543 27 : return changeEditApi.create(change);
544 : }
545 :
546 : @Override
547 : public void setMessage(CommitMessageInput in) throws RestApiException {
548 : try {
549 4 : putMessage.apply(change, in);
550 1 : } catch (Exception e) {
551 1 : throw asRestApiException("Cannot edit commit message", e);
552 4 : }
553 4 : }
554 :
555 : @Override
556 : public void setHashtags(HashtagsInput input) throws RestApiException {
557 : try {
558 5 : postHashtags.apply(change, input);
559 1 : } catch (Exception e) {
560 1 : throw asRestApiException("Cannot post hashtags", e);
561 5 : }
562 5 : }
563 :
564 : @Override
565 : public Set<String> getHashtags() throws RestApiException {
566 : try {
567 4 : return getHashtags.apply(change).value();
568 0 : } catch (Exception e) {
569 0 : throw asRestApiException("Cannot get hashtags", e);
570 : }
571 : }
572 :
573 : @Override
574 : public AccountInfo addToAttentionSet(AttentionSetInput input) throws RestApiException {
575 : try {
576 6 : return addToAttentionSet.apply(change, input).value();
577 1 : } catch (Exception e) {
578 1 : throw asRestApiException("Cannot add to attention set", e);
579 : }
580 : }
581 :
582 : @Override
583 : public AttentionSetApi attention(String id) throws RestApiException {
584 : try {
585 13 : return attentionSetApi.create(attentionSet.parse(change, IdString.fromDecoded(id)));
586 1 : } catch (Exception e) {
587 1 : throw asRestApiException("Cannot parse account", e);
588 : }
589 : }
590 :
591 : @Override
592 : public AccountInfo setAssignee(AssigneeInput input) throws RestApiException {
593 : try {
594 6 : return putAssignee.apply(change, input).value();
595 1 : } catch (Exception e) {
596 1 : throw asRestApiException("Cannot set assignee", e);
597 : }
598 : }
599 :
600 : @Nullable
601 : @Override
602 : public AccountInfo getAssignee() throws RestApiException {
603 : try {
604 1 : Response<AccountInfo> r = getAssignee.apply(change);
605 1 : return r.isNone() ? null : r.value();
606 0 : } catch (Exception e) {
607 0 : throw asRestApiException("Cannot get assignee", e);
608 : }
609 : }
610 :
611 : @Override
612 : public List<AccountInfo> getPastAssignees() throws RestApiException {
613 : try {
614 1 : return getPastAssignees.apply(change).value();
615 0 : } catch (Exception e) {
616 0 : throw asRestApiException("Cannot get past assignees", e);
617 : }
618 : }
619 :
620 : @Nullable
621 : @Override
622 : public AccountInfo deleteAssignee() throws RestApiException {
623 : try {
624 1 : Response<AccountInfo> r = deleteAssignee.apply(change, null);
625 1 : return r.isNone() ? null : r.value();
626 0 : } catch (Exception e) {
627 0 : throw asRestApiException("Cannot delete assignee", e);
628 : }
629 : }
630 :
631 : @Override
632 : public CommentsRequest commentsRequest() {
633 11 : return new CommentsRequest() {
634 : @Override
635 : public Map<String, List<CommentInfo>> get() throws RestApiException {
636 : try {
637 10 : ListChangeComments listComments = listCommentsProvider.get();
638 10 : listComments.setContext(this.getContext());
639 10 : listComments.setContextPadding(this.getContextPadding());
640 10 : return listComments.apply(change).value();
641 0 : } catch (Exception e) {
642 0 : throw asRestApiException("Cannot get comments", e);
643 : }
644 : }
645 :
646 : @Override
647 : public List<CommentInfo> getAsList() throws RestApiException {
648 : try {
649 2 : ListChangeComments listComments = listCommentsProvider.get();
650 2 : listComments.setContext(this.getContext());
651 2 : listComments.setContextPadding(this.getContextPadding());
652 2 : return listComments.getComments(change);
653 0 : } catch (Exception e) {
654 0 : throw asRestApiException("Cannot get comments", e);
655 : }
656 : }
657 : };
658 : }
659 :
660 : @Override
661 : public Map<String, List<RobotCommentInfo>> robotComments() throws RestApiException {
662 : try {
663 3 : return listChangeRobotComments.apply(change).value();
664 0 : } catch (Exception e) {
665 0 : throw asRestApiException("Cannot get robot comments", e);
666 : }
667 : }
668 :
669 : @Override
670 : public DraftsRequest draftsRequest() {
671 7 : return new DraftsRequest() {
672 : @Override
673 : public Map<String, List<CommentInfo>> get() throws RestApiException {
674 : try {
675 6 : ListChangeDrafts listDrafts = listDraftsProvider.get();
676 6 : listDrafts.setContext(this.getContext());
677 6 : listDrafts.setContextPadding(this.getContextPadding());
678 6 : return listDrafts.apply(change).value();
679 0 : } catch (Exception e) {
680 0 : throw asRestApiException("Cannot get drafts", e);
681 : }
682 : }
683 :
684 : @Override
685 : public List<CommentInfo> getAsList() throws RestApiException {
686 : try {
687 2 : ListChangeDrafts listDrafts = listDraftsProvider.get();
688 2 : listDrafts.setContext(this.getContext());
689 2 : listDrafts.setContextPadding(this.getContextPadding());
690 2 : return listDrafts.getComments(change);
691 1 : } catch (Exception e) {
692 1 : throw asRestApiException("Cannot get drafts", e);
693 : }
694 : }
695 : };
696 : }
697 :
698 : @Override
699 : public ChangeInfo check() throws RestApiException {
700 : try {
701 0 : return check.apply(change).value();
702 0 : } catch (Exception e) {
703 0 : throw asRestApiException("Cannot check change", e);
704 : }
705 : }
706 :
707 : @Override
708 : public ChangeInfo check(FixInput fix) throws RestApiException {
709 : try {
710 : // TODO(dborowitz): Convert to RetryingRestModifyView. Needs to plumb BatchUpdate.Factory into
711 : // ConsistencyChecker.
712 1 : return check.apply(change, fix).value();
713 0 : } catch (Exception e) {
714 0 : throw asRestApiException("Cannot check change", e);
715 : }
716 : }
717 :
718 : @Override
719 : public CheckSubmitRequirementRequest checkSubmitRequirementRequest() {
720 1 : return new CheckSubmitRequirementRequest() {
721 : @Override
722 : public SubmitRequirementResultInfo get() throws RestApiException {
723 : try {
724 1 : CheckSubmitRequirement check = checkSubmitRequirementProvider.get();
725 1 : check.setSrName(this.srName());
726 1 : check.setRefsConfigChangeId(this.getRefsConfigChangeId());
727 1 : return check.apply(change, null).value();
728 1 : } catch (Exception e) {
729 1 : throw asRestApiException("Cannot check submit requirement", e);
730 : }
731 : }
732 : };
733 : }
734 :
735 : @Override
736 : public SubmitRequirementResultInfo checkSubmitRequirement(SubmitRequirementInput input)
737 : throws RestApiException {
738 : try {
739 1 : return checkSubmitRequirementProvider.get().apply(change, input).value();
740 0 : } catch (Exception e) {
741 0 : throw asRestApiException("Cannot check submit requirement", e);
742 : }
743 : }
744 :
745 : @Override
746 : public void index() throws RestApiException {
747 : try {
748 6 : index.apply(change, new Input());
749 0 : } catch (Exception e) {
750 0 : throw asRestApiException("Cannot index change", e);
751 6 : }
752 6 : }
753 :
754 : @Override
755 : public PureRevertInfo pureRevert() throws RestApiException {
756 1 : return pureRevert(null);
757 : }
758 :
759 : @Override
760 : public PureRevertInfo pureRevert(@Nullable String claimedOriginal) throws RestApiException {
761 : try {
762 1 : GetPureRevert getPureRevert = getPureRevertProvider.get();
763 1 : getPureRevert.setClaimedOriginal(claimedOriginal);
764 1 : return getPureRevert.apply(change).value();
765 1 : } catch (Exception e) {
766 1 : throw asRestApiException("Cannot compute pure revert", e);
767 : }
768 : }
769 :
770 : @Override
771 : public List<ChangeMessageInfo> messages() throws RestApiException {
772 : try {
773 7 : return changeMessages.list().apply(change).value();
774 0 : } catch (Exception e) {
775 0 : throw asRestApiException("Cannot list change messages", e);
776 : }
777 : }
778 :
779 : @Override
780 : public ChangeMessageApi message(String id) throws RestApiException {
781 : try {
782 2 : ChangeMessageResource resource = changeMessages.parse(change, IdString.fromDecoded(id));
783 2 : return changeMessageApi.create(resource);
784 1 : } catch (Exception e) {
785 1 : throw asRestApiException("Cannot parse change message " + id, e);
786 : }
787 : }
788 :
789 : @Singleton
790 : static class DynamicOptionParser {
791 : private final CmdLineParser.Factory cmdLineParserFactory;
792 :
793 : @Inject
794 149 : DynamicOptionParser(CmdLineParser.Factory cmdLineParserFactory) {
795 149 : this.cmdLineParserFactory = cmdLineParserFactory;
796 149 : }
797 :
798 : void parseDynamicOptions(
799 : Object bean, ListMultimap<String, String> pluginOptions, DynamicOptions dynamicOptions)
800 : throws BadRequestException {
801 68 : CmdLineParser clp = cmdLineParserFactory.create(bean);
802 68 : dynamicOptions.setBean(bean);
803 68 : dynamicOptions.startLifecycleListeners();
804 68 : dynamicOptions.parseDynamicBeans(clp);
805 68 : dynamicOptions.setDynamicBeans();
806 68 : dynamicOptions.onBeanParseStart();
807 : try {
808 68 : clp.parseOptionMap(pluginOptions);
809 0 : } catch (CmdLineException | NumberFormatException e) {
810 0 : throw new BadRequestException(e.getMessage(), e);
811 68 : }
812 68 : dynamicOptions.onBeanParseEnd();
813 68 : }
814 : }
815 : }
|