com.day.cq.search.eval.RelativeDateRangePredicateEvaluator Maven / Gradle / Ivy
/*
* Copyright 1997-2009 Day Management AG
* Barfuesserplatz 6, 4001 Basel, Switzerland
* All Rights Reserved.
*
* This software is the confidential and proprietary information of
* Day Management AG, ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Day.
*/
package com.day.cq.search.eval;
import java.util.GregorianCalendar;
import java.util.Scanner;
import com.day.cq.search.Predicate;
import org.apache.felix.scr.annotations.Component;
/**
* Matches JCR DATE properties against a date/time interval using time offsets
* relative to the current server time. You can specify lowerBound and upperBound
* using either a millisecond value or the bugzilla syntax 1s 2m 3h 4d 5w 6M 7y
* (one second, two minutes, three hours, four days, five weeks, six months, seven years).
* Prefix with "-" to indicate a negative offset before the current time.
* If you only specify lowerBound or upperBound, the other one will default to 0,
* meaning the current time.
*
*
* For example:
*
* -
*
upperBound=1h
(and no lowerBound) would select anything in the next hour
*
* -
*
lowerBound=-1d
(and no upperBound) would select anything in the last 24 hours
*
* -
*
lowerBound=-6M
and upperBound=-3M
* would select anything 6 months to 3 months old
*
* -
*
lowerBound=-1500
and upperBound=5500
* would select anything between 1500 milliseconds in the past and
* 5500 milliseconds in the future
*
* -
*
lowerBound=1d
and upperBound=2d
would select anything
* in the day after tomorrow
*
*
*
*
* Note it does not take leap years into consideration and all months are 30 days.
*
*
* Does not support filtering.
*
*
* Supports facet extraction in the same way as the {@link DateRangePredicateEvaluator}.
*
*
Name:
* relativedaterange
*
* Properties:
*
* - upperBound
* - upper date bound in milliseconds or 1s 2m 3h 4d 5w 6M 7y
* (one second, two minutes, three hours, four days, five weeks, six months, seven years)
* relative to current server time, use "-" for negative offset
* - lowerBound
* - lower date bound in milliseconds or 1s 2m 3h 4d 5w 6M 7y
* (one second, two minutes, three hours, four days, five weeks, six months, seven years)
* relative to current server time, use "-" for negative offset
*
*/
@Component(metatype = false, factory = "com.day.cq.search.eval.PredicateEvaluator/relativedaterange")
public class RelativeDateRangePredicateEvaluator extends
DateRangePredicateEvaluator {
@Override
public String getXPathExpression(final Predicate p, final EvaluationContext context) {
//get a new predicate that we can modify
Predicate modifiedPredicate = p.clone();
//what time is it now
long now = new GregorianCalendar().getTimeInMillis();
//default values for lower bound and upper bound offset
long upperBound = 0;
long lowerBound = 0;
//try to parse values, fallback to 0 if it fails
//calculate the offset
//modify the predicate
try {
upperBound = parseDateRange(p.get(UPPER_BOUND));
upperBound += now;
modifiedPredicate.set(UPPER_BOUND, "" + upperBound);
} catch (Exception nfe) {
modifiedPredicate.set(UPPER_BOUND, null);
}
try {
lowerBound = parseDateRange(p.get(LOWER_BOUND));
lowerBound += now;
modifiedPredicate.set(LOWER_BOUND, "" + lowerBound);
} catch (Exception nfe) {
modifiedPredicate.set(LOWER_BOUND, null);
}
//let the super class handle the complicated XPath stuff
return super.getXPathExpression(modifiedPredicate, context);
}
public long parseDateRange(String daterange) throws NumberFormatException {
if ((daterange==null)||(daterange.length()==0)) {
throw new NumberFormatException("cannot parse empty string");
} else if (daterange.matches("^(-)?\\d+$")) {
return Long.parseLong(daterange);
}
String cleandaterange = daterange.replaceAll("[^dsmhdwMy\\d-]", "");
boolean negative = cleandaterange.matches("^-.*");
cleandaterange = cleandaterange.replaceAll("-", "");
if (!cleandaterange.matches("^(\\d+\\w)+$")) {
throw new NumberFormatException("only s, m, h, d, w, M, y are allowed modifiers");
}
cleandaterange = cleandaterange.replaceAll("(\\d+)(\\w)", "$1 $2 ");
Scanner scanner = new Scanner(cleandaterange);
long value = 0;
while (scanner.hasNext()) {
long number = scanner.nextLong();
String unit = scanner.next();
if ("s".equals(unit)) {
value += number * 1000;
} else if ("m".equals(unit)) {
// minute
value += number * 60 * 1000;
} else if ("h".equals(unit)) {
value += number * 60 * 60 * 1000;
} else if ("d".equals(unit)) {
value += number * 24 * 60 * 60 * 1000;
} else if ("w".equals(unit)) {
value += number * 7 * 24 * 60 * 60 * 1000;
} else if ("M".equals(unit)) {
// month
value += number * 30 * 24 * 60 * 60 * 1000;
} else if ("y".equals(unit)) {
value += number * 365 * 24 * 60 * 60 * 1000;
}
}
if (negative) {
value *= -1;
}
return value;
}
}