| /********************************************************************** |
| * Copyright (c) 2017 Ericsson |
| * |
| * All rights reserved. This program and the accompanying materials are |
| * made available under the terms of the Eclipse Public License 2.0 which |
| * accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| **********************************************************************/ |
| |
| package org.eclipse.tracecompass.tmf.core.model.filters; |
| |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Objects; |
| |
| import org.eclipse.jdt.annotation.Nullable; |
| |
| import com.google.common.collect.Ordering; |
| import com.google.common.primitives.Longs; |
| |
| /** |
| * This represents a time query filter used by data providers. It encapsulates |
| * an array of times used for requesting data. It's the responsibility of |
| * viewers using data provider to create a time query filter and pass it to data |
| * providers if needed. |
| * |
| * Elements of the array should be ORDERED ascendingly. |
| * |
| * @author Yonni Chen |
| * @since 4.0 |
| */ |
| public class TimeQueryFilter { |
| |
| private final long[] fTimesRequested; |
| |
| /** |
| * Constructor. Given a start value, end value and n entries, this constructor |
| * will set its property to an array of n entries uniformly distributed and |
| * ordered ascendingly. |
| * |
| * @param start |
| * The starting value |
| * @param end |
| * The ending value |
| * @param n |
| * The number of entries |
| **/ |
| public TimeQueryFilter(long start, long end, int n) { |
| fTimesRequested = splitRangeIntoEqualParts(start, end, n); |
| } |
| |
| /** |
| * Create a {@link TimeQueryFilter} from a sorted list of times. |
| * |
| * @param times |
| * sorted list of times to query. |
| */ |
| public TimeQueryFilter(List<Long> times) { |
| if (!Ordering.natural().isOrdered(times)) { |
| throw new IllegalArgumentException("List of times is not sorted"); //$NON-NLS-1$ |
| } |
| fTimesRequested = Longs.toArray(times); |
| } |
| |
| /** |
| * Gets the array of times requested |
| * |
| * @return The array of requested times |
| */ |
| public long[] getTimesRequested() { |
| return fTimesRequested; |
| } |
| |
| /** |
| * Gets the first time |
| * |
| * @return The first time |
| */ |
| public long getStart() { |
| return fTimesRequested[0]; |
| } |
| |
| /** |
| * Gets the last time |
| * |
| * @return The last time |
| */ |
| public long getEnd() { |
| return fTimesRequested[Integer.max(0, fTimesRequested.length - 1)]; |
| } |
| |
| /** |
| * Given a start and end value, this method will create an array of n entries |
| * uniformly distributed. First entry of resulting array is start and last entry |
| * is end. Example : start = 1, end = 15, n = 5, resulting array will be : [1, |
| * 5, 8, 12, 15]. <br/> |
| * If n is equal to 1, this method will return an array of size 1 ONLY if start |
| * and end are equal. Otherwise, an IllegalArgumentException will be thrown. |
| * |
| * @param start |
| * The starting value |
| * @param end |
| * The ending value. Must be greater or equal to start value |
| * @param n |
| * The number of entries. Must be greater than 0 |
| * @return An uniformly distributed array of n elements |
| */ |
| private static final long[] splitRangeIntoEqualParts(long start, long end, int n) { |
| if (n < 1) { |
| throw new IllegalArgumentException("Number of entries must be greater than 0"); //$NON-NLS-1$ |
| } |
| |
| if (n == 1) { |
| if (start == end) { |
| long[] result = new long[1]; |
| result[0] = start; |
| return result; |
| } |
| throw new IllegalArgumentException("Number of entries requested is 1, but start and end are different. Impossible to create array."); //$NON-NLS-1$ |
| } |
| |
| double stepSize = Math.abs(end - start) / ((double) n - 1); |
| long[] result = new long[n]; |
| |
| for (int i = 0; i < n; i++) { |
| result[i] = Math.min(start, end) + Math.round(i * stepSize); |
| } |
| |
| /* This is to make sure that last value will always be end */ |
| result[result.length - 1] = Math.max(start, end); |
| return result; |
| } |
| |
| @Override |
| public boolean equals(@Nullable Object obj) { |
| if (obj == null || getClass() != obj.getClass()) { |
| return false; |
| } |
| if (this == obj) { |
| return true; |
| } |
| TimeQueryFilter other = (TimeQueryFilter) obj; |
| return Arrays.equals(fTimesRequested, other.getTimesRequested()); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(fTimesRequested); |
| } |
| } |