001/*
002 *  Copyright 2014 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.text.DateFormat;
019import java.text.SimpleDateFormat;
020import java.util.Date;
021
022/**
023 * Represents a {@link Query} testing a date field.
024 */
025public class DateQuery extends AbstractFieldQuery
026{
027    
028    /** The date format. */
029    public static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
030    
031    /** The operator. */
032    protected Operator _operator;
033    /** The value to test. */
034    protected Date _value;
035    
036    /**
037     * Build a DateQuery testing the existence of the field.
038     * @param fieldPath the field path.
039     */
040    public DateQuery(String fieldPath)
041    {
042        this(fieldPath, Operator.EXISTS, null);
043    }
044    
045    /**
046     * Build a DateQuery.
047     * @param fieldPath the field's path
048     * @param value the value.
049     */
050    public DateQuery(String fieldPath, Date value)
051    {
052        this(fieldPath, Operator.EQ, value);
053    }
054    
055    /**
056     * Build a DateQuery.
057     * @param fieldPath the field's path
058     * @param op the operator.
059     * @param value the value.
060     */
061    public DateQuery(String fieldPath, Operator op, Date value)
062    {
063        super(fieldPath);
064        _operator = op;
065        _value = value;
066    }
067    
068    /**
069     * Get the operator.
070     * @return the operator.
071     */
072    public Operator getOperator()
073    {
074        return _operator;
075    }
076    
077    /**
078     * Get the value.
079     * @return the value.
080     */
081    public Date getValue()
082    {
083        return _value;
084    }
085    
086    @Override
087    public String build() throws QuerySyntaxException
088    {
089        StringBuilder query = new StringBuilder();
090        
091        if (_operator == Operator.NE)
092        {
093            NotQuery.appendNegation(query);
094        }
095        
096        query.append(_fieldPath).append("_dt:");
097        
098        if (_operator == Operator.EXISTS)
099        {
100            query.append(QueryHelper.EXISTS_VALUE);
101        }
102        else
103        {
104            appendDateValue(query, _operator, _value);
105        }
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 + ((_operator == null) ? 0 : _operator.hashCode());
116        result = prime * result + ((_value == null) ? 0 : _value.hashCode());
117        return result;
118    }
119
120    @Override
121    public boolean equals(Object obj)
122    {
123        if (this == obj)
124        {
125            return true;
126        }
127        if (!super.equals(obj))
128        {
129            return false;
130        }
131        if (getClass() != obj.getClass())
132        {
133            return false;
134        }
135        DateQuery other = (DateQuery) obj;
136        if (_operator != other._operator)
137        {
138            return false;
139        }
140        if (_value == null)
141        {
142            if (other._value != null)
143            {
144                return false;
145            }
146        }
147        else if (!_value.equals(other._value))
148        {
149            return false;
150        }
151        return true;
152    }
153
154    /**
155     * Format and append the given date to a StringBuilder.
156     * @param query The string builder containing the query being built.
157     * @param operator The query operator.
158     * @param value The test value.
159     */
160    public static void appendDateValue(StringBuilder query, Operator operator, Date value)
161    {
162        String strValue = DATE_FORMAT.format(value);
163        
164        if (operator == Operator.EQ || operator == Operator.NE)
165        {
166            query.append('"').append(strValue).append('"');
167        }
168        else if (operator == Operator.GT)
169        {
170            query.append('{').append(strValue).append(" TO *]");
171        }
172        else if (operator == Operator.GE)
173        {
174            query.append('[').append(strValue).append(" TO *]");
175        }
176        else if (operator == Operator.LT)
177        {
178            query.append("[* TO ").append(strValue).append('}');
179        }
180        else if (operator == Operator.LE)
181        {
182            query.append("[* TO ").append(strValue).append(']');
183        }
184    }
185    
186}