package mil.nga.giat.geowave.core.store.index.numeric; import java.util.Collections; import java.util.List; import mil.nga.giat.geowave.core.index.ByteArrayId; import mil.nga.giat.geowave.core.index.ByteArrayRange; import mil.nga.giat.geowave.core.store.filter.DistributableQueryFilter; import mil.nga.giat.geowave.core.store.index.FilterableConstraints; /** * A class based on FilterableConstraints that uses numeric values and includes * a lower and upper range * * @author geowave * */ public class NumericQueryConstraint implements FilterableConstraints { protected final ByteArrayId fieldId; protected Number lowerValue; protected Number upperValue; protected boolean inclusiveLow; protected boolean inclusiveHigh; public NumericQueryConstraint( final ByteArrayId fieldId, final Number lowerValue, final Number upperValue, boolean inclusiveLow, boolean inclusiveHigh ) { super(); this.fieldId = fieldId; this.lowerValue = lowerValue; this.upperValue = upperValue; this.inclusiveHigh = inclusiveHigh; this.inclusiveLow = inclusiveLow; } @Override public ByteArrayId getFieldId() { return fieldId; } @Override public int getDimensionCount() { return 1; } @Override public boolean isEmpty() { return false; } public double getMinValue() { return lowerValue.doubleValue(); } public double getMaxValue() { return upperValue.doubleValue(); } @Override public DistributableQueryFilter getFilter() { return new NumberRangeFilter( fieldId, lowerValue, upperValue, inclusiveLow, inclusiveHigh); } /** * Creates a collection of range values based on lower and upper bounds for * this constraint * * @return */ public List<ByteArrayRange> getRange() { return Collections.singletonList(new ByteArrayRange( new ByteArrayId( NumericIndexStrategy.toIndexByte(lowerValue.doubleValue())), new ByteArrayId( NumericIndexStrategy.toIndexByte(upperValue.doubleValue())))); } /** * * Returns an FilterableConstraints object that is the intersection of the * numeric bounds of this object and object passed in. * <p> * This method returns an object with the highest min and lowest max of the * two objects * * @param otherConstraint * object whose constraints are 'intersected' with existing * constraints * @return new {@link FilterableConstraints} */ public FilterableConstraints intersect( FilterableConstraints otherConstraint ) { if (otherConstraint instanceof NumericQueryConstraint && ((NumericQueryConstraint) otherConstraint).fieldId.equals(this.fieldId)) { final NumericQueryConstraint otherNumeric = ((NumericQueryConstraint) otherConstraint); final boolean lowEquals = lowerValue.equals(otherNumeric.lowerValue); final boolean upperEquals = upperValue.equals(otherNumeric.upperValue); final boolean replaceMin = (lowerValue.doubleValue() < otherNumeric.lowerValue.doubleValue()); final boolean replaceMax = (upperValue.doubleValue() > otherNumeric.upperValue.doubleValue()); double newMin = Math.max( this.lowerValue.doubleValue(), otherNumeric.lowerValue.doubleValue()); double newMax = Math.min( this.upperValue.doubleValue(), otherNumeric.upperValue.doubleValue()); boolean newIncLow = lowEquals ? (otherNumeric.inclusiveLow & inclusiveLow) : (replaceMin ? otherNumeric.inclusiveLow : inclusiveLow); boolean newIncHigh = upperEquals ? (otherNumeric.inclusiveHigh & inclusiveHigh) : (replaceMax ? otherNumeric.inclusiveHigh : inclusiveHigh); return new NumericQueryConstraint( fieldId, newMin, newMax, newIncLow, newIncHigh); } return this; } /** * * Returns an FilterableConstraints object that is the union of the numeric * bounds of this object and object passed in. * <p> * This method returns an object with the lowest min and highest max of the * two objects * * @param otherConstraint * object whose constraints are 'unioned' with existing * constraints * @return new {@link FilterableConstraints} */ public FilterableConstraints union( FilterableConstraints otherConstraint ) { if (otherConstraint instanceof NumericQueryConstraint && ((NumericQueryConstraint) otherConstraint).fieldId.equals(this.fieldId)) { final NumericQueryConstraint otherNumeric = ((NumericQueryConstraint) otherConstraint); final boolean lowEquals = lowerValue.equals(otherNumeric.lowerValue); final boolean upperEquals = upperValue.equals(otherNumeric.upperValue); final boolean replaceMin = (lowerValue.doubleValue() > otherNumeric.lowerValue.doubleValue()); final boolean replaceMax = (upperValue.doubleValue() < otherNumeric.upperValue.doubleValue()); double newMin = Math.min( this.lowerValue.doubleValue(), otherNumeric.lowerValue.doubleValue()); double newMax = Math.max( this.upperValue.doubleValue(), otherNumeric.upperValue.doubleValue()); boolean newIncLow = lowEquals ? (otherNumeric.inclusiveLow | inclusiveLow) : (replaceMin ? otherNumeric.inclusiveLow : inclusiveLow); boolean newIncHigh = upperEquals ? (otherNumeric.inclusiveHigh | inclusiveHigh) : (replaceMax ? otherNumeric.inclusiveHigh : inclusiveHigh); return new NumericQueryConstraint( fieldId, newMin, newMax, newIncLow, newIncHigh); } return this; } }