001/*
002 *  Copyright 2016 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.cms.search.query;
017
018import java.time.LocalDate;
019import java.time.LocalTime;
020
021import org.ametys.core.util.date.AdaptableDate;
022
023/**
024 * Represents a {@link Query} testing a date range.
025 */
026public class DateRangeQuery extends AbstractFieldQuery
027{
028    
029    /** The lower end of the date range. */
030    protected AdaptableDate _from;
031    /** The upper end of the date range. */
032    protected AdaptableDate _to;
033    /** True to include the lower end, false to exclude it. */
034    protected boolean _includeFrom;
035    /** True to include the upper end, false to exclude it. */
036    protected boolean _includeTo;
037    
038    /**
039     * Build a date range query.
040     * @param fieldPath The field path.
041     * @param from The lower end of the range.
042     * @param to The upper end of the range.
043     */
044    public DateRangeQuery(String fieldPath, LocalDate from, LocalDate to)
045    {
046        this(fieldPath, AdaptableDate.fromDate(from), AdaptableDate.fromDate(to));
047    }
048    
049    /**
050     * Build a date range query.
051     * @param fieldPath The field path.
052     * @param from The lower end of the range.
053     * @param to The upper end of the range.
054     */
055    public DateRangeQuery(String fieldPath, AdaptableDate from, AdaptableDate to)
056    {
057        this(fieldPath, from, to, true, true);
058    }
059    
060    /**
061     * Build a date range query.
062     * @param fieldPath The field path.
063     * @param from The lower end of the range.
064     * @param to The upper end of the range.
065     * @param includeFrom Whether to include the lower end or not.
066     * @param includeTo Whether to include the upper end or not.
067     */
068    public DateRangeQuery(String fieldPath, LocalDate from, LocalDate to, boolean includeFrom, boolean includeTo)
069    {
070        this(fieldPath, AdaptableDate.fromDate(from), AdaptableDate.fromDate(to), includeFrom, includeTo);
071    }
072    
073    /**
074     * Build a date range query.
075     * @param fieldPath The field path.
076     * @param from The lower end of the range.
077     * @param to The upper end of the range.
078     * @param includeFrom Whether to include the lower end or not.
079     * @param includeTo Whether to include the upper end or not.
080     */
081    public DateRangeQuery(String fieldPath, AdaptableDate from, AdaptableDate to, boolean includeFrom, boolean includeTo)
082    {
083        super(fieldPath);
084        _from = from;
085        _to = to;
086        _includeFrom = includeFrom;
087        _includeTo = includeTo;
088    }
089    
090    @Override
091    public String build() throws QuerySyntaxException
092    {
093        String fromStr = _from.resolveDate()
094                .atTime(_includeFrom ? LocalTime.MIN : LocalTime.MAX)
095                .format(DateQuery.DATE_FORMATTER);
096        String toStr = _to.resolveDate()
097                .atTime(_includeTo ? LocalTime.MAX : LocalTime.MIN)
098                .format(DateQuery.DATE_FORMATTER);
099        
100        StringBuilder query = new StringBuilder();
101        
102        query.append(_fieldPath).append("_dt:")
103             .append(_includeFrom ? '[' : '{')
104             .append(fromStr).append(" TO ").append(toStr)
105             .append(_includeTo ? ']' : '}');
106        
107        return query.toString();
108    }
109
110    @Override
111    public int hashCode()
112    {
113        final int prime = 31;
114        int result = super.hashCode();
115        result = prime * result + ((_from == null) ? 0 : _from.hashCode());
116        result = prime * result + (_includeFrom ? 1231 : 1237);
117        result = prime * result + (_includeTo ? 1231 : 1237);
118        result = prime * result + ((_to == null) ? 0 : _to.hashCode());
119        return result;
120    }
121
122    @Override
123    public boolean equals(Object obj)
124    {
125        if (this == obj)
126        {
127            return true;
128        }
129        if (!super.equals(obj))
130        {
131            return false;
132        }
133        if (getClass() != obj.getClass())
134        {
135            return false;
136        }
137        DateRangeQuery other = (DateRangeQuery) obj;
138        if (_from == null)
139        {
140            if (other._from != null)
141            {
142                return false;
143            }
144        }
145        else if (!_from.equals(other._from))
146        {
147            return false;
148        }
149        if (_includeFrom != other._includeFrom)
150        {
151            return false;
152        }
153        if (_includeTo != other._includeTo)
154        {
155            return false;
156        }
157        if (_to == null)
158        {
159            if (other._to != null)
160            {
161                return false;
162            }
163        }
164        else if (!_to.equals(other._to))
165        {
166            return false;
167        }
168        return true;
169    }
170}