LCOV - code coverage report
Current view: top level - server/change - SetHashtagsOp.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 57 60 95.0 %
Date: 2022-11-19 15:00:39 Functions: 9 10 90.0 %

          Line data    Source code
       1             : // Copyright (C) 2015 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 com.google.common.base.Preconditions.checkState;
      18             : import static com.google.gerrit.server.change.HashtagsUtil.extractTags;
      19             : 
      20             : import com.google.common.base.Joiner;
      21             : import com.google.common.collect.ImmutableSortedSet;
      22             : import com.google.common.collect.Ordering;
      23             : import com.google.gerrit.common.Nullable;
      24             : import com.google.gerrit.entities.Change;
      25             : import com.google.gerrit.extensions.api.changes.HashtagsInput;
      26             : import com.google.gerrit.extensions.restapi.AuthException;
      27             : import com.google.gerrit.extensions.restapi.BadRequestException;
      28             : import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
      29             : import com.google.gerrit.server.ChangeMessagesUtil;
      30             : import com.google.gerrit.server.change.HashtagsUtil.InvalidHashtagException;
      31             : import com.google.gerrit.server.extensions.events.HashtagsEdited;
      32             : import com.google.gerrit.server.notedb.ChangeNotes;
      33             : import com.google.gerrit.server.notedb.ChangeUpdate;
      34             : import com.google.gerrit.server.plugincontext.PluginSetContext;
      35             : import com.google.gerrit.server.update.BatchUpdateOp;
      36             : import com.google.gerrit.server.update.ChangeContext;
      37             : import com.google.gerrit.server.update.PostUpdateContext;
      38             : import com.google.gerrit.server.validators.HashtagValidationListener;
      39             : import com.google.gerrit.server.validators.ValidationException;
      40             : import com.google.inject.Inject;
      41             : import com.google.inject.assistedinject.Assisted;
      42             : import java.io.IOException;
      43             : import java.util.Collection;
      44             : import java.util.HashSet;
      45             : import java.util.Set;
      46             : 
      47             : public class SetHashtagsOp implements BatchUpdateOp {
      48             :   public interface Factory {
      49             :     SetHashtagsOp create(HashtagsInput input);
      50             :   }
      51             : 
      52             :   private final ChangeMessagesUtil cmUtil;
      53             :   private final PluginSetContext<HashtagValidationListener> validationListeners;
      54             :   private final HashtagsEdited hashtagsEdited;
      55             :   private final HashtagsInput input;
      56             : 
      57           8 :   private boolean fireEvent = true;
      58             : 
      59             :   private Change change;
      60             :   private Set<String> toAdd;
      61             :   private Set<String> toRemove;
      62             :   private ImmutableSortedSet<String> updatedHashtags;
      63             : 
      64             :   @Inject
      65             :   SetHashtagsOp(
      66             :       ChangeMessagesUtil cmUtil,
      67             :       PluginSetContext<HashtagValidationListener> validationListeners,
      68             :       HashtagsEdited hashtagsEdited,
      69           8 :       @Assisted @Nullable HashtagsInput input) {
      70           8 :     this.cmUtil = cmUtil;
      71           8 :     this.validationListeners = validationListeners;
      72           8 :     this.hashtagsEdited = hashtagsEdited;
      73           8 :     this.input = input;
      74           8 :   }
      75             : 
      76             :   public SetHashtagsOp setFireEvent(boolean fireEvent) {
      77           3 :     this.fireEvent = fireEvent;
      78           3 :     return this;
      79             :   }
      80             : 
      81             :   @Override
      82             :   public boolean updateChange(ChangeContext ctx)
      83             :       throws AuthException, BadRequestException, MethodNotAllowedException, IOException {
      84           8 :     if (input == null || (input.add == null && input.remove == null)) {
      85           0 :       updatedHashtags = ImmutableSortedSet.of();
      86           0 :       return false;
      87             :     }
      88             : 
      89           8 :     change = ctx.getChange();
      90           8 :     ChangeUpdate update = ctx.getUpdate(change.currentPatchSetId());
      91           8 :     ChangeNotes notes = update.getNotes().load();
      92             : 
      93             :     try {
      94           8 :       Set<String> existingHashtags = notes.getHashtags();
      95           8 :       Set<String> updated = new HashSet<>();
      96           8 :       toAdd = new HashSet<>(extractTags(input.add));
      97           8 :       toRemove = new HashSet<>(extractTags(input.remove));
      98             : 
      99           8 :       validationListeners.runEach(
     100           0 :           l -> l.validateHashtags(update.getChange(), toAdd, toRemove), ValidationException.class);
     101           8 :       updated.addAll(existingHashtags);
     102           8 :       toAdd.removeAll(existingHashtags);
     103           8 :       toRemove.retainAll(existingHashtags);
     104           8 :       if (updated()) {
     105           8 :         updated.addAll(toAdd);
     106           8 :         updated.removeAll(toRemove);
     107           8 :         update.setHashtags(updated);
     108           8 :         addMessage(ctx);
     109             :       }
     110             : 
     111           8 :       updatedHashtags = ImmutableSortedSet.copyOf(updated);
     112           8 :       return true;
     113           1 :     } catch (ValidationException | InvalidHashtagException e) {
     114           1 :       throw new BadRequestException(e.getMessage(), e);
     115             :     }
     116             :   }
     117             : 
     118             :   private void addMessage(ChangeContext ctx) {
     119           8 :     StringBuilder msg = new StringBuilder();
     120           8 :     appendHashtagMessage(msg, "added", toAdd);
     121           8 :     appendHashtagMessage(msg, "removed", toRemove);
     122           8 :     cmUtil.setChangeMessage(ctx, msg.toString(), ChangeMessagesUtil.TAG_SET_HASHTAGS);
     123           8 :   }
     124             : 
     125             :   private void appendHashtagMessage(StringBuilder b, String action, Set<String> hashtags) {
     126           8 :     if (isNullOrEmpty(hashtags)) {
     127           8 :       return;
     128             :     }
     129             : 
     130           8 :     if (b.length() > 0) {
     131           1 :       b.append("\n");
     132             :     }
     133           8 :     b.append("Hashtag");
     134           8 :     if (hashtags.size() > 1) {
     135           8 :       b.append("s");
     136             :     }
     137           8 :     b.append(" ");
     138           8 :     b.append(action);
     139           8 :     b.append(": ");
     140           8 :     b.append(Joiner.on(", ").join(Ordering.natural().sortedCopy(hashtags)));
     141           8 :   }
     142             : 
     143             :   @Override
     144             :   public void postUpdate(PostUpdateContext ctx) {
     145           8 :     if (updated() && fireEvent) {
     146           5 :       hashtagsEdited.fire(
     147           5 :           ctx.getChangeData(change),
     148           5 :           ctx.getAccount(),
     149             :           updatedHashtags,
     150             :           toAdd,
     151             :           toRemove,
     152           5 :           ctx.getWhen());
     153             :     }
     154           8 :   }
     155             : 
     156             :   public ImmutableSortedSet<String> getUpdatedHashtags() {
     157           5 :     checkState(updatedHashtags != null, "getUpdatedHashtags() only valid after executing op");
     158           5 :     return updatedHashtags;
     159             :   }
     160             : 
     161             :   private boolean updated() {
     162           8 :     return !isNullOrEmpty(toAdd) || !isNullOrEmpty(toRemove);
     163             :   }
     164             : 
     165             :   private static boolean isNullOrEmpty(Collection<?> coll) {
     166           8 :     return coll == null || coll.isEmpty();
     167             :   }
     168             : }

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