/* * Copyright 2013 Gordon Burgett and individual contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.xflatdb.xflat.query; import java.util.Comparator; import org.xflatdb.xflat.util.ComparableComparator; /** * A class containing a number of factory methods for getting {@link IntervalProvider} * objects for numbers. * * Each IntervalProvider provides fixed-width intervals calculated based on the * width and base parameters to each function. The base is the offset on the number line * from which to start, and the width is the size of each interval on the number line. * <p/> * Example: <br/> * for base = 25 and width = 100, intervals would be the following: <br/> * ... [-175, -75) [-75, 25) [25, 125) [125, 225) ... * @author Gordon */ public class NumericIntervalProvider { private NumericIntervalProvider(){ } /** * Creates a IntervalProvider for {@link Integer} based intervals. * @param base The base from which intervals should be calculated. Usually 0. * @param width The width of one interval. * @return A IntervalProvider providing intervals based on these settings. */ public static IntervalProvider<Integer> forInteger(final int base, final int width){ return new IntervalProvider<Integer>(){ @Override public Interval<Integer> getInterval(Integer value) { int diff = Math.abs(value - base) % width; int lower, upper; if(value < base){ //if the diff was zero, it was an exact mod, then we need to add the width instead of zero. upper = value + (diff == 0 ? width : diff); lower = upper - width; } else{ lower = value - diff; upper = lower + width; } return new Interval<>(lower, true, upper, false); } @Override public Interval<Integer> nextInterval(Interval<Integer> current, long factor) { int lower = (int) (current.getBegin() + (width * factor)); int upper = lower + width; return new Interval<>(lower, true, upper, false); } @Override public Comparator<Integer> getComparator() { return ComparableComparator.getComparator(Integer.class); } @Override public String getName(Interval<Integer> interval){ return interval.getBegin().toString(); } @Override public Interval<Integer> getInterval(String name) { try{ int i = Integer.parseInt(name); return getInterval(i); }catch(Exception ex){ return null; } } }; } /** * Creates a IntervalProvider for {@link Long} based intervals. * @param base The base from which intervals should be calculated. Usually 0. * @param width The width of one interval. * @return A IntervalProvider providing intervals based on these settings. */ public static IntervalProvider<Long> forLong(final long base, final long width){ return new IntervalProvider<Long>(){ @Override public Interval<Long> getInterval(Long value) { long diff = Math.abs(value - base) % width; long lower, upper; if(value < base){ //if the diff was zero, it was an exact mod, then we need to add the width instead of zero. upper = value + (diff == 0 ? width : diff); lower = upper - width; } else{ lower = value - diff; upper = lower + width; } return new Interval<>(lower, true, upper, false); } @Override public Interval<Long> nextInterval(Interval<Long> current, long factor) { long lower = (current.getBegin() + (width * factor)); long upper = lower + width; return new Interval<>(lower, true, upper, false); } @Override public Comparator<Long> getComparator() { return ComparableComparator.getComparator(Long.class); } @Override public String getName(Interval<Long> interval){ return interval.getBegin().toString(); } @Override public Interval<Long> getInterval(String name) { try{ long i = Long.parseLong(name); return getInterval(i); }catch(Exception ex){ return null; } } }; } /** * Creates a IntervalProvider for {@link Double} based intervals. * @param base The base from which intervals should be calculated. Usually 0. * @param width The width of one interval. * @return A IntervalProvider providing intervals based on these settings. */ public static IntervalProvider<Double> forDouble(final double base, final double width){ return new IntervalProvider<Double>(){ @Override public Interval<Double> getInterval(Double value) { double diff = Math.abs(value - base) % width; double lower, upper; if(value < base){ //if the diff was zero, it was an exact mod, then we need to add the width instead of zero. upper = value + (diff == 0 ? width : diff); lower = upper - width; } else{ lower = value - diff; upper = lower + width; } return new Interval<>(lower, true, upper, false); } @Override public Interval<Double> nextInterval(Interval<Double> current, long factor) { double lower = (current.getBegin() + (width * factor)); double upper = lower + width; return new Interval<>(lower, true, upper, false); } @Override public Comparator<Double> getComparator() { return ComparableComparator.getComparator(Double.class); } @Override public String getName(Interval<Double> interval){ return interval.getBegin().toString(); } @Override public Interval<Double> getInterval(String name) { try{ double i = Double.parseDouble(name); return getInterval(i); }catch(Exception ex){ return null; } } }; } }