001/* 002 * Copyright 2017 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.Arrays; 019import java.util.Collection; 020import java.util.Collections; 021import java.util.List; 022import java.util.stream.Collectors; 023 024import org.apache.commons.lang3.StringUtils; 025 026/** 027 * Represents a search {@link Query} corresponding to the logical "and" between several other queries. 028 */ 029public class AndQuery implements Query 030{ 031 032 /** The list of queries. The queries on this list are distinct. */ 033 protected List<Query> _queries; 034 /** If a query is empty should just ignore it, or return an empty AndQuery */ 035 protected boolean _ignoreEmptyQueries; 036 037 /** 038 * Build an AndQuery object. 039 * @param queries the queries. 040 */ 041 public AndQuery(Query... queries) 042 { 043 this(true, queries); 044 } 045 046 /** 047 * Build an AndQuery object. 048 * @param ignoreEmptyQueries If a query is empty should just ignore it, or return an empty AndQuery 049 * @param queries the queries. 050 */ 051 public AndQuery(boolean ignoreEmptyQueries, Query... queries) 052 { 053 this(ignoreEmptyQueries, Arrays.asList(queries)); 054 } 055 056 /** 057 * Build an AndQuery object. 058 * @param queries the queries as a Collection. 059 */ 060 public AndQuery(Collection<Query> queries) 061 { 062 this(true, queries); 063 } 064 065 /** 066 * Build an AndQuery object. 067 * @param ignoreEmptyQueries If a query is empty should just ignore it, or return an empty AndQuery 068 * @param queries the queries as a Collection. 069 */ 070 public AndQuery(boolean ignoreEmptyQueries, Collection<Query> queries) 071 { 072 _queries = queries.stream().distinct().collect(Collectors.toList()); 073 _ignoreEmptyQueries = ignoreEmptyQueries; 074 } 075 076 /** 077 * Get the list of queries in this "and". 078 * @return the list of queries. 079 */ 080 public List<Query> getQueries() 081 { 082 return Collections.unmodifiableList(_queries); 083 } 084 085 @Override 086 public String build() throws QuerySyntaxException 087 { 088 boolean isFirst = true; 089 StringBuilder sb = new StringBuilder(); 090 091 if (_queries.size() > 1) 092 { 093 sb.append('('); 094 } 095 096 for (Query subQuery : _queries) 097 { 098 if (subQuery != null) 099 { 100 String exprAsString = subQuery.build(); 101 if (StringUtils.isNotBlank(exprAsString)) 102 { 103 if (!isFirst) 104 { 105 sb.append(" AND "); 106 } 107 sb.append(exprAsString); 108 isFirst = false; 109 } 110 else if (!_ignoreEmptyQueries) 111 { 112 return ""; 113 } 114 } 115 } 116 117 if (isFirst) 118 { 119 return ""; 120 } 121 else 122 { 123 if (_queries.size() > 1) 124 { 125 sb.append(')'); 126 } 127 return sb.toString(); 128 } 129 } 130 131 @Override 132 public int hashCode() 133 { 134 final int prime = 31; 135 int result = 1; 136 result = prime * result + (_ignoreEmptyQueries ? 1231 : 1237); 137 result = prime * result + ((_queries == null) ? 0 : _queries.hashCode()); 138 return result; 139 } 140 141 @Override 142 public boolean equals(Object obj) 143 { 144 if (this == obj) 145 { 146 return true; 147 } 148 if (obj == null) 149 { 150 return false; 151 } 152 if (getClass() != obj.getClass()) 153 { 154 return false; 155 } 156 AndQuery other = (AndQuery) obj; 157 if (_ignoreEmptyQueries != other._ignoreEmptyQueries) 158 { 159 return false; 160 } 161 if (_queries == null) 162 { 163 if (other._queries != null) 164 { 165 return false; 166 } 167 } 168 else if (!_queries.equals(other._queries)) 169 { 170 return false; 171 } 172 return true; 173 } 174}