/*
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved.
Contact:
SYSTAP, LLC DBA Blazegraph
2501 Calvert ST NW #106
Washington, DC 20008
licenses@blazegraph.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Created on Apr 6, 2009
*/
package com.bigdata.counters.query;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import cern.clhep.Units;
import com.bigdata.counters.render.XHTMLRenderer;
/**
* Utility class to interpret URL query parameters as a time range. Some
* examples of supported expressions include:
*
* <dl>
* <dt>12m</dt>
* <dd>12 minutes into the available history.</dd>
* <dt>-4h</dt>
* <dd>4 hours before the end of the available history.</dd>
* </dl>
*
* The general form is either <code>([+-]?)([0-9]+)([mhd])</code>.
* <p>
* The implied fromTime is the start of the available history. The implied
* toTime is the end of the available history. The implied units are
* {@link TimeUnit#MINUTES}.
* <p>
* Some query examples are:
*
* <dl>
*
* <dt>fromTime=-10m&period=Minutes</dt>
* <dd>The last 10 minutes of the available history.</dd>
*
* <dt>toTime=+4h</dt>
* <dd>The first 4 hours of the available history, with one sample every
* minute.</dd>
*
* <dt>toTime=+4h&period=Hours</dt>
* <dd>The first 4 hours of the available history, with one sample every hour.</dd>
*
* <dt>fromTime=+2h&toTime=+4h</dt>
* <dd>The data from the 2nd hour up to (but not including) the 4th hour of the
* available history, with one sample every minute.</dd>
*
* </dl>
*
* @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a>
* @version $Id$
*
* @todo fence posts all over for toTime, which needs to be correctly adjusted
* to reveal the end of the last minute of interest by placing the toTime
* to the first millisecond beyond the end of that minute.
*
* @todo if no suffix then directly gives the milliseconds since the epoch?
*
* @todo the {@link XHTMLRenderer.URLQueryModel} should also support fromDate and
* toDate, where the values are dates/date-times and where there is an
* optional URL query parameter to specify the format string used to
* interpret the data/time.
*/
public class TimeRange {
/**
* @todo <code>true</code> iff the adjusted time is {@link #dur} {@link #unit}s
* after some (unspecified) reference time; <code>false</code> iff the
* adjusted time is {@link #dur} {@link #unit}s before some (unspecified)
* reference time; and <code>null</code> if {@link #dur} should be
* directly interpreted as a time in the specified {@link #unit}s.
*/
public final Boolean relative;
/**
* The units in which the duration was specified.
*/
public final TimeUnit unit;
/**
* The duration in the specified units.
*/
public final long dur;
/**
* @todo Return the adjusted timestamp. This is {@link #dur} unless
* {@link #relative} is <code>true</code> in which case it is the given
* timestamp <i>minus</i> {@link #dur}.
*
* @param ts
* A reference timestamp from within the available history.
*
* @return The exclusive upper bound.
*/
public long getAdjustedTimestamp(final long ts) {
final long ms = unit.toMillis(dur);
if(relative) {
return ms;
}
return ts - ms;
}
public TimeRange(final String s) {
if (s == null)
throw new IllegalArgumentException();
final Matcher m = pattern.matcher(s);
if (!m.matches())
throw new IllegalArgumentException(s);
// anchored from the start unless prefixed with '-'.
relative = !("-".equals(m.group(1)));
final char ch = m.group(2).charAt(0);
switch (ch) {
case 'm':
unit = TimeUnit.MINUTES;
break;
case 'h':
unit = TimeUnit.HOURS;
break;
case 'd':
unit = TimeUnit.DAYS;
break;
default:
throw new AssertionError();
}
// duration.
dur = Long.valueOf(m.group(1));
}
/**
*
*/
static protected final Pattern pattern = Pattern
.compile("([+-]?)([0-9]+)([mhd])");
}