blob: 4fc99fcce693823747f945da7c91b3f66c23b26e [file] [log] [blame]
/**********************************************************************
* 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);
}
}