/*******************************************************************************
* Copyright (c) 2006 IBM Corporation.
* 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
*
* Contributors:
* IBM Corporation - Jeff Briggs, Henry Hughes, Ryan Morse
*******************************************************************************/
package org.eclipse.linuxtools.systemtap.graphing.core.filters;
import java.text.MessageFormat;
import java.util.List;
import org.eclipse.linuxtools.internal.systemtap.graphing.core.Localization;
import org.eclipse.linuxtools.systemtap.graphing.core.structures.NumberType;
import org.eclipse.linuxtools.systemtap.structures.Copier;
public class RangeFilter implements IDataSetFilter {
/**
* Create a new Range Filter for a table of data.
* @param column The index of the table's column to apply the filter to.
* @param lowerBound The lower bound of the range to apply. Set to <code>null</code> to set a boundless lower limit.
* @param upperBound The upper bound of the range to apply. Set to <code>null</code> to set a boundless upper limit.
* @param style Extra properties of this filter, set by <i>bitwise-OR</i>'ing none or more of
* {@link #INSIDE_BOUNDS}, {@link #OUTSIDE_BOUNDS}, or {@link #INCLUSIVE}.
*/
public RangeFilter(int column, Number lowerBound, Number upperBound, int style) {
this.column = column;
this.lowerBound = lowerBound;
this.upperBound = upperBound;
if (lowerBound == null || upperBound == null) {
this.style = style & INCLUSIVE;
} else {
this.style = style;
}
}
/**
* Apply the RangeFilter to the passed dataset.
*
* @param data The dataset to filter.
*
* @return The filtered dataset.
*/
@Override
public List<Object>[] filter(List<Object>[] data) {
if(column < 0 || column >= data.length) {
return null;
}
List<Object>[] newData = Copier.copy(data);
for(int j,i=newData[column].size()-1; i>=0; i--) {
if(!inBounds(NumberType.obj2num(newData[column].get(i)))) {
for(j=0; j<newData.length; j++) {
newData[j].remove(i);
}
}
}
return newData;
}
@Override
public String getID() {
return ID;
}
/**
* Verify that the number passed is in the bounds of the created filter.
*
* @param num The number to verify.
*
* @return True if the number is within bounds.
*/
private boolean inBounds(Number num) {
if (INSIDE_BOUNDS == (style & 1)) {
if(INCLUSIVE == (style & 2)) {
if((upperBound != null && num.doubleValue() > upperBound.doubleValue())
|| (lowerBound != null && num.doubleValue() < lowerBound.doubleValue())) {
return false;
}
} else {
if((upperBound != null && num.doubleValue() >= upperBound.doubleValue())
|| (lowerBound != null && num.doubleValue() <= lowerBound.doubleValue())) {
return false;
}
}
} else {
if(INCLUSIVE == (style & 2)) {
if((upperBound != null && num.doubleValue() < upperBound.doubleValue())
&& (lowerBound != null && num.doubleValue() > lowerBound.doubleValue())) {
return false;
}
} else {
if((upperBound != null && num.doubleValue() <= upperBound.doubleValue())
&& (lowerBound != null && num.doubleValue() >= lowerBound.doubleValue())) {
return false;
}
}
}
return true;
}
/**
* @since 2.0
*/
@Override
public String getInfo() {
boolean insideBounds = INSIDE_BOUNDS == (style & 1);
boolean inclusive = INCLUSIVE == (style & 2);
String info;
if (lowerBound != null && upperBound != null) {
info = MessageFormat.format(Localization.getString(insideBounds ?
"RangeFilter.Inside" : "RangeFilter.Outside"), lowerBound.toString(), upperBound.toString()); //$NON-NLS-1$ //$NON-NLS-2$
return inclusive ? MessageFormat.format(Localization.getString("RangeFilter.Inclusive"), info) : info; //$NON-NLS-1$
} else {
boolean lower = lowerBound != null;
info = (lower ? lowerBound : upperBound).toString();
return MessageFormat.format(Localization.getString(lower ?
"RangeFilter.GreaterThan" : "RangeFilter.LessThan"), !inclusive ? //$NON-NLS-1$ //$NON-NLS-2$
info : MessageFormat.format(Localization.getString("RangeFilter.EqualTo"), info)); //$NON-NLS-1$
}
}
/**
* @since 2.0
*/
@Override
public int getColumn() {
return column;
}
private int column;
private Number upperBound;
private Number lowerBound;
private int style;
/**
* Style constant indicating that the filter will only keep values inside the provided bounds.
* (Not applicable for unbounded ranges.)
*/
public static final int INSIDE_BOUNDS = 0;
/**
* Style constant indicating that the filter will only keep values outside the provided bounds.
* (Not applicable for unbounded ranges.)
*/
public static final int OUTSIDE_BOUNDS = 1;
/**
* Style constant indicating that the filter will not exclude values that equal either the upper or lower bound.
*/
public static final int INCLUSIVE = 2;
public static final String ID = "org.eclipse.linuxtools.systemtap.graphing.core.filters.RangeFilter"; //$NON-NLS-1$
}