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 private WordingType _wordingType; 052 053 /** 054 * Constructs a {@link WordingSearchCriterionDefinition} 055 * @param id The id 056 * @param pluginName The plugin name 057 * @param label The label 058 * @param searchable the {@link Searchable} 059 * @param wordingType the type of {@link WordingSearchCriterionDefinition} 060 */ 061 public WordingSearchCriterionDefinition( 062 String id, 063 String pluginName, 064 I18nizableText label, 065 Optional<Searchable> searchable, 066 WordingType wordingType) 067 { 068 super(id, pluginName, label, MetadataType.STRING, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), searchable); 069 _wordingType = wordingType; 070 } 071 072 @Override 073 public Query getQuery(Object value, Operator operator, String language, Map<String, Object> contextualParameters) 074 { 075 switch (_wordingType) 076 { 077 case TEXTFIELD: 078 return new FullTextQuery(((String) value).trim(), language, operator); 079 case ALL_WORDS: 080 case NO_WORDS: 081 StringBuilder allWords = new StringBuilder(); 082 String[] words = StringUtils.split((String) value); 083 for (String word : words) 084 { 085 String escapedWord = ClientUtils.escapeQueryChars(word); 086 if (allWords.length() > 0) 087 { 088 allWords.append(' '); 089 } 090 allWords.append('+').append(escapedWord); 091 092 } 093 Query query = new FullTextQuery(allWords.toString(), language, operator, true); 094 if (_wordingType == WordingType.NO_WORDS) 095 { 096 query = new NotQuery(query); 097 } 098 099 return query; 100 default: 101 throw new IllegalStateException("Unknown wording type: " + _wordingType); 102 } 103 } 104}