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.change; 16 : 17 : import static java.util.Objects.requireNonNull; 18 : import static java.util.stream.Collectors.joining; 19 : 20 : import com.google.auto.value.AutoValue; 21 : import com.google.common.collect.ImmutableList; 22 : import com.google.common.collect.ImmutableSetMultimap; 23 : import com.google.gerrit.common.Nullable; 24 : import com.google.gerrit.entities.Account; 25 : import com.google.gerrit.extensions.api.changes.NotifyHandling; 26 : import com.google.gerrit.extensions.api.changes.NotifyInfo; 27 : import com.google.gerrit.extensions.api.changes.RecipientType; 28 : import com.google.gerrit.extensions.restapi.BadRequestException; 29 : import com.google.gerrit.extensions.restapi.UnprocessableEntityException; 30 : import com.google.gerrit.server.account.AccountResolver; 31 : import com.google.inject.Inject; 32 : import com.google.inject.Singleton; 33 : import java.io.IOException; 34 : import java.util.ArrayList; 35 : import java.util.List; 36 : import java.util.Map; 37 : import org.eclipse.jgit.errors.ConfigInvalidException; 38 : 39 : @Singleton 40 : public class NotifyResolver { 41 : @AutoValue 42 112 : public abstract static class Result { 43 : public static Result none() { 44 58 : return create(NotifyHandling.NONE); 45 : } 46 : 47 : public static Result all() { 48 112 : return create(NotifyHandling.ALL); 49 : } 50 : 51 : public static Result create(NotifyHandling notifyHandling) { 52 112 : return create(notifyHandling, ImmutableSetMultimap.of()); 53 : } 54 : 55 : public static Result create( 56 : NotifyHandling handling, ImmutableSetMultimap<RecipientType, Account.Id> recipients) { 57 112 : return new AutoValue_NotifyResolver_Result(handling, recipients); 58 : } 59 : 60 : public abstract NotifyHandling handling(); 61 : 62 : public abstract ImmutableSetMultimap<RecipientType, Account.Id> accounts(); 63 : 64 : public Result withHandling(NotifyHandling notifyHandling) { 65 37 : return create(notifyHandling, accounts()); 66 : } 67 : 68 : public boolean shouldNotify() { 69 106 : return !accounts().isEmpty() || handling().compareTo(NotifyHandling.NONE) > 0; 70 : } 71 : } 72 : 73 : private final AccountResolver accountResolver; 74 : 75 : @Inject 76 149 : NotifyResolver(AccountResolver accountResolver) { 77 149 : this.accountResolver = accountResolver; 78 149 : } 79 : 80 : public Result resolve( 81 : NotifyHandling handling, @Nullable Map<RecipientType, NotifyInfo> notifyDetails) 82 : throws BadRequestException, IOException, ConfigInvalidException { 83 93 : requireNonNull(handling); 84 93 : ImmutableSetMultimap.Builder<RecipientType, Account.Id> b = ImmutableSetMultimap.builder(); 85 93 : if (notifyDetails != null) { 86 11 : for (Map.Entry<RecipientType, NotifyInfo> e : notifyDetails.entrySet()) { 87 11 : b.putAll(e.getKey(), find(e.getValue().accounts)); 88 11 : } 89 : } 90 93 : return Result.create(handling, b.build()); 91 : } 92 : 93 : private ImmutableList<Account.Id> find(@Nullable List<String> inputs) 94 : throws BadRequestException, IOException, ConfigInvalidException { 95 11 : if (inputs == null || inputs.isEmpty()) { 96 8 : return ImmutableList.of(); 97 : } 98 5 : ImmutableList.Builder<Account.Id> r = ImmutableList.builder(); 99 5 : List<String> problems = new ArrayList<>(inputs.size()); 100 5 : for (String nameOrEmail : inputs) { 101 : try { 102 5 : r.add(accountResolver.resolve(nameOrEmail).asUnique().account().id()); 103 0 : } catch (UnprocessableEntityException e) { 104 0 : problems.add(e.getMessage()); 105 5 : } 106 5 : } 107 : 108 5 : if (!problems.isEmpty()) { 109 0 : throw new BadRequestException( 110 : "Some accounts that should be notified could not be resolved: " 111 0 : + problems.stream().collect(joining("\n"))); 112 : } 113 : 114 5 : return r.build(); 115 : } 116 : }