summaryrefslogtreecommitdiff
path: root/src/main/java/com/android/vts/util/FilterUtil.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/android/vts/util/FilterUtil.java')
-rw-r--r--src/main/java/com/android/vts/util/FilterUtil.java537
1 files changed, 0 insertions, 537 deletions
diff --git a/src/main/java/com/android/vts/util/FilterUtil.java b/src/main/java/com/android/vts/util/FilterUtil.java
deleted file mode 100644
index 5a567e5..0000000
--- a/src/main/java/com/android/vts/util/FilterUtil.java
+++ /dev/null
@@ -1,537 +0,0 @@
-/**
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * <p>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
- *
- * <p>http://www.apache.org/licenses/LICENSE-2.0
- *
- * <p>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.android.vts.util;
-
-import com.android.vts.entity.DeviceInfoEntity;
-import com.android.vts.entity.ProfilingPointRunEntity;
-import com.android.vts.entity.TestRunEntity;
-import com.google.appengine.api.datastore.DatastoreService;
-import com.google.appengine.api.datastore.DatastoreServiceFactory;
-import com.google.appengine.api.datastore.Entity;
-import com.google.appengine.api.datastore.FetchOptions;
-import com.google.appengine.api.datastore.Key;
-import com.google.appengine.api.datastore.KeyFactory;
-import com.google.appengine.api.datastore.Query;
-import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
-import com.google.appengine.api.datastore.Query.Filter;
-import com.google.appengine.api.datastore.Query.FilterOperator;
-import com.google.appengine.api.datastore.Query.FilterPredicate;
-import com.google.common.collect.Sets;
-import com.google.gson.Gson;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.servlet.http.HttpServletRequest;
-
-/** FilterUtil, a helper class for parsing and matching search queries to data. */
-public class FilterUtil {
- protected static final Logger logger = Logger.getLogger(FilterUtil.class.getName());
- private static final String INEQUALITY_REGEX = "(<=|>=|<|>|=)";
-
- /** Key class to represent a filter token. */
- public enum FilterKey {
- DEVICE_BUILD_ID("deviceBuildId", DeviceInfoEntity.BUILD_ID, true),
- BRANCH("branch", DeviceInfoEntity.BRANCH, true),
- TARGET("device", DeviceInfoEntity.BUILD_FLAVOR, true),
- VTS_BUILD_ID("testBuildId", TestRunEntity.TEST_BUILD_ID, false),
- HOSTNAME("hostname", TestRunEntity.HOST_NAME, false),
- PASSING("passing", TestRunEntity.PASS_COUNT, false),
- NONPASSING("nonpassing", TestRunEntity.FAIL_COUNT, false);
-
- private static final Map<String, FilterKey> keyMap;
-
- static {
- keyMap = new HashMap<>();
- for (FilterKey k : EnumSet.allOf(FilterKey.class)) {
- keyMap.put(k.keyString, k);
- }
- }
-
- /**
- * Test if a string is a valid device key.
- *
- * @param keyString The key string.
- * @return True if they key string matches a key and the key is a device filter.
- */
- public static boolean isDeviceKey(String keyString) {
- return keyMap.containsKey(keyString) && keyMap.get(keyString).isDevice;
- }
-
- /**
- * Test if a string is a valid test key.
- *
- * @param keyString The key string.
- * @return True if they key string matches a key and the key is a test filter.
- */
- public static boolean isTestKey(String keyString) {
- return keyMap.containsKey(keyString) && !keyMap.get(keyString).isDevice;
- }
-
- /**
- * Parses a key string into a key.
- *
- * @param keyString The key string.
- * @return The key matching the key string.
- */
- public static FilterKey parse(String keyString) {
- return keyMap.get(keyString);
- }
-
- private final String keyString;
- private final String property;
- private final boolean isDevice;
-
- /**
- * Constructs a key with the specified key string.
- *
- * @param keyString The identifying key string.
- * @param propertyName The name of the property to match.
- */
- private FilterKey(String keyString, String propertyName, boolean isDevice) {
- this.keyString = keyString;
- this.property = propertyName;
- this.isDevice = isDevice;
- }
-
- /**
- * Return a filter predicate for string equality.
- *
- * @param matchString The string to match.
- * @return A filter predicate enforcing equality on the property.
- */
- public FilterPredicate getFilterForString(String matchString) {
- return new FilterPredicate(this.property, FilterOperator.EQUAL, matchString);
- }
-
- /**
- * Return a filter predicate for number inequality or equality.
- *
- * @param matchNumber A string, either a number or an inequality symbol followed by a
- * number.
- * @return A filter predicate enforcing equality on the property, or null if invalid.
- */
- public FilterPredicate getFilterForNumber(String matchNumber) {
- String numberString = matchNumber.trim();
- Pattern p = Pattern.compile(INEQUALITY_REGEX);
- Matcher m = p.matcher(numberString);
-
- // Default operator is equality.
- FilterOperator op = FilterOperator.EQUAL;
-
- // Determine if there is an inequality operator.
- if (m.find() && m.start() == 0 && m.end() != numberString.length()) {
- String opString = m.group();
-
- // Inequality operator can be <=, <, >, >=, or =.
- if (opString.equals("<=")) {
- op = FilterOperator.LESS_THAN_OR_EQUAL;
- } else if (opString.equals("<")) {
- op = FilterOperator.LESS_THAN;
- } else if (opString.equals(">")) {
- op = FilterOperator.GREATER_THAN;
- } else if (opString.equals(">=")) {
- op = FilterOperator.GREATER_THAN_OR_EQUAL;
- } else if (!opString.equals("=")) { // unrecognized inequality.
- return null;
- }
- numberString = matchNumber.substring(m.end()).trim();
- }
- try {
- long number = Long.parseLong(numberString);
- return new FilterPredicate(this.property, op, number);
- } catch (NumberFormatException e) {
- // invalid number
- return null;
- }
- }
-
- /**
- * Get the enum value
- *
- * @return The string value associated with the key.
- */
- public String getValue() {
- return this.keyString;
- }
- }
-
- /**
- * Get the common elements among multiple collections.
- *
- * @param collections The collections containing all sub collections to find common element.
- * @return The common elements set found from the collections param.
- */
- public static <T> Set<T> getCommonElements(Collection<? extends Collection<T>> collections) {
-
- Set<T> common = new LinkedHashSet<T>();
- if (!collections.isEmpty()) {
- Iterator<? extends Collection<T>> iterator = collections.iterator();
- common.addAll(iterator.next());
- while (iterator.hasNext()) {
- common.retainAll(iterator.next());
- }
- }
- return common;
- }
-
- /**
- * Get the first value associated with the key in the parameter map.
- *
- * @param parameterMap The parameter map with string keys and (Object) String[] values.
- * @param key The key whose value to get.
- * @return The first value associated with the provided key.
- */
- public static String getFirstParameter(Map<String, String[]> parameterMap, String key) {
- String[] values = (String[]) parameterMap.get(key);
- if (values.length == 0) return null;
- return values[0];
- }
-
- /**
- * Get a filter on devices from a user search query.
- *
- * @param parameterMap The key-value map of url parameters.
- * @return A filter with the values from the user search parameters.
- */
- public static Filter getUserDeviceFilter(Map<String, String[]> parameterMap) {
- Filter deviceFilter = null;
- for (String key : parameterMap.keySet()) {
- if (!FilterKey.isDeviceKey(key)) continue;
- String value = getFirstParameter(parameterMap, key);
- if (value == null) continue;
- FilterKey filterKey = FilterKey.parse(key);
- Filter f = filterKey.getFilterForString(value);
- if (deviceFilter == null) {
- deviceFilter = f;
- } else {
- deviceFilter = CompositeFilterOperator.and(deviceFilter, f);
- }
- }
- return deviceFilter;
- }
-
- /**
- * Get a list of test filters given the user parameters.
- *
- * @param parameterMap The key-value map of url parameters.
- * @return A list of filters, each having at most one inequality filter.
- */
- public static List<Filter> getUserTestFilters(Map<String, String[]> parameterMap) {
- List<Filter> userFilters = new ArrayList<>();
- for (String key : parameterMap.keySet()) {
- if (!FilterKey.isTestKey(key)) continue;
- String stringValue = getFirstParameter(parameterMap, key);
- if (stringValue == null) continue;
- FilterKey filterKey = FilterKey.parse(key);
- switch (filterKey) {
- case NONPASSING:
- case PASSING:
- userFilters.add(filterKey.getFilterForNumber(stringValue));
- break;
- case HOSTNAME:
- case VTS_BUILD_ID:
- userFilters.add(filterKey.getFilterForString(stringValue.toLowerCase()));
- break;
- default:
- continue;
- }
- }
- return userFilters;
- }
-
- /**
- * Get a filter on the test run type.
- *
- * @param showPresubmit True to display presubmit tests.
- * @param showPostsubmit True to display postsubmit tests.
- * @param unfiltered True if no filtering should be applied.
- * @return A filter on the test type.
- */
- public static Filter getTestTypeFilter(
- boolean showPresubmit, boolean showPostsubmit, boolean unfiltered) {
- if (unfiltered) {
- return null;
- } else if (showPresubmit && !showPostsubmit) {
- return new FilterPredicate(
- TestRunEntity.TYPE,
- FilterOperator.EQUAL,
- TestRunEntity.TestRunType.PRESUBMIT.getNumber());
- } else if (showPostsubmit && !showPresubmit) {
- return new FilterPredicate(
- TestRunEntity.TYPE,
- FilterOperator.EQUAL,
- TestRunEntity.TestRunType.POSTSUBMIT.getNumber());
- } else {
- List<Integer> types = new ArrayList<>();
- types.add(TestRunEntity.TestRunType.PRESUBMIT.getNumber());
- types.add(TestRunEntity.TestRunType.POSTSUBMIT.getNumber());
- return new FilterPredicate(TestRunEntity.TYPE, FilterOperator.IN, types);
- }
- }
-
- /**
- * Get a filter for profiling points between a specified time window.
- *
- * @param grandparentKey The key of the profiling point grandparent entity.
- * @param parentKind The kind of the profiling point parent.
- * @param startTime The start time of the window, or null if unbounded.
- * @param endTime The end time of the window, or null if unbounded.
- * @return A filter to query for profiling points in the time window.
- */
- public static Filter getProfilingTimeFilter(
- Key grandparentKey, String parentKind, Long startTime, Long endTime) {
- if (startTime == null && endTime == null) {
- endTime = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
- }
- Filter startFilter = null;
- Filter endFilter = null;
- Filter filter = null;
- if (startTime != null) {
- Key minRunKey = KeyFactory.createKey(grandparentKey, parentKind, startTime);
- Key startKey =
- KeyFactory.createKey(
- minRunKey, ProfilingPointRunEntity.KIND, String.valueOf((char) 0x0));
- startFilter =
- new FilterPredicate(
- Entity.KEY_RESERVED_PROPERTY,
- FilterOperator.GREATER_THAN_OR_EQUAL,
- startKey);
- filter = startFilter;
- }
- if (endTime != null) {
- Key maxRunKey = KeyFactory.createKey(grandparentKey, parentKind, endTime);
- Key endKey =
- KeyFactory.createKey(
- maxRunKey, ProfilingPointRunEntity.KIND, String.valueOf((char) 0xff));
- endFilter =
- new FilterPredicate(
- Entity.KEY_RESERVED_PROPERTY,
- FilterOperator.LESS_THAN_OR_EQUAL,
- endKey);
- filter = endFilter;
- }
- if (startFilter != null && endFilter != null) {
- filter = CompositeFilterOperator.and(startFilter, endFilter);
- }
- return filter;
- }
-
- /**
- * Get a filter for device information between a specified time window.
- *
- * @param grandparentKey The key of the device's grandparent entity.
- * @param parentKind The kind of the device's parent.
- * @param startTime The start time of the window, or null if unbounded.
- * @param endTime The end time of the window, or null if unbounded.
- * @return A filter to query for devices in the time window.
- */
- public static Filter getDeviceTimeFilter(
- Key grandparentKey, String parentKind, Long startTime, Long endTime) {
- if (startTime == null && endTime == null) {
- endTime = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
- }
- Filter startFilter = null;
- Filter endFilter = null;
- Filter filter = null;
- if (startTime != null) {
- Key minRunKey = KeyFactory.createKey(grandparentKey, parentKind, startTime);
- Key startKey = KeyFactory.createKey(minRunKey, DeviceInfoEntity.KIND, 1);
- startFilter =
- new FilterPredicate(
- Entity.KEY_RESERVED_PROPERTY,
- FilterOperator.GREATER_THAN_OR_EQUAL,
- startKey);
- filter = startFilter;
- }
- if (endTime != null) {
- Key maxRunKey = KeyFactory.createKey(grandparentKey, parentKind, endTime);
- Key endKey = KeyFactory.createKey(maxRunKey, DeviceInfoEntity.KIND, Long.MAX_VALUE);
- endFilter =
- new FilterPredicate(
- Entity.KEY_RESERVED_PROPERTY,
- FilterOperator.LESS_THAN_OR_EQUAL,
- endKey);
- filter = endFilter;
- }
- if (startFilter != null && endFilter != null) {
- filter = CompositeFilterOperator.and(startFilter, endFilter);
- }
- return filter;
- }
-
- /**
- * Get the time range filter to apply to a query.
- *
- * @param testKey The key of the parent TestEntity object.
- * @param kind The kind to use for the filters.
- * @param startTime The start time in microseconds, or null if unbounded.
- * @param endTime The end time in microseconds, or null if unbounded.
- * @param testRunFilter The existing filter on test runs to apply, or null.
- * @return A filter to apply on test runs.
- */
- public static Filter getTimeFilter(
- Key testKey, String kind, Long startTime, Long endTime, Filter testRunFilter) {
- if (startTime == null && endTime == null) {
- endTime = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());
- }
-
- Filter startFilter = null;
- Filter endFilter = null;
- Filter filter = null;
- if (startTime != null) {
- Key startKey = KeyFactory.createKey(testKey, kind, startTime);
- startFilter =
- new FilterPredicate(
- Entity.KEY_RESERVED_PROPERTY,
- FilterOperator.GREATER_THAN_OR_EQUAL,
- startKey);
- filter = startFilter;
- }
- if (endTime != null) {
- Key endKey = KeyFactory.createKey(testKey, kind, endTime);
- endFilter =
- new FilterPredicate(
- Entity.KEY_RESERVED_PROPERTY,
- FilterOperator.LESS_THAN_OR_EQUAL,
- endKey);
- filter = endFilter;
- }
- if (startFilter != null && endFilter != null) {
- filter = CompositeFilterOperator.and(startFilter, endFilter);
- }
- if (testRunFilter != null) {
- filter = CompositeFilterOperator.and(filter, testRunFilter);
- }
- return filter;
- }
-
- public static Filter getTimeFilter(Key testKey, String kind, Long startTime, Long endTime) {
- return getTimeFilter(testKey, kind, startTime, endTime, null);
- }
-
- /**
- * Get the list of keys matching the provided test filter and device filter.
- *
- * @param ancestorKey The ancestor key to use in the query.
- * @param kind The entity kind to use in the test query.
- * @param testFilters The filter list to apply to test runs (each having <=1 inequality filter).
- * @param deviceFilter The filter to apply to associated devices.
- * @param dir The sort direction of the returned list.
- * @param maxSize The maximum number of entities to return.
- * @return a list of keys matching the provided test and device filters.
- */
- public static List<Key> getMatchingKeys(
- Key ancestorKey,
- String kind,
- List<Filter> testFilters,
- Filter deviceFilter,
- Query.SortDirection dir,
- int maxSize) {
- DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
- Set<Key> matchingTestKeys = null;
- Key minKey = null;
- Key maxKey = null;
- for (Filter testFilter : testFilters) {
- Query testQuery =
- new Query(kind).setAncestor(ancestorKey).setFilter(testFilter).setKeysOnly();
- Set<Key> filterMatches = new HashSet<>();
- FetchOptions ops = DatastoreHelper.getLargeBatchOptions();
- if (deviceFilter == null && testFilters.size() == 1) {
- ops.limit(maxSize);
- testQuery.addSort(Entity.KEY_RESERVED_PROPERTY, dir);
- }
- logger.log(Level.INFO, "testQuery => " + testQuery);
- for (Entity testRunKey : datastore.prepare(testQuery).asIterable(ops)) {
- filterMatches.add(testRunKey.getKey());
- if (maxKey == null || testRunKey.getKey().compareTo(maxKey) > 0)
- maxKey = testRunKey.getKey();
- if (minKey == null || testRunKey.getKey().compareTo(minKey) < 0)
- minKey = testRunKey.getKey();
- }
- if (matchingTestKeys == null) {
- matchingTestKeys = filterMatches;
- } else {
- matchingTestKeys = Sets.intersection(matchingTestKeys, filterMatches);
- }
- }
- logger.log(Level.INFO, "matchingTestKeys => " + matchingTestKeys);
-
- Set<Key> allMatchingKeys;
- if (deviceFilter == null || matchingTestKeys.size() == 0) {
- allMatchingKeys = matchingTestKeys;
- } else {
- deviceFilter =
- CompositeFilterOperator.and(
- deviceFilter,
- getDeviceTimeFilter(
- minKey.getParent(),
- minKey.getKind(),
- minKey.getId(),
- maxKey.getId()));
- allMatchingKeys = new HashSet<>();
- Query deviceQuery =
- new Query(DeviceInfoEntity.KIND)
- .setAncestor(ancestorKey)
- .setFilter(deviceFilter)
- .setKeysOnly();
- for (Entity device :
- datastore
- .prepare(deviceQuery)
- .asIterable(DatastoreHelper.getLargeBatchOptions())) {
- if (matchingTestKeys.contains(device.getKey().getParent())) {
- allMatchingKeys.add(device.getKey().getParent());
- }
- }
- }
- logger.log(Level.INFO, "allMatchingKeys => " + allMatchingKeys);
- List<Key> gets = new ArrayList<>(allMatchingKeys);
- if (dir == Query.SortDirection.DESCENDING) {
- gets.sort(Comparator.reverseOrder());
- } else {
- gets.sort(Comparator.naturalOrder());
- }
- gets = gets.subList(0, Math.min(gets.size(), maxSize));
- return gets;
- }
-
- /**
- * Set the request with the provided key/value attribute map.
- *
- * @param request The request whose attributes to set.
- * @param parameterMap The map from key to (Object) String[] value whose entries to parse.
- */
- public static void setAttributes(HttpServletRequest request, Map<String, String[]> parameterMap) {
- for (String key : parameterMap.keySet()) {
- if (!FilterKey.isDeviceKey(key) && !FilterKey.isTestKey(key)) continue;
- FilterKey filterKey = FilterKey.parse(key);
- String[] values = parameterMap.get(key);
- if (values.length == 0) continue;
- String stringValue = values[0];
- request.setAttribute(filterKey.keyString, new Gson().toJson(stringValue));
- }
- }
-}