com.stratio.cassandra.lucene.schema.mapping.DateRangeMapper Maven / Gradle / Ivy
The newest version!
/*
* Copyright (C) 2014 Stratio (http://stratio.com)
*
* 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 com.stratio.cassandra.lucene.schema.mapping;
import com.google.common.base.MoreObjects;
import com.stratio.cassandra.lucene.IndexException;
import com.stratio.cassandra.lucene.column.Columns;
import com.stratio.cassandra.lucene.common.DateParser;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.search.SortField;
import org.apache.lucene.spatial.prefix.NumberRangePrefixTreeStrategy;
import org.apache.lucene.spatial.prefix.tree.DateRangePrefixTree;
import org.apache.lucene.spatial.prefix.tree.NumberRangePrefixTree.NRShape;
import org.apache.lucene.spatial.prefix.tree.NumberRangePrefixTree.UnitNRShape;
import java.util.*;
/**
* A {@link Mapper} to map 1-dimensional date ranges.
*
* @author Andres de la Pena {@literal }
*/
public class DateRangeMapper extends MultipleColumnMapper {
/** The name of the column containing the from date. */
public final String from;
/** The name of the column containing the to date. */
public final String to;
/** The {@link DateParser}. */
public final DateParser parser;
private final DateRangePrefixTree tree;
/** The {@link NumberRangePrefixTreeStrategy}. */
public final NumberRangePrefixTreeStrategy strategy;
/**
* Builds a new {@link DateRangeMapper}.
*
* @param field the name of the field
* @param validated if the field must be validated
* @param from the name of the column containing the from date
* @param to the name of the column containing the to date
* @param pattern the date pattern
*/
public DateRangeMapper(String field, Boolean validated, String from, String to, String pattern) {
super(field, validated, Arrays.asList(from, to), DATE_TYPES);
if (StringUtils.isBlank(from)) {
throw new IndexException("from column name is required");
}
if (StringUtils.isBlank(to)) {
throw new IndexException("to column name is required");
}
this.from = from;
this.to = to;
this.parser = new DateParser(pattern);
tree = DateRangePrefixTree.INSTANCE;
strategy = new NumberRangePrefixTreeStrategy(tree, field);
}
/** {@inheritDoc} */
@Override
public List indexableFields(Columns columns) {
Date fromDate = readFrom(columns);
Date toDate = readTo(columns);
if (fromDate == null && toDate == null) {
return Collections.emptyList();
}
validate(fromDate, toDate);
NRShape shape = makeShape(fromDate, toDate);
return Arrays.asList(strategy.createIndexableFields(shape));
}
private void validate(Date from, Date to) {
if (from == null) {
throw new IndexException("From column required");
}
if (to == null) {
throw new IndexException("To column required");
}
if (from.after(to)) {
throw new IndexException("From:'{}' is after To:'{}'", parser.toString(to), parser.toString(from));
}
}
/** {@inheritDoc} */
@Override
public SortField sortField(String name, boolean reverse) {
throw new IndexException("Date range mapper '{}' does not support sorting", name);
}
/**
* Makes an spatial shape representing the time range defined by the two specified dates.
*
* @param from the start {@link Date}
* @param to the end {@link Date}
* @return a shape
*/
public NRShape makeShape(Date from, Date to) {
UnitNRShape fromShape = tree.toUnitShape(from);
UnitNRShape toShape = tree.toUnitShape(to);
return tree.toRangeShape(fromShape, toShape);
}
/**
* Returns the start {@link Date} contained in the specified {@link Columns}.
*
* @param columns the columns containing the start {@link Date}
* @return the start date
*/
Date readFrom(Columns columns) {
return parser.parse(columns.valueForField(from));
}
/**
* Returns the end {@link Date} contained in the specified {@link Columns}.
*
* @param columns the columns containing the end {@link Date}
* @return the end date
*/
Date readTo(Columns columns) {
return parser.parse(columns.valueForField(to));
}
/**
* Returns the {@link Date} represented by the specified object, or {@code null} if there is no one. A {@link
* IllegalArgumentException} if the date is not parseable.
*
* @param value a value which could represent a {@link Date}
* @return the date represented by the specified object, or {@code null} if there is no one
*/
public Date base(Object value) {
return parser.parse(value);
}
/** {@inheritDoc} */
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("field", field)
.add("validated", validated)
.add("from", from)
.add("to", to)
.add("pattern", parser)
.toString();
}
}