001/* 002 * Copyright 2018 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.web.frontoffice.search.metamodel.impl; 017 018import java.util.Map; 019import java.util.Optional; 020 021import org.apache.commons.lang3.StringUtils; 022import org.apache.solr.client.solrj.util.ClientUtils; 023 024import org.ametys.cms.contenttype.MetadataType; 025import org.ametys.cms.search.query.FullTextQuery; 026import org.ametys.cms.search.query.NotQuery; 027import org.ametys.cms.search.query.Query; 028import org.ametys.cms.search.query.Query.Operator; 029import org.ametys.runtime.i18n.I18nizableText; 030import org.ametys.web.frontoffice.search.metamodel.SearchCriterionDefinition; 031import org.ametys.web.frontoffice.search.metamodel.Searchable; 032 033/** 034 * A wording {@link SearchCriterionDefinition}, based on {@link FullTextQuery FullTextQueries} 035 */ 036public class WordingSearchCriterionDefinition extends AbstractDefaultSearchCriterionDefinition 037{ 038 /** 039 * The type of {@link WordingSearchCriterionDefinition} 040 */ 041 public enum WordingType 042 { 043 /** A normal wording criterion, the given user input will be trimmed and sent as is to Solr */ 044 TEXTFIELD, 045 /** A wording criterion for filtering documents including all the given user words (separated by whitespaces) */ 046 ALL_WORDS, 047 /** A wording criterion for filtering documents not including any of the given user words (separated by whitespaces) */ 048 NO_WORDS 049 } 050 051 /** The wording type */ 052 protected WordingType _wordingType; 053 054 /** 055 * Constructs a {@link WordingSearchCriterionDefinition} 056 * @param id The id 057 * @param pluginName The plugin name 058 * @param label The label 059 * @param searchable the {@link Searchable} 060 * @param wordingType the type of {@link WordingSearchCriterionDefinition} 061 */ 062 public WordingSearchCriterionDefinition( 063 String id, 064 String pluginName, 065 I18nizableText label, 066 Optional<Searchable> searchable, 067 WordingType wordingType) 068 { 069 super(id, pluginName, label, MetadataType.STRING, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), searchable); 070 _wordingType = wordingType; 071 } 072 073 @Override 074 public Query getQuery(Object value, Operator operator, String language, Map<String, Object> contextualParameters) 075 { 076 switch (_wordingType) 077 { 078 case TEXTFIELD: 079 return _getTextFieldQuery(value, operator, language); 080 case ALL_WORDS: 081 case NO_WORDS: 082 Query query = _getWordsQuery(value, operator, language); 083 if (_wordingType == WordingType.NO_WORDS) 084 { 085 query = new NotQuery(query); 086 } 087 088 return query; 089 default: 090 throw new IllegalStateException("Unknown wording type: " + _wordingType); 091 } 092 } 093 094 /** 095 * Get the text field query 096 * @param value the value 097 * @param operator the operator 098 * @param language the language 099 * @return the text field query 100 */ 101 protected Query _getTextFieldQuery(Object value, Operator operator, String language) 102 { 103 return new FullTextQuery(((String) value).trim(), language, operator); 104 } 105 106 /** 107 * Get the words query 108 * @param value the value 109 * @param operator the operator 110 * @param language the language 111 * @return the words query 112 */ 113 protected Query _getWordsQuery(Object value, Operator operator, String language) 114 { 115 StringBuilder allWords = new StringBuilder(); 116 String[] words = StringUtils.split((String) value); 117 for (String word : words) 118 { 119 String escapedWord = ClientUtils.escapeQueryChars(word); 120 if (allWords.length() > 0) 121 { 122 allWords.append(' '); 123 } 124 allWords.append('+').append(escapedWord); 125 126 } 127 return new FullTextQuery(allWords.toString(), language, operator, true); 128 } 129 130 @Override 131 public Query getEmptyValueQuery(String language, Map<String, Object> contextualParameters) 132 { 133 throw new IllegalStateException("This method should not be called on the non-enumerated WordingSearchCriterionDefinition"); 134 } 135}