001/* 002 * Copyright 2024 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.model.impl; 017 018import java.util.ArrayList; 019import java.util.List; 020import java.util.Locale; 021import java.util.Map; 022import java.util.Optional; 023 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.commons.lang3.BooleanUtils; 026 027import org.ametys.cms.data.type.indexing.IndexableElementType; 028import org.ametys.cms.model.CMSDataContext; 029import org.ametys.cms.search.QueryBuilder; 030import org.ametys.cms.search.model.CriterionDefinition; 031import org.ametys.cms.search.model.CriterionDefinitionHelper; 032import org.ametys.cms.search.query.Query; 033import org.ametys.cms.search.query.Query.LogicalOperator; 034import org.ametys.cms.search.query.Query.Operator; 035import org.ametys.runtime.i18n.I18nizableText; 036import org.ametys.runtime.model.DefaultElementDefinition; 037 038/** 039 * Abstract implementation for {@link CriterionDefinition} 040 * @param <T> Type of the criterion value 041 */ 042public abstract class AbstractCriterionDefinition<T> extends DefaultElementDefinition<T> implements CriterionDefinition<T> 043{ 044 /** The criterion definition helper */ 045 protected CriterionDefinitionHelper _criterionDefinitionHelper; 046 047 /** Logical operator to use for multi-valued criteria */ 048 protected LogicalOperator _multipleOperandOperator = LogicalOperator.OR; 049 050 /** The criterion's solr facet field name */ 051 protected String _solrFacetFieldName; 052 053 /** The criterion's joined paths */ 054 protected List<String> _joinedPaths = new ArrayList<>(); 055 056 /** 057 * Retrieves the logical operator for multi-valued criteria 058 * @return the the logical operator for multi-valued criteria 059 */ 060 protected LogicalOperator getMultipleOperandOperator() 061 { 062 return _multipleOperandOperator; 063 } 064 065 public Query getQuery(Object value, Operator operator, Map<String, Object> allValues, String language, Map<String, Object> contextualParameters) 066 { 067 if (operator != Operator.EXISTS && _getCriterionDefinitionHelper().isQueryValueEmpty(value)) 068 { 069 return null; 070 } 071 072 boolean isMultipleOperandAnd = LogicalOperator.AND.equals(getMultipleOperandOperator()); 073 CMSDataContext context = getQueryContext(language, contextualParameters); 074 075 return getType().getDefaultQuery(value, getName(), operator, isMultipleOperandAnd, context); 076 } 077 078 public Object convertQueryValue(Object value, Map<String, Object> contextualParameters) 079 { 080 CMSDataContext context = getQueryContext(null, contextualParameters); 081 return getType().convertQueryValue(value, context); 082 } 083 084 /** 085 * Retrieves the context to use in query 086 * @param language The current search language. 087 * @param contextualParameters the search contextual parameters. 088 * @return the context to use in query 089 */ 090 protected CMSDataContext getQueryContext(String language, Map<String, Object> contextualParameters) 091 { 092 return CMSDataContext.newInstance() 093 .withMultilingualSearch(contextualParameters.containsKey(QueryBuilder.MULTILINGUAL_SEARCH)) 094 .withSearchedValueEscaped(BooleanUtils.isTrue((Boolean) contextualParameters.get(QueryBuilder.VALUE_IS_ESCAPED))) 095 .withLocale(Optional.ofNullable(language) 096 .map(Locale::forLanguageTag) 097 .orElse(null)); 098 } 099 100 public String getSolrFacetFieldName(Map<String, Object> contextualParameters) 101 { 102 return _solrFacetFieldName; 103 } 104 105 /** 106 * Set the criterion's solr facet field name 107 * @param solrFacetFieldName the solr facet field name to set 108 */ 109 public void setSolrFacetFieldName(String solrFacetFieldName) 110 { 111 _solrFacetFieldName = solrFacetFieldName; 112 } 113 114 public List<String> getJoinedPaths(Map<String, Object> contextualParameters) 115 { 116 return _joinedPaths; 117 } 118 119 /** 120 * Set the criterion's joined paths 121 * @param joinedPath the joined paths to set 122 */ 123 public void setJoinedPaths(List<String> joinedPath) 124 { 125 _joinedPaths = joinedPath; 126 } 127 128 @Override 129 public String getWidget() 130 { 131 return Optional.ofNullable(super.getWidget()) 132 .orElseGet(this::_getDefaultWidget); 133 } 134 135 /** 136 * Retrieves the default widget for the criterion 137 * @return the default widget for the criterion 138 */ 139 protected String _getDefaultWidget() 140 { 141 return _getCriterionDefinitionHelper().getCriterionDefinitionDefaultWidget(this); 142 } 143 144 @Override 145 public Map<String, I18nizableText> getWidgetParameters() 146 { 147 Map<String, I18nizableText> widgetParameters = _getDefaultWidgetParameters(); 148 149 // Override default parameters with widget parameters from the criterion itself 150 widgetParameters.putAll(super.getWidgetParameters()); 151 152 return widgetParameters; 153 } 154 155 /** 156 * Retrieves the default widget parameters for the criterion 157 * @return the default widget parameters for the criterion 158 */ 159 protected Map<String, I18nizableText> _getDefaultWidgetParameters() 160 { 161 return _getCriterionDefinitionHelper().getCriterionDefinitionDefaultWidgetParameters(this); 162 } 163 164 @Override 165 public IndexableElementType<T> getType() 166 { 167 return (IndexableElementType<T>) super.getType(); 168 } 169 170 /** 171 * Retrieves the {@link CriterionDefinitionHelper} 172 * @return the {@link CriterionDefinitionHelper} 173 */ 174 protected CriterionDefinitionHelper _getCriterionDefinitionHelper() 175 { 176 if (_criterionDefinitionHelper == null) 177 { 178 try 179 { 180 _criterionDefinitionHelper = (CriterionDefinitionHelper) __serviceManager.lookup(CriterionDefinitionHelper.ROLE); 181 } 182 catch (ServiceException e) 183 { 184 throw new RuntimeException("Unable to lookup after the criterion definition helper", e); 185 } 186 } 187 188 return _criterionDefinitionHelper; 189 } 190 191}