LCOV - code coverage report
Current view: top level - server/project - RefFilter.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 39 41 95.1 %
Date: 2022-11-19 15:00:39 Functions: 11 11 100.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.project;
      16             : 
      17             : import static com.google.common.collect.ImmutableList.toImmutableList;
      18             : 
      19             : import com.google.common.base.Strings;
      20             : import com.google.common.collect.ImmutableList;
      21             : import com.google.gerrit.extensions.api.projects.RefInfo;
      22             : import com.google.gerrit.extensions.restapi.BadRequestException;
      23             : import dk.brics.automaton.RegExp;
      24             : import dk.brics.automaton.RunAutomaton;
      25             : import java.util.List;
      26             : import java.util.Locale;
      27             : import java.util.stream.Stream;
      28             : 
      29             : public class RefFilter<T extends RefInfo> {
      30             :   private final String prefix;
      31             :   private String matchSubstring;
      32             :   private String matchRegex;
      33             :   private int start;
      34             :   private int limit;
      35             : 
      36          10 :   public RefFilter(String prefix) {
      37          10 :     this.prefix = prefix;
      38          10 :   }
      39             : 
      40             :   public RefFilter<T> subString(String subString) {
      41          10 :     this.matchSubstring = subString;
      42          10 :     return this;
      43             :   }
      44             : 
      45             :   public RefFilter<T> regex(String regex) {
      46          10 :     this.matchRegex = regex;
      47          10 :     return this;
      48             :   }
      49             : 
      50             :   public RefFilter<T> start(int start) {
      51          10 :     this.start = start;
      52          10 :     return this;
      53             :   }
      54             : 
      55             :   public RefFilter<T> limit(int limit) {
      56          10 :     this.limit = limit;
      57          10 :     return this;
      58             :   }
      59             : 
      60             :   public ImmutableList<T> filter(List<T> refs) throws BadRequestException {
      61          10 :     if (!Strings.isNullOrEmpty(matchSubstring) && !Strings.isNullOrEmpty(matchRegex)) {
      62           2 :       throw new BadRequestException("specify exactly one of m/r");
      63             :     }
      64          10 :     Stream<T> results = refs.stream();
      65          10 :     if (!Strings.isNullOrEmpty(matchSubstring)) {
      66           2 :       String lowercaseSubstring = matchSubstring.toLowerCase(Locale.US);
      67           2 :       results = results.filter(refInfo -> matchesSubstring(prefix, lowercaseSubstring, refInfo));
      68          10 :     } else if (!Strings.isNullOrEmpty(matchRegex)) {
      69           2 :       RunAutomaton a = parseRegex(matchRegex);
      70           2 :       results = results.filter(refInfo -> matchesRegex(prefix, a, refInfo));
      71             :     }
      72          10 :     if (start > 0) {
      73           2 :       results = results.skip(start);
      74             :     }
      75          10 :     if (limit > 0) {
      76           2 :       results = results.limit(limit);
      77             :     }
      78          10 :     return results.collect(toImmutableList());
      79             :   }
      80             : 
      81             :   private static <T extends RefInfo> boolean matchesSubstring(
      82             :       String prefix, String lowercaseSubstring, T refInfo) {
      83           2 :     String ref = refInfo.ref;
      84           2 :     if (ref.startsWith(prefix)) {
      85           2 :       ref = ref.substring(prefix.length());
      86             :     }
      87           2 :     ref = ref.toLowerCase(Locale.US);
      88           2 :     return ref.contains(lowercaseSubstring);
      89             :   }
      90             : 
      91             :   private static RunAutomaton parseRegex(String regex) throws BadRequestException {
      92           2 :     if (regex.startsWith("^")) {
      93           1 :       regex = regex.substring(1);
      94           1 :       if (regex.endsWith("$") && !regex.endsWith("\\$")) {
      95           1 :         regex = regex.substring(0, regex.length() - 1);
      96             :       }
      97             :     }
      98             :     try {
      99           2 :       return new RunAutomaton(new RegExp(regex).toAutomaton());
     100           0 :     } catch (IllegalArgumentException e) {
     101           0 :       throw new BadRequestException(e.getMessage());
     102             :     }
     103             :   }
     104             : 
     105             :   private static <T extends RefInfo> boolean matchesRegex(
     106             :       String prefix, RunAutomaton a, T refInfo) {
     107           2 :     String ref = refInfo.ref;
     108           2 :     if (ref.startsWith(prefix)) {
     109           2 :       ref = ref.substring(prefix.length());
     110             :     }
     111           2 :     return a.run(ref);
     112             :   }
     113             : }

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