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.util.Map; 019 020import org.apache.commons.lang3.StringUtils; 021 022/** 023 * Represents a {@link Query} corresponding to the logical negation of another {@link Query}. 024 */ 025public class NotQuery extends AbstractWrapperQuery 026{ 027 /** The prefix for making a query negative. */ 028 public static final String NEGATION_QUERY_PREFIX = "*:* -"; 029 030 /** 031 * Build a NotQuery object. 032 * @param query the negated query. 033 */ 034 public NotQuery(Query query) 035 { 036 super(query); 037 } 038 039 /** 040 * Appends a negation to the query being built. 041 * <br>This method just does <code>sb.append({@value #NEGATION_QUERY_PREFIX});</code> 042 * @param query The query builder 043 * @return The given query builder 044 */ 045 public static StringBuilder appendNegation(StringBuilder query) 046 { 047 query.append(NEGATION_QUERY_PREFIX); 048 return query; 049 } 050 051 @Override 052 public String build() throws QuerySyntaxException 053 { 054 String queryString = getSubQuery().build(); 055 if (queryString.isEmpty()) 056 { 057 return ""; 058 } 059 else 060 { 061 return NEGATION_QUERY_PREFIX + "(" + queryString + ")"; 062 } 063 } 064 065 public Object buildAsJson() throws QuerySyntaxException 066 { 067 Query rewrittenQuery = getSubQuery().rewrite(); 068 069 if (rewrittenQuery instanceof NotQuery nq) 070 { 071 return nq.getSubQuery().buildAsJson(); 072 } 073 else 074 { 075 return Map.of("bool", Map.of("must", "*:*", "must_not", rewrittenQuery.buildAsJson())); 076 } 077 } 078 079 public Query rewrite() 080 { 081 Query subQuery = getSubQuery(); 082 Query rewrittenQuery = subQuery.rewrite(); 083 084 if (rewrittenQuery == subQuery) 085 { 086 return this; 087 } 088 else if (rewrittenQuery instanceof NotQuery nq) 089 { 090 return nq.getSubQuery(); 091 } 092 else 093 { 094 return new NotQuery(rewrittenQuery); 095 } 096 } 097 098 @Override 099 public String toString(int indent) 100 { 101 final String notLineIndent = StringUtils.repeat(' ', indent); 102 final String subq = getSubQuery().toString(indent + 2); 103 return notLineIndent + "[NOT]\n" + subq + "\n" + notLineIndent + "[/NOT]"; 104 } 105}