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 org.apache.commons.lang3.StringUtils;
019
020/**
021 * Represents a {@link Query} corresponding to the logical negation of another {@link Query}.
022 */
023public class NotQuery implements Query
024{
025    /** The prefix for making a query negative. */
026    public static final String NEGATION_QUERY_PREFIX = "*:* -";
027    
028    /** The negated query. */
029    protected Query _query;
030    
031    /**
032     * Build a NotQuery object.
033     * @param query the negated query.
034     */
035    public NotQuery(Query query)
036    {
037        _query = query;
038    }
039    
040    /**
041     * Get the negated query.
042     * @return the negated query.
043     */
044    public Query getQuery()
045    {
046        return _query;
047    }
048    
049    /**
050     * Appends a negation to the query being built.
051     * <br>This method just does <code>sb.append({@value #NEGATION_QUERY_PREFIX});</code>
052     * @param query The query builder
053     * @return The given query builder
054     */
055    public static StringBuilder appendNegation(StringBuilder query)
056    {
057        query.append(NEGATION_QUERY_PREFIX);
058        return query;
059    }
060    
061    @Override
062    public String build() throws QuerySyntaxException
063    {
064        String queryString = _query.build();
065        if (queryString.isEmpty())
066        {
067            return "";
068        }
069        else
070        {
071            return "(" + NEGATION_QUERY_PREFIX + "(" + _query.build() + "))";
072        }
073    }
074    
075    @Override
076    public String toString(int indent)
077    {
078        final String notLineIndent = StringUtils.repeat(' ', indent);
079        final String subq = _query.toString(indent + 2);
080        return notLineIndent + "[NOT]\n" +  subq + "\n" + notLineIndent + "[/NOT]";
081    }
082
083    @Override
084    public int hashCode()
085    {
086        final int prime = 31;
087        int result = 1;
088        result = prime * result + ((_query == null) ? 0 : _query.hashCode());
089        return result;
090    }
091
092    @Override
093    public boolean equals(Object obj)
094    {
095        if (this == obj)
096        {
097            return true;
098        }
099        if (obj == null)
100        {
101            return false;
102        }
103        if (getClass() != obj.getClass())
104        {
105            return false;
106        }
107        NotQuery other = (NotQuery) obj;
108        if (_query == null)
109        {
110            if (other._query != null)
111            {
112                return false;
113            }
114        }
115        else if (!_query.equals(other._query))
116        {
117            return false;
118        }
119        return true;
120    }
121}