LCOV - code coverage report
Current view: top level - httpd/raw - IndexPreloadingUtil.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 58 80 72.5 %
Date: 2022-11-19 15:00:39 Functions: 7 10 70.0 %

          Line data    Source code
       1             : // Copyright (C) 2020 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.httpd.raw;
      16             : 
      17             : import static com.google.common.collect.ImmutableList.toImmutableList;
      18             : 
      19             : import com.google.common.collect.ImmutableList;
      20             : import com.google.common.collect.ImmutableSet;
      21             : import com.google.common.primitives.Ints;
      22             : import com.google.gerrit.common.Nullable;
      23             : import com.google.gerrit.common.UsedAt;
      24             : import com.google.gerrit.common.UsedAt.Project;
      25             : import com.google.gerrit.extensions.api.config.Server;
      26             : import com.google.gerrit.extensions.client.ListChangesOption;
      27             : import com.google.gerrit.extensions.restapi.RestApiException;
      28             : import com.google.gerrit.extensions.restapi.Url;
      29             : import java.net.URI;
      30             : import java.net.URISyntaxException;
      31             : import java.util.ArrayList;
      32             : import java.util.List;
      33             : import java.util.Optional;
      34             : import java.util.regex.Matcher;
      35             : import java.util.regex.Pattern;
      36             : import java.util.stream.Stream;
      37             : 
      38             : /** Helper for generating preloading parts of {@code index.html}. */
      39             : @UsedAt(Project.GOOGLE)
      40             : public class IndexPreloadingUtil {
      41           1 :   enum RequestedPage {
      42           1 :     CHANGE,
      43           1 :     DIFF,
      44           1 :     DASHBOARD,
      45           1 :     PAGE_WITHOUT_PRELOADING,
      46             :   }
      47             : 
      48             :   public static final String CHANGE_CANONICAL_PATH = "/c/(?<project>.+)/\\+/(?<changeNum>\\d+)";
      49             :   public static final String BASE_PATCH_NUM_PATH_PART = "(/(-?\\d+|edit)(\\.\\.(\\d+|edit))?)";
      50           3 :   public static final Pattern CHANGE_URL_PATTERN =
      51           3 :       Pattern.compile(CHANGE_CANONICAL_PATH + BASE_PATCH_NUM_PATH_PART + "?" + "/?$");
      52           3 :   public static final Pattern DIFF_URL_PATTERN =
      53           3 :       Pattern.compile(CHANGE_CANONICAL_PATH + BASE_PATCH_NUM_PATH_PART + "(/(.+))" + "/?$");
      54           3 :   public static final Pattern DASHBOARD_PATTERN = Pattern.compile("/dashboard/self$");
      55             :   public static final String ROOT_PATH = "/";
      56             : 
      57             :   // These queries should be kept in sync with PolyGerrit:
      58             :   // polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts
      59             :   public static final String DASHBOARD_HAS_UNPUBLISHED_DRAFTS_QUERY = "has:draft limit:10";
      60             :   public static final String YOUR_TURN = "attention:${user} limit:25";
      61             :   public static final String DASHBOARD_ASSIGNED_QUERY =
      62             :       "assignee:${user} (-is:wip OR " + "owner:self OR assignee:self) is:open limit:25";
      63             :   public static final String DASHBOARD_WORK_IN_PROGRESS_QUERY =
      64             :       "is:open owner:${user} is:wip limit:25";
      65             :   public static final String DASHBOARD_OUTGOING_QUERY = "is:open owner:${user} -is:wip limit:25";
      66             :   public static final String DASHBOARD_INCOMING_QUERY =
      67             :       "is:open -owner:${user} -is:wip (reviewer:${user} OR assignee:${user}) limit:25";
      68             :   public static final String CC_QUERY = "is:open -is:wip cc:${user} limit:10";
      69             :   public static final String DASHBOARD_RECENTLY_CLOSED_QUERY =
      70             :       "is:closed (-is:wip OR owner:self) "
      71             :           + "(owner:${user} OR reviewer:${user} OR assignee:${user} "
      72             :           + "OR cc:${user}) -age:4w limit:10";
      73             :   public static final String NEW_USER = "owner:${user} limit:1";
      74             : 
      75           3 :   public static final String SELF_DASHBOARD_HAS_UNPUBLISHED_DRAFTS_QUERY =
      76           3 :       DASHBOARD_HAS_UNPUBLISHED_DRAFTS_QUERY.replaceAll("\\$\\{user}", "self");
      77           3 :   public static final String SELF_YOUR_TURN = YOUR_TURN.replaceAll("\\$\\{user}", "self");
      78           3 :   public static final String SELF_DASHBOARD_ASSIGNED_QUERY =
      79           3 :       DASHBOARD_ASSIGNED_QUERY.replaceAll("\\$\\{user}", "self");
      80           3 :   public static final ImmutableList<String> SELF_DASHBOARD_QUERIES =
      81           3 :       Stream.of(
      82             :               DASHBOARD_WORK_IN_PROGRESS_QUERY,
      83             :               DASHBOARD_OUTGOING_QUERY,
      84             :               DASHBOARD_INCOMING_QUERY,
      85             :               CC_QUERY,
      86             :               DASHBOARD_RECENTLY_CLOSED_QUERY,
      87             :               NEW_USER)
      88           3 :           .map(query -> query.replaceAll("\\$\\{user}", "self"))
      89           3 :           .collect(toImmutableList());
      90           3 :   public static final ImmutableSet<ListChangesOption> DASHBOARD_OPTIONS =
      91           3 :       ImmutableSet.of(
      92             :           ListChangesOption.LABELS,
      93             :           ListChangesOption.DETAILED_ACCOUNTS,
      94             :           ListChangesOption.SUBMIT_REQUIREMENTS);
      95             : 
      96           3 :   public static final ImmutableSet<ListChangesOption> CHANGE_DETAIL_OPTIONS =
      97           3 :       ImmutableSet.of(
      98             :           ListChangesOption.ALL_COMMITS,
      99             :           ListChangesOption.ALL_REVISIONS,
     100             :           ListChangesOption.CHANGE_ACTIONS,
     101             :           ListChangesOption.DETAILED_LABELS,
     102             :           ListChangesOption.DOWNLOAD_COMMANDS,
     103             :           ListChangesOption.MESSAGES,
     104             :           ListChangesOption.SUBMITTABLE,
     105             :           ListChangesOption.WEB_LINKS,
     106             :           ListChangesOption.SKIP_DIFFSTAT,
     107             :           ListChangesOption.SUBMIT_REQUIREMENTS);
     108             : 
     109             :   @Nullable
     110             :   public static String getPath(@Nullable String requestedURL) throws URISyntaxException {
     111           1 :     if (requestedURL == null) {
     112           1 :       return null;
     113             :     }
     114           1 :     URI uri = new URI(requestedURL);
     115           1 :     return uri.getPath();
     116             :   }
     117             : 
     118             :   public static RequestedPage parseRequestedPage(@Nullable String requestedPath) {
     119           1 :     if (requestedPath == null) {
     120           1 :       return RequestedPage.PAGE_WITHOUT_PRELOADING;
     121             :     }
     122             : 
     123           1 :     Optional<String> changeRequestsPath =
     124           1 :         computeChangeRequestsPath(requestedPath, RequestedPage.CHANGE);
     125           1 :     if (changeRequestsPath.isPresent()) {
     126           1 :       return RequestedPage.CHANGE;
     127             :     }
     128             : 
     129           1 :     changeRequestsPath = computeChangeRequestsPath(requestedPath, RequestedPage.DIFF);
     130           1 :     if (changeRequestsPath.isPresent()) {
     131           0 :       return RequestedPage.DIFF;
     132             :     }
     133             : 
     134           1 :     Matcher dashboardMatcher = IndexPreloadingUtil.DASHBOARD_PATTERN.matcher(requestedPath);
     135           1 :     if (dashboardMatcher.matches()) {
     136           1 :       return RequestedPage.DASHBOARD;
     137             :     }
     138             : 
     139           1 :     if (ROOT_PATH.equals(requestedPath)) {
     140           1 :       return RequestedPage.DASHBOARD;
     141             :     }
     142             : 
     143           1 :     return RequestedPage.PAGE_WITHOUT_PRELOADING;
     144             :   }
     145             : 
     146             :   public static Optional<String> computeChangeRequestsPath(
     147             :       String requestedURL, RequestedPage page) {
     148             :     Matcher matcher;
     149           1 :     switch (page) {
     150             :       case CHANGE:
     151           1 :         matcher = CHANGE_URL_PATTERN.matcher(requestedURL);
     152           1 :         break;
     153             :       case DIFF:
     154           1 :         matcher = DIFF_URL_PATTERN.matcher(requestedURL);
     155           1 :         break;
     156             :       case DASHBOARD:
     157             :       case PAGE_WITHOUT_PRELOADING:
     158             :       default:
     159           0 :         return Optional.empty();
     160             :     }
     161             : 
     162           1 :     if (matcher.matches()) {
     163           1 :       Integer changeId = Ints.tryParse(matcher.group("changeNum"));
     164           1 :       if (changeId != null) {
     165           1 :         return Optional.of("changes/" + Url.encode(matcher.group("project")) + "~" + changeId);
     166             :       }
     167             :     }
     168           1 :     return Optional.empty();
     169             :   }
     170             : 
     171             :   public static Optional<Integer> computeChangeNum(String requestedURL, RequestedPage page) {
     172             :     Matcher matcher;
     173           1 :     switch (page) {
     174             :       case CHANGE:
     175           1 :         matcher = CHANGE_URL_PATTERN.matcher(requestedURL);
     176           1 :         break;
     177             :       case DIFF:
     178           0 :         matcher = DIFF_URL_PATTERN.matcher(requestedURL);
     179           0 :         break;
     180             :       case DASHBOARD:
     181             :       case PAGE_WITHOUT_PRELOADING:
     182             :       default:
     183           0 :         return Optional.empty();
     184             :     }
     185             : 
     186           1 :     if (matcher.matches()) {
     187           1 :       Integer changeNum = Ints.tryParse(matcher.group("changeNum"));
     188           1 :       if (changeNum != null) {
     189           1 :         return Optional.of(changeNum);
     190             :       }
     191             :     }
     192           0 :     return Optional.empty();
     193             :   }
     194             : 
     195             :   public static List<String> computeDashboardQueryList(Server serverApi) throws RestApiException {
     196           0 :     List<String> queryList = new ArrayList<>();
     197           0 :     queryList.add(SELF_DASHBOARD_HAS_UNPUBLISHED_DRAFTS_QUERY);
     198           0 :     if (isEnabledAttentionSet(serverApi)) {
     199           0 :       queryList.add(SELF_YOUR_TURN);
     200             :     }
     201           0 :     if (isEnabledAssignee(serverApi)) {
     202           0 :       queryList.add(SELF_DASHBOARD_ASSIGNED_QUERY);
     203             :     }
     204             : 
     205           0 :     queryList.addAll(SELF_DASHBOARD_QUERIES);
     206             : 
     207           0 :     return queryList;
     208             :   }
     209             : 
     210             :   private static boolean isEnabledAttentionSet(Server serverApi) throws RestApiException {
     211           0 :     return serverApi.getInfo() != null
     212           0 :         && serverApi.getInfo().change != null
     213           0 :         && serverApi.getInfo().change.enableAttentionSet != null
     214           0 :         && serverApi.getInfo().change.enableAttentionSet;
     215             :   }
     216             : 
     217             :   private static boolean isEnabledAssignee(Server serverApi) throws RestApiException {
     218           0 :     return serverApi.getInfo() != null
     219           0 :         && serverApi.getInfo().change != null
     220           0 :         && serverApi.getInfo().change.enableAssignee != null
     221           0 :         && serverApi.getInfo().change.enableAssignee;
     222             :   }
     223             : 
     224             :   private IndexPreloadingUtil() {}
     225             : }

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