/* * Licensed to STRATIO (C) under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. The STRATIO (C) licenses this file * to you 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.search.condition; import com.stratio.cassandra.lucene.schema.mapping.BitemporalMapper; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Query; import static com.stratio.cassandra.lucene.schema.mapping.BitemporalMapper.BitemporalDateTime; import static org.apache.lucene.search.BooleanClause.Occur.MUST; import static org.apache.lucene.search.BooleanClause.Occur.SHOULD; import static org.apache.lucene.search.NumericRangeQuery.newLongRange; /** * A {@link Condition} implementation that matches bi-temporal (four) fields within two range of values. * * @author Eduardo Alonso {@literal <eduardoalonso@stratio.com>} */ public class BitemporalCondition extends SingleMapperCondition<BitemporalMapper> { /** The default from value for vtFrom and ttFrom. */ public static final Long DEFAULT_FROM = 0L; /** The default to value for vtTo and ttTo. */ public static final Long DEFAULT_TO = Long.MAX_VALUE; /** The Valid Time Start. */ public final Object vtFrom; /** The Valid Time End. */ public final Object vtTo; /** The Transaction Time Start. */ public final Object ttFrom; /** The Transaction Time End. */ public final Object ttTo; /** * Constructs a query selecting all fields that intersects with valid time and transaction time ranges including * limits. * * @param boost The boost for this query clause. Documents matching this clause will (in addition to the normal * weightings) have their score multiplied by {@code boost}. * @param field The name of the field to be matched * @param vtFrom the valid time start * @param vtTo the valid time end * @param ttFrom the transaction time start * @param ttTo the transaction time end */ public BitemporalCondition(Float boost, String field, Object vtFrom, Object vtTo, Object ttFrom, Object ttTo) { super(boost, field, BitemporalMapper.class); this.vtFrom = vtFrom; this.vtTo = vtTo; this.ttFrom = ttFrom; this.ttTo = ttTo; } /** {@inheritDoc} */ @Override public Query query(BitemporalMapper mapper, Analyzer analyzer) { Long vtFromTime = parseTime(mapper, DEFAULT_FROM, vtFrom); Long vtToTime = parseTime(mapper, DEFAULT_TO, vtTo); Long ttFromTime = parseTime(mapper, DEFAULT_FROM, ttFrom); Long ttToTime = parseTime(mapper, DEFAULT_TO, ttTo); Long minTime = BitemporalDateTime.MIN.toDate().getTime(); Long maxTime = BitemporalDateTime.MAX.toDate().getTime(); BooleanQuery.Builder builder = new BooleanQuery.Builder(); if (!((vtFromTime.equals(0L)) && (vtToTime.equals(Long.MAX_VALUE)))) { BooleanQuery.Builder validBuilder = new BooleanQuery.Builder(); validBuilder.add(newLongRange(field + BitemporalMapper.VT_FROM_FIELD_SUFFIX, vtFromTime, vtToTime, true, true), SHOULD); validBuilder.add(newLongRange(field + BitemporalMapper.VT_TO_FIELD_SUFFIX, vtFromTime, vtToTime, true, true), SHOULD); BooleanQuery.Builder containsValidBuilder = new BooleanQuery.Builder(); containsValidBuilder.add(newLongRange(field + BitemporalMapper.VT_FROM_FIELD_SUFFIX, minTime, vtFromTime, true, true), MUST); containsValidBuilder.add(newLongRange(field + BitemporalMapper.VT_TO_FIELD_SUFFIX, vtToTime, maxTime, true, true), MUST); validBuilder.add(containsValidBuilder.build(), SHOULD); builder.add(validBuilder.build(), MUST); } if (!((ttFromTime.equals(0L)) && (ttToTime.equals(Long.MAX_VALUE)))) { BooleanQuery.Builder transactionBuilder = new BooleanQuery.Builder(); transactionBuilder.add(newLongRange(field + BitemporalMapper.TT_FROM_FIELD_SUFFIX, ttFromTime, ttToTime, true, true), SHOULD); transactionBuilder.add(newLongRange(field + BitemporalMapper.TT_TO_FIELD_SUFFIX, ttFromTime, ttToTime, true, true), SHOULD); BooleanQuery.Builder containsTransactionBuilder = new BooleanQuery.Builder(); containsTransactionBuilder.add(newLongRange(field + BitemporalMapper.TT_FROM_FIELD_SUFFIX, minTime, ttFromTime, true, true), MUST); containsTransactionBuilder.add(newLongRange(field + BitemporalMapper.TT_TO_FIELD_SUFFIX, ttToTime, maxTime, true, true), MUST); transactionBuilder.add(containsTransactionBuilder.build(), SHOULD); builder.add(transactionBuilder.build(), MUST); } Query query = builder.build(); query.setBoost(boost); return query; } private static Long parseTime(BitemporalMapper mapper, Long defaultTime, Object value) { return value == null ? new BitemporalDateTime(defaultTime).toDate().getTime() : mapper.parseBitemporalDate(value).toDate().getTime(); } /** {@inheritDoc} */ @Override public String toString() { return toStringHelper(this).add("vtFrom", vtFrom) .add("vtTo", vtTo) .add("ttFrom", ttFrom) .add("ttTo", ttTo) .toString(); } }