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.Objects; 019 020import org.ametys.cms.content.indexing.solr.SolrFieldNames; 021import org.ametys.cms.search.QueryBuilder; 022 023/** 024 * A {@link Query} realizing a full-text search on contents (search on all properties). 025 * Available operators:<ul> 026 * <li>SEARCH (default)</li> 027 * <li>SEARCH_STEMMED</li> 028 * <li>LIKE</li> 029 * <li>EQ</li> 030 * </ul> 031 */ 032public class FullTextQuery implements Query 033{ 034 /** The value to test. */ 035 protected String _value; 036 /** The field name. */ 037 protected String _fieldName; 038 /** The language. */ 039 protected String _language; 040 /** The operator. */ 041 protected Operator _operator; 042 /** <code>true</code> if the value is already escaped and there is no need to escape again the value during {@link #build() the build of the query}. */ 043 protected boolean _valueAlreadyEscaped; 044 045 /** 046 * Build a FullTextQuery. 047 * @param value the value. 048 */ 049 public FullTextQuery(String value) 050 { 051 this(value, Operator.SEARCH); 052 } 053 054 /** 055 * Build a FullTextQuery. 056 * @param value the value. 057 * @param operator The operator to use. 058 */ 059 public FullTextQuery(String value, Operator operator) 060 { 061 this(value, null, operator); 062 } 063 064 /** 065 * Build a FullTextQuery. 066 * @param value the value. 067 * @param language the language. 068 */ 069 public FullTextQuery(String value, String language) 070 { 071 this(value, language, Operator.SEARCH); 072 } 073 074 /** 075 * Build a FullTextQuery. 076 * @param value the value. 077 * @param language the language. 078 * @param operator The operator to use. 079 */ 080 public FullTextQuery(String value, String language, Operator operator) 081 { 082 this(value, language, operator, false); 083 } 084 085 /** 086 * Build a FullTextQuery. 087 * @param value the value. 088 * @param language the language. 089 * @param operator The operator to use. 090 * @param alreadyEscaped true if the value is already escaped and there is no need to escape again the value during {@link #build() the build of the query}. 091 */ 092 public FullTextQuery(String value, String language, Operator operator, boolean alreadyEscaped) 093 { 094 this(value, SolrFieldNames.SYSTEM_FULL, language, operator, alreadyEscaped); 095 } 096 097 /** 098 * Build a FullTextQuery. 099 * @param value the value. 100 * @param fieldName the field name. 101 * @param language the language. 102 * @param operator The operator to use. 103 */ 104 public FullTextQuery(String value, String fieldName, String language, Operator operator) 105 { 106 this(value, fieldName, language, operator, false); 107 } 108 109 /** 110 * Build a FullTextQuery. 111 * @param value the value. 112 * @param fieldName the field name. 113 * @param language the language. 114 * @param operator The operator to use. 115 * @param alreadyEscaped true if the value is already escaped and there is no need to escape again the value during {@link #build() the build of the query}. 116 */ 117 public FullTextQuery(String value, String fieldName, String language, Operator operator, boolean alreadyEscaped) 118 { 119 _value = value; 120 _fieldName = fieldName; 121 _language = language; 122 _operator = operator; 123 _valueAlreadyEscaped = alreadyEscaped; 124 } 125 126 /** 127 * Get the value. 128 * @return the value. 129 */ 130 public String getValue() 131 { 132 return _value; 133 } 134 135 /** 136 * Get the language. 137 * @return the language. 138 */ 139 public String getLanguage() 140 { 141 return _language; 142 } 143 144 /** 145 * Get the operator to use. 146 * @return the operator. 147 */ 148 public Operator getOperator() 149 { 150 return _operator; 151 } 152 153 @Override 154 public String build() throws QuerySyntaxException 155 { 156 String language = _language != null ? _language : QueryBuilder.DEFAULT_LANGUAGE; 157 158 AbstractTextQuery.checkStringValue(_value); 159 160 String escapedValue = _valueAlreadyEscaped ? _value : AbstractTextQuery.escapeStringValue(_value, _operator); 161 162 StringBuilder solrQuery = new StringBuilder(); 163 164 switch (_operator) 165 { 166 case EQ: 167 solrQuery.append(_fieldName).append(SolrFieldNames.EXACT_WS_OPERATOR) 168 .append(":\"").append(escapedValue).append('"'); 169 break; 170 case LIKE: 171 solrQuery.append(_fieldName) 172 .append(":(").append(escapedValue).append(')'); 173 break; 174 case SEARCH_STEMMED: 175 solrQuery.append(_fieldName).append(SolrFieldNames.STEMMED_OPERATOR).append(SolrFieldNames.LANGUAGE_SEPARATOR).append(language) 176 .append(":(").append(escapedValue).append(')'); 177 break; 178 case SEARCH: 179 default: 180 solrQuery.append(_fieldName).append(SolrFieldNames.LANGUAGE_SEPARATOR).append(language) 181 .append(":(").append(escapedValue).append(')'); 182 break; 183 } 184 185 return solrQuery.toString(); 186 } 187 188 @Override 189 public int hashCode() 190 { 191 return 31 + Objects.hash(_language, _operator, _value); 192 } 193 194 @Override 195 public boolean equals(Object obj) 196 { 197 if (this == obj) 198 { 199 return true; 200 } 201 202 if (obj == null || getClass() != obj.getClass()) 203 { 204 return false; 205 } 206 207 FullTextQuery other = (FullTextQuery) obj; 208 return Objects.equals(_language, other._language) 209 && Objects.equals(_operator, other._operator) 210 && Objects.equals(_value, other._value); 211 } 212}