LCOV - code coverage report
Current view: top level - server/query/approval - ApprovalQueryBuilder.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 40 40 100.0 %
Date: 2022-11-19 15:00:39 Functions: 11 11 100.0 %

          Line data    Source code
       1             : // Copyright (C) 2021 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.query.approval;
      16             : 
      17             : import static java.util.stream.Collectors.joining;
      18             : 
      19             : import com.google.common.base.Enums;
      20             : import com.google.common.primitives.Ints;
      21             : import com.google.gerrit.entities.AccountGroup;
      22             : import com.google.gerrit.entities.GroupDescription;
      23             : import com.google.gerrit.extensions.client.ChangeKind;
      24             : import com.google.gerrit.index.query.Predicate;
      25             : import com.google.gerrit.index.query.QueryBuilder;
      26             : import com.google.gerrit.index.query.QueryParseException;
      27             : import com.google.gerrit.server.account.GroupControl;
      28             : import com.google.gerrit.server.group.GroupResolver;
      29             : import com.google.inject.Inject;
      30             : import java.util.Arrays;
      31             : import java.util.Optional;
      32             : 
      33             : public class ApprovalQueryBuilder extends QueryBuilder<ApprovalContext, ApprovalQueryBuilder> {
      34         148 :   private static final QueryBuilder.Definition<ApprovalContext, ApprovalQueryBuilder> mydef =
      35             :       new QueryBuilder.Definition<>(ApprovalQueryBuilder.class);
      36             : 
      37             :   private final MagicValuePredicate.Factory magicValuePredicate;
      38             :   private final UserInPredicate.Factory userInPredicate;
      39             :   private final GroupResolver groupResolver;
      40             :   private final GroupControl.Factory groupControl;
      41             :   private final ListOfFilesUnchangedPredicate listOfFilesUnchangedPredicate;
      42             : 
      43             :   @Inject
      44             :   protected ApprovalQueryBuilder(
      45             :       MagicValuePredicate.Factory magicValuePredicate,
      46             :       UserInPredicate.Factory userInPredicate,
      47             :       GroupResolver groupResolver,
      48             :       GroupControl.Factory groupControl,
      49             :       ListOfFilesUnchangedPredicate listOfFilesUnchangedPredicate) {
      50         148 :     super(mydef, null);
      51         148 :     this.magicValuePredicate = magicValuePredicate;
      52         148 :     this.userInPredicate = userInPredicate;
      53         148 :     this.groupResolver = groupResolver;
      54         148 :     this.groupControl = groupControl;
      55         148 :     this.listOfFilesUnchangedPredicate = listOfFilesUnchangedPredicate;
      56         148 :   }
      57             : 
      58             :   @Operator
      59             :   public Predicate<ApprovalContext> changekind(String value) throws QueryParseException {
      60          12 :     return parseEnumValue(ChangeKind.class, value)
      61          12 :         .map(ChangeKindPredicate::new)
      62          12 :         .orElseThrow(
      63             :             () ->
      64           1 :                 new QueryParseException(
      65           1 :                     String.format(
      66             :                         "%s is not a valid value for operator 'changekind'. Valid values: %s",
      67           1 :                         value, formatEnumValues(ChangeKind.class))));
      68             :   }
      69             : 
      70             :   @Operator
      71             :   public Predicate<ApprovalContext> is(String value) throws QueryParseException {
      72             :     // try to parse exact value
      73          16 :     Optional<Integer> exactValue = Optional.ofNullable(Ints.tryParse(value));
      74          16 :     if (exactValue.isPresent()) {
      75           3 :       return new ExactValuePredicate(exactValue.get().shortValue());
      76             :     }
      77             : 
      78             :     // try to parse magic value
      79          16 :     Optional<MagicValuePredicate.MagicValue> magicValue =
      80          16 :         parseEnumValue(MagicValuePredicate.MagicValue.class, value);
      81          16 :     if (magicValue.isPresent()) {
      82          16 :       return magicValuePredicate.create(magicValue.get());
      83             :     }
      84             : 
      85             :     // it's neither an exact value nor a magic value
      86           1 :     throw new QueryParseException(
      87           1 :         String.format(
      88             :             "%s is not a valid value for operator 'is'. Valid values: %s or integer",
      89           1 :             value, formatEnumValues(MagicValuePredicate.MagicValue.class)));
      90             :   }
      91             : 
      92             :   @Operator
      93             :   public Predicate<ApprovalContext> approverin(String group) throws QueryParseException {
      94           3 :     return userInPredicate.create(UserInPredicate.Field.APPROVER, parseGroupOrThrow(group));
      95             :   }
      96             : 
      97             :   @Operator
      98             :   public Predicate<ApprovalContext> uploaderin(String group) throws QueryParseException {
      99           4 :     return userInPredicate.create(UserInPredicate.Field.UPLOADER, parseGroupOrThrow(group));
     100             :   }
     101             : 
     102             :   @Operator
     103             :   public Predicate<ApprovalContext> has(String value) throws QueryParseException {
     104           2 :     if (value.equals("unchanged-files")) {
     105           2 :       return listOfFilesUnchangedPredicate;
     106             :     }
     107           1 :     throw error(
     108           1 :         String.format(
     109             :             "'%s' is not a valid value for operator 'has'."
     110             :                 + " The only valid value is 'unchanged-files'.",
     111             :             value));
     112             :   }
     113             : 
     114             :   private static <T extends Enum<T>> Optional<T> parseEnumValue(Class<T> clazz, String value) {
     115          17 :     return Optional.ofNullable(
     116          17 :         Enums.getIfPresent(clazz, value.toUpperCase().replace('-', '_')).orNull());
     117             :   }
     118             : 
     119             :   private <T extends Enum<T>> String formatEnumValues(Class<T> clazz) {
     120           1 :     return Arrays.stream(clazz.getEnumConstants())
     121           1 :         .map(Object::toString)
     122           1 :         .sorted()
     123           1 :         .collect(joining(", "));
     124             :   }
     125             : 
     126             :   private AccountGroup.UUID parseGroupOrThrow(String maybeUUID) throws QueryParseException {
     127           5 :     GroupDescription.Basic g = groupResolver.parseId(maybeUUID);
     128           5 :     if (g == null || !groupControl.controlFor(g).isVisible()) {
     129           3 :       throw error("Group " + maybeUUID + " not found");
     130             :     }
     131           5 :     return g.getGroupUUID();
     132             :   }
     133             : }

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