// Copyright (C) 2014 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.gerrit.server.util; import com.google.common.primitives.Ints; import com.google.gerrit.common.Nullable; import java.util.regex.Matcher; import java.util.regex.Pattern; public final class RangeUtil { private static final Pattern RANGE_PATTERN = Pattern.compile("(>|>=|=|<|<=|)([+-]?\\d+)$"); private RangeUtil() {} public static class Range { /** The prefix of the query, before the range component. */ public final String prefix; /** The minimum value specified in the query, inclusive. */ public final int min; /** The maximum value specified in the query, inclusive. */ public final int max; public Range(String prefix, int min, int max) { this.prefix = prefix; this.min = min; this.max = max; } } /** * Determine the range of values being requested in the given query. * * @param rangeQuery the raw query, e.g. "added:>12345" * @param minValue the minimum possible value for the field, inclusive * @param maxValue the maximum possible value for the field, inclusive * @return the calculated {@link Range}, or null if the query is invalid */ @Nullable public static Range getRange(String rangeQuery, int minValue, int maxValue) { Matcher m = RANGE_PATTERN.matcher(rangeQuery); String prefix; String test; Integer queryInt; if (m.find()) { prefix = rangeQuery.substring(0, m.start()); test = m.group(1); queryInt = value(m.group(2)); if (queryInt == null) { return null; } } else { return null; } return getRange(prefix, test, queryInt, minValue, maxValue); } /** * Determine the range of values being requested in the given query. * * @param prefix a prefix string which is copied into the range * @param test the test operator, one of >, >=, =, <, or <= * @param queryInt the integer being queried * @param minValue the minimum possible value for the field, inclusive * @param maxValue the maximum possible value for the field, inclusive * @return the calculated {@link Range} */ public static Range getRange( String prefix, String test, int queryInt, int minValue, int maxValue) { int min, max; switch (test) { case "=": default: min = max = queryInt; break; case ">": min = Ints.saturatedCast(queryInt + 1L); max = maxValue; break; case ">=": min = queryInt; max = maxValue; break; case "<": min = minValue; max = Ints.saturatedCast(queryInt - 1L); break; case "<=": min = minValue; max = queryInt; break; } return new Range(prefix, min, max); } private static Integer value(String value) { if (value.startsWith("+")) { value = value.substring(1); } return Ints.tryParse(value); } }