/*******************************************************************************
* Copyright (c) 2017 École Polytechnique de Montréal
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
******************************************************************************/
package org.eclipse.tracecompass.internal.datastore.core.condition;
import java.util.Collection;
import java.util.NavigableSet;
import java.util.TreeSet;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.internal.provisional.datastore.core.condition.RangeCondition;
/**
* Generic Set Condition. This condition will verify that a value is one of a
* collection of values. It has a lower and upper bound, lower and upper bounds
* of the collection, to limit the space of research, but within those bounds,
* only the values in the collection are verified.
*
* @author Loïc Prieur-Drevon
* @param <E>
* Comparable type, for instance Long for timestamps
*/
public class DiscreteRangeCondition<E extends Comparable<E>> implements RangeCondition<E> {
/* the set will always have at least one element */
private final NavigableSet<@NonNull E> fSet;
/**
* Constructor for a NumCondition from a Collection of Integers
*
* @param c
* Integers to include in Set Condition.
*/
public DiscreteRangeCondition(Collection<E> c) {
if (c.isEmpty()) {
throw new IllegalArgumentException("DiscreteRangeCondition requires a non-empty collection"); //$NON-NLS-1$
}
fSet = new TreeSet<>(c);
}
@Override
public E min() {
return fSet.first();
}
@Override
public E max() {
return fSet.last();
}
@Override
public boolean test(E element) {
return fSet.contains(element);
}
/**
* Return true if the range [low, high] intersects at least one element from
* the Discrete Range.
*
* @param low
* lower bound of the timerange
* @param high
* upper bound of the timerange
*/
@Override
public boolean intersects(E low, E high) {
@Nullable E floor = fSet.floor(high);
if (floor == null) {
/* There is no element smaller than high */
return false;
}
@Nullable E ceil = fSet.ceiling(low);
if (ceil == null) {
/* There is no element larger than low */
return false;
}
/* At least one element is between low and high */
return ceil.compareTo(floor) <= 0;
}
@Override
public @Nullable DiscreteRangeCondition<E> subCondition(E from, E to) {
if (from.compareTo(to) > 0) {
throw new IllegalArgumentException(from.toString() + " is greater than " + to.toString()); //$NON-NLS-1$
}
NavigableSet<@NonNull E> subSet = fSet.subSet(from, true, to, true);
if (subSet.isEmpty()) {
return null;
}
return new DiscreteRangeCondition<>(subSet);
}
@Override
public String toString() {
return "Discrete condition: " + fSet.toString(); //$NON-NLS-1$
}
}