
com.day.cq.search.eval.DateRangePredicateEvaluator Maven / Gradle / Ivy
/*
* Copyright 1997-2008 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.Calendar;
import java.util.TimeZone;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.ValueFactory;
import com.day.cq.search.Predicate;
import com.day.cq.search.facets.FacetExtractor;
import com.day.cq.search.facets.buckets.ValueRangeBucket;
import com.day.cq.search.facets.extractors.PredefinedBucketsFacetExtractor;
import com.day.cq.search.impl.util.DateUtil;
import com.day.cq.search.impl.util.InvalidDateException;
import org.apache.felix.scr.annotations.Component;
/**
* DateRangePropertyPredicate
is a generic evaluator for
* checking a jcr DATE property against an interval. This uses the ISO8601
* format for dates (YYYY-MM-DDTHH:mm:ss.SSSZ
) and allows also partial
* representations (eg. YYYY-MM-DD
). You can also provide the
* dates (for the bounds) as number of milliseconds since 1970 (UTC timezone,
* basically the unix format).
*
*
* You can define a lower bound and an upper bound or only one of them. The
* operation (eg. "lesser than" or "lesser or equals") can also be specified for
* lower and upper bound individually.
*
*
* Note: Does not implement filtering, which means this predicate
* cannot be used together with filter-only predicates in an OR group.
*
*
Name:
* daterange
*
* Properties:
*
* - property
- relative path to a DATE property
* - lowerBound
- lower bound to check property for
* - lowerOperation
- ">" (default) or ">=", applies to the lowerBound
* - upperBound
- upper bound to check property for
* - upperOperation
- "<" (default) or "<=", applies to the upperBound
* - timeZone
- ID of timezone to use when it's not given in the ISO-8601 date string; default is the default timezone of the system
*
*
* @since 5.2
*/
@Component(metatype = false, factory="com.day.cq.search.eval.PredicateEvaluator/daterange")
public class DateRangePredicateEvaluator extends RangePropertyPredicateEvaluator {
public static final String TIME_ZONE = "timeZone";
@Override
public String getXPathExpression(Predicate p, EvaluationContext context) {
return super.getXPathExpression(p.get(PROPERTY),
parseDateString(p.get(LOWER_BOUND), p.get(TIME_ZONE), context.getSession()), p.get(LOWER_OPERATION),
parseDateString(p.get(UPPER_BOUND), p.get(TIME_ZONE), context.getSession()), p.get(UPPER_OPERATION));
}
@Override
public boolean canFilter(Predicate p, EvaluationContext context) {
return false;
}
@Override
public boolean canXpath(Predicate p, EvaluationContext context) {
return true;
}
public static String parseDateString(String dateString, String timeZoneID, Session session) {
if (dateString == null || dateString.length() == 0) {
return null;
}
TimeZone timeZone = null;
if (timeZoneID != null && timeZoneID.length() > 0) {
timeZone = TimeZone.getTimeZone(timeZoneID);
}
try {
// use ValueFactory for round-tripping as defined in JSR-170, section 6.2.6
ValueFactory vf = session.getValueFactory();
Calendar date;
try {
// a) check if the number is a plain long (msec since 1970, unix format)
long msec = Long.parseLong(dateString);
date = vf.createValue(msec).getDate();
} catch (NumberFormatException e) {
// b) else check for ISO 8601 format (eg. "2008-12-16")
try {
// DateUtil provides a relaxed ISO 8601 parser as opposed to the strict parser from JCR in ISO8601.java
date = DateUtil.parseISO8601(dateString, timeZone);
} catch (InvalidDateException e1) {
return "";
}
}
return "xs:dateTime('" + vf.createValue(date).getString() + "')";
} catch (RepositoryException e) {
return "";
}
}
public static final String TODAY = "Today";
public static final String THIS_WEEK = "This Week";
public static final String THIS_MONTH = "This Month";
public static final String LAST_THREE_MONTHS = "Last three months";
public static final String THIS_YEAR = "This Year";
public static final String LAST_YEAR = "Last Year";
public static final String EARLIER_THAN_LAST_YEAR = "Earlier than last year";
@Override
public FacetExtractor getFacetExtractor(Predicate p, EvaluationContext context) {
if (!p.hasNonEmptyValue(PROPERTY)) {
return null;
}
PredefinedBucketsFacetExtractor extractor = new PredefinedBucketsFacetExtractor(p.get(PROPERTY));
DateUtil dates = new DateUtil();
final Calendar endOfToday = dates.getToday();
endOfToday.add(Calendar.HOUR, 24);
// -> today
Predicate predicate = p.clone();
predicate.set(LOWER_BOUND, DateUtil.getISO8601DateNoTime(dates.getToday()));
predicate.set(LOWER_OPERATION, ">=");
predicate.set(UPPER_BOUND, DateUtil.getISO8601DateNoTime(endOfToday));
predicate.set(UPPER_OPERATION, "<=");
extractor.addPredefinedBucket(
new ValueRangeBucket(TODAY, dates.getToday().getTimeInMillis(), true, endOfToday.getTimeInMillis(), true, predicate));
// -> this week
predicate = p.clone();
predicate.set(LOWER_BOUND, DateUtil.getISO8601DateNoTime(dates.getWeekStart()));
predicate.set(LOWER_OPERATION, ">=");
predicate.set(UPPER_BOUND, DateUtil.getISO8601DateNoTime(endOfToday));
predicate.set(UPPER_OPERATION, "<=");
extractor.addPredefinedBucket(
new ValueRangeBucket(THIS_WEEK, dates.getWeekStart().getTimeInMillis(), true, endOfToday.getTimeInMillis(), true, predicate));
// -> this month
predicate = p.clone();
predicate.set(LOWER_BOUND, DateUtil.getISO8601DateNoTime(dates.getMonthStart()));
predicate.set(LOWER_OPERATION, ">=");
predicate.set(UPPER_BOUND, DateUtil.getISO8601DateNoTime(endOfToday));
predicate.set(UPPER_OPERATION, "<=");
extractor.addPredefinedBucket(
new ValueRangeBucket(THIS_MONTH, dates.getMonthStart().getTimeInMillis(), true, endOfToday.getTimeInMillis(), true, predicate));
// -> last three months
predicate = p.clone();
predicate.set(LOWER_BOUND, DateUtil.getISO8601DateNoTime(dates.getThreeMonthsAgo()));
predicate.set(LOWER_OPERATION, ">=");
predicate.set(UPPER_BOUND, DateUtil.getISO8601DateNoTime(endOfToday));
predicate.set(UPPER_OPERATION, "<=");
extractor.addPredefinedBucket(
new ValueRangeBucket(LAST_THREE_MONTHS, dates.getThreeMonthsAgo().getTimeInMillis(), true, endOfToday.getTimeInMillis(), true, predicate));
// -> this year
predicate = p.clone();
predicate.set(LOWER_BOUND, DateUtil.getISO8601DateNoTime(dates.getYearStart()));
predicate.set(LOWER_OPERATION, ">=");
predicate.set(UPPER_BOUND, DateUtil.getISO8601DateNoTime(endOfToday));
predicate.set(UPPER_OPERATION, "<=");
extractor.addPredefinedBucket(
new ValueRangeBucket(THIS_YEAR, dates.getYearStart().getTimeInMillis(), true, endOfToday.getTimeInMillis(), true, predicate));
// -> last year
predicate = p.clone();
predicate.set(LOWER_BOUND, DateUtil.getISO8601DateNoTime(dates.getLastYearStart()));
predicate.set(LOWER_OPERATION, ">=");
predicate.set(UPPER_BOUND, DateUtil.getISO8601DateNoTime(dates.getYearStart()));
predicate.set(UPPER_OPERATION, "<=");
extractor.addPredefinedBucket(
new ValueRangeBucket(LAST_YEAR, dates.getLastYearStart().getTimeInMillis(), true, dates.getYearStart().getTimeInMillis(), true, predicate));
// -> earlier than last year
predicate = p.clone();
predicate.set(LOWER_BOUND, null);
predicate.set(UPPER_BOUND, DateUtil.getISO8601DateNoTime(dates.getLastYearStart()));
predicate.set(UPPER_OPERATION, "<");
extractor.addPredefinedBucket(
new ValueRangeBucket(EARLIER_THAN_LAST_YEAR, // + new SimpleDateFormat("yyyy").format(dates.getLastYearStart().getTime()),
null, true, dates.getLastYearStart().getTimeInMillis(), false, predicate));
return extractor;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy