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 org.ametys.cms.search.query.Query.Operator;
019
020/**
021 * Class providing helper methods to Query implementations.
022 */
023public final class QueryHelper
024{
025    /** The special value testing that the field exists. */
026    public static final String EXISTS_VALUE = "*";
027    
028    private QueryHelper()
029    {
030        // Hides the default constructor.
031    }
032    
033    /**
034     * Get a standard query on a value, with all possible standard operators.
035     * @param fieldName The field name.
036     * @param operator The operator.
037     * @param value The value, can be null if the operator is EXISTS.
038     * @return The standard value query.
039     */
040    public static final String getStandardQuery(String fieldName, Operator operator, Object value)
041    {
042        StringBuilder query = new StringBuilder();
043        
044        if (operator == Operator.NE)
045        {
046            NotQuery.appendNegation(query);
047        }
048        
049        query.append(fieldName).append(':');
050        
051        if (operator == Operator.EQ || operator == Operator.NE)
052        {
053            query.append(value);
054        }
055        else if (operator == Operator.GT)
056        {
057            query.append('{').append(value).append(" TO *]");
058        }
059        else if (operator == Operator.GE)
060        {
061            query.append('[').append(value).append(" TO *]");
062        }
063        else if (operator == Operator.LT)
064        {
065            query.append("[* TO ").append(value).append('}');
066        }
067        else if (operator == Operator.LE)
068        {
069            query.append("[* TO ").append(value).append(']');
070        }
071        else if (operator == Operator.EXISTS)
072        {
073            query.append(EXISTS_VALUE);
074        }
075        
076        return query.toString();
077    }
078    
079    /**
080     * Escape the query except stars and whitespaces.
081     * (Identical to ClientUtils#escapeQueryChars except for stars or whitespaces)
082     * @param query the string query to escape
083     * @return the escaped query
084     */
085    @SuppressWarnings("all")
086    public static String escapeQueryCharsExceptStarsAndWhitespaces(String query)
087    {
088        StringBuilder sb = new StringBuilder();
089        for (int i = 0; i < query.length(); i++)
090        {
091            char c = query.charAt(i);
092            // These characters are part of the query syntax and must be escaped (except '*' and whitespaces)
093            if (c == '\\' || c == '+' || c == '-' || c == '!'  || c == '(' || c == ')' || c == ':'
094                || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~'
095                || c == '?' || c == '|' || c == '&'  || c == ';' || c == '/')
096            {
097                sb.append('\\');
098            }
099            sb.append(c);
100        }
101        return sb.toString();
102    }
103}