001/* 002 * Copyright 2015 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; 019 020import org.ametys.cms.content.indexing.solr.SolrFieldNames; 021 022 023/** 024 * Represents a {@link Query} testing if an object possesses one or more tags. 025 */ 026public class TagQuery implements Query 027{ 028 029 private Operator _operator; 030 private String[] _values; 031 private LogicalOperator _logicalOperator; 032 private boolean _descendantAutoposting; 033 034 /** 035 * Build a TagQuery. 036 * @param value the tag id to test. 037 */ 038 public TagQuery(String value) 039 { 040 this(new String[] {value}); 041 } 042 043 /** 044 * Build a TagQuery. 045 * @param values the tag IDs to test. 046 */ 047 public TagQuery(String... values) 048 { 049 this(Operator.EQ, values); 050 } 051 052 /** 053 * Build a TagQuery. 054 * @param operator the operator. 055 * @param value the tag id to test. 056 */ 057 public TagQuery(Operator operator, String value) 058 { 059 this(operator, new String[] {value}); 060 } 061 062 /** 063 * Build a TagQuery. 064 * @param operator the operator. 065 * @param values the tag IDs to test. 066 */ 067 public TagQuery(Operator operator, String... values) 068 { 069 this(operator, false, values); 070 } 071 072 /** 073 * Build a TagQuery. 074 * @param operator the operator. 075 * @param descendantAutoposting true to enable descendant autoposting (parent tags are found), false otherwise. 076 * @param value the tag id to test. 077 */ 078 public TagQuery(Operator operator, boolean descendantAutoposting, String value) 079 { 080 this(operator, descendantAutoposting, new String[] {value}); 081 } 082 083 /** 084 * Build a TagQuery. 085 * @param operator the operator. 086 * @param descendantAutoposting true to enable descendant autoposting (parent tags are found), false otherwise. 087 * @param values the tag IDs to test. 088 */ 089 public TagQuery(Operator operator, boolean descendantAutoposting, String... values) 090 { 091 this(operator, descendantAutoposting, LogicalOperator.OR, values); 092 } 093 094 /** 095 * Build a TagQuery. 096 * @param operator the operator. The operator is applied to each value individually. 097 * For instance, if operator is {@link Query.Operator#NE NE} and logicalOperator is 098 * {@link Query.LogicalOperator#OR OR}, then the Query represents: <code>(NOT A) OR (NOT B) ...</code> 099 * @param descendantAutoposting true to enable descendant autoposting (parent tags are found), false otherwise. 100 * @param logicalOperator the logical operator. 101 * @param values the tag IDs to test. 102 */ 103 public TagQuery(Operator operator, boolean descendantAutoposting, LogicalOperator logicalOperator, String... values) 104 { 105 if (Operator.EQ != operator && Operator.NE != operator && Operator.EXISTS != operator) 106 { 107 throw new IllegalArgumentException("Test operator '" + operator + "' can't be used for a tag query."); 108 } 109 110 _operator = operator; 111 _logicalOperator = logicalOperator; 112 _values = values; 113 _descendantAutoposting = descendantAutoposting; 114 } 115 116 /** 117 * Get the operator. 118 * @return the operator 119 */ 120 public Operator getOperator() 121 { 122 return _operator; 123 } 124 125 /** 126 * Get the values. 127 * @return the values 128 */ 129 public String[] getValues() 130 { 131 return _values; 132 } 133 134 /** 135 * Get the logicalOperator. 136 * @return the logicalOperator 137 */ 138 public LogicalOperator getLogicalOperator() 139 { 140 return _logicalOperator; 141 } 142 143 @Override 144 public String build() throws QuerySyntaxException 145 { 146 StringBuilder query = new StringBuilder(); 147 148 if (_operator == Operator.EXISTS) 149 { 150 query.append(SolrFieldNames.ALL_TAGS).append(":").append(QueryHelper.EXISTS_VALUE); 151 152 return query.toString(); 153 } 154 155 if (_values.length > 0) 156 { 157 for (int i = 0; i < _values.length; i++) 158 { 159 if (i > 0) 160 { 161 query.append(' ').append(_logicalOperator).append(' '); 162 } 163 if (_values.length > 1) 164 { 165 query.append('('); 166 } 167 168 if (_operator == Operator.NE) 169 { 170 NotQuery.appendNegation(query); 171 } 172 173 query.append(_descendantAutoposting ? SolrFieldNames.ALL_TAGS : SolrFieldNames.TAGS) 174 .append(':').append(_values[i]); 175 176 if (_values.length > 1) 177 { 178 query.append(')'); 179 } 180 } 181 } 182 183 return query.toString(); 184 } 185 186 @Override 187 public int hashCode() 188 { 189 final int prime = 31; 190 int result = 1; 191 result = prime * result + (_descendantAutoposting ? 1231 : 1237); 192 result = prime * result + ((_logicalOperator == null) ? 0 : _logicalOperator.hashCode()); 193 result = prime * result + ((_operator == null) ? 0 : _operator.hashCode()); 194 result = prime * result + Arrays.hashCode(_values); 195 return result; 196 } 197 198 @Override 199 public boolean equals(Object obj) 200 { 201 if (this == obj) 202 { 203 return true; 204 } 205 if (obj == null) 206 { 207 return false; 208 } 209 if (getClass() != obj.getClass()) 210 { 211 return false; 212 } 213 TagQuery other = (TagQuery) obj; 214 if (_descendantAutoposting != other._descendantAutoposting) 215 { 216 return false; 217 } 218 if (_logicalOperator != other._logicalOperator) 219 { 220 return false; 221 } 222 if (_operator != other._operator) 223 { 224 return false; 225 } 226 if (!Arrays.equals(_values, other._values)) 227 { 228 return false; 229 } 230 return true; 231 } 232}