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.Collections; 019import java.util.List; 020import java.util.Locale; 021import java.util.Map; 022import java.util.Optional; 023import java.util.Set; 024 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.commons.lang3.LocaleUtils; 027 028import org.ametys.cms.contenttype.ContentType; 029import org.ametys.cms.search.model.impl.ReferencingCriterionDefinition; 030import org.ametys.cms.search.query.NotQuery; 031import org.ametys.cms.search.query.Query; 032import org.ametys.cms.search.query.Query.Operator; 033import org.ametys.runtime.i18n.I18nizableText; 034import org.ametys.runtime.model.DefinitionContext; 035import org.ametys.runtime.model.ElementDefinition; 036import org.ametys.runtime.model.Enumerator; 037import org.ametys.runtime.parameter.Validator; 038import org.ametys.web.frontoffice.search.metamodel.RestrictedEnumerator; 039import org.ametys.web.frontoffice.search.metamodel.SearchServiceCriterionDefinition; 040import org.ametys.web.frontoffice.search.metamodel.SearchServiceCriterionDefinitionHelper; 041import org.ametys.web.frontoffice.search.metamodel.Searchable; 042 043/** 044 * {@link SearchServiceCriterionDefinition} for {@link ContentSearchable} searching on a model item. 045 * @param <T> Type of the criterion value 046 */ 047public class ReferencingSearchServiceCriterionDefinition<T> extends ReferencingCriterionDefinition<T> implements SearchServiceCriterionDefinition<T> 048{ 049 /** The search service criterion definition helper */ 050 protected SearchServiceCriterionDefinitionHelper _searchServiceCriterionDefinitionHelper; 051 052 private Optional<Searchable> _searchable = Optional.empty(); 053 054 /** 055 * Constructor used to create a FO criterion definition on a referenced item 056 * @param reference the item referenced by this criterion 057 * @param referencePath the path of the criterion's reference 058 * @param baseContentType the content type defining the reference 059 */ 060 public ReferencingSearchServiceCriterionDefinition(ElementDefinition reference, String referencePath, ContentType baseContentType) 061 { 062 super(reference, referencePath); 063 064 if (baseContentType != null) 065 { 066 setContentTypeIds(Set.of(baseContentType.getId())); 067 } 068 } 069 070 public Optional<Searchable> getSearchable() 071 { 072 return _searchable; 073 } 074 075 public void setSearchable(Searchable searchable) 076 { 077 _searchable = Optional.ofNullable(searchable); 078 } 079 080 /** 081 * Get the label of a facet value. 082 * @param value the facet value. 083 * @param contextualParameters the contextual parameters 084 * @return the label, or null if the value does not exist. 085 */ 086 public Optional<I18nizableText> getFacetLabel(String value, Map<String, Object> contextualParameters) 087 { 088 Locale currentLocale = LocaleUtils.toLocale((String) contextualParameters.get("lang")); 089 return Optional.ofNullable(_getCriterionDefinitionHelper().getFacetLabel(this, value, currentLocale)) 090 .or(() -> Optional.of(new I18nizableText(value))); 091 } 092 093 @Override 094 public List<I18nizableText> getContextPrefixLabels() 095 { 096 return Collections.singletonList( 097 Optional.of(getReference()) 098 .map(ElementDefinition::getModel) 099 .filter(ContentType.class::isInstance) 100 .map(ContentType.class::cast) 101 .map(ContentType::getLabel) 102 .orElse(new I18nizableText("plugin.web", "PLUGINS_WEB_SERVICE_SEARCH_SEARCHABLE_CONTENT_ALL_PREFIX_LABEL"))); 103 } 104 105 @Override 106 public boolean isMultiple() 107 { 108 return isEnumerated(); 109 } 110 111 @Override 112 public Validator getValidator() 113 { 114 ElementDefinition reference = getReference(); 115 return reference.isEditable() && reference.getType().getId().equals(getType().getId()) 116 ? reference.getValidator() 117 : super.getValidator(); 118 } 119 120 @Override 121 public Query getEmptyValueQuery(String language, Map<String, Object> contextualParameters) 122 { 123 Query existQuery = getQuery(null, Operator.EXISTS, Collections.EMPTY_MAP, language, contextualParameters); 124 return new NotQuery(existQuery); 125 } 126 127 public boolean isEnumerated() 128 { 129 return getEnumerator() != null; 130 } 131 132 /** 133 * Determines if the current criterion definition is enumerated but can contain too much data 134 * @return <code>true</code> if the criterion definition can contain too much data, <code>false</code> otherwise 135 */ 136 protected boolean isTooBigForStaticEnumerator() 137 { 138 return false; 139 } 140 141 public RestrictedEnumerator<T> getRestrictedEnumerator(Map<String, Object> contextualParameters) 142 { 143 Enumerator<T> enumerator = getEnumerator(); 144 return enumerator != null 145 ? new RestrictedWrappedEnumerator<>(enumerator, getName()) 146 : null; 147 } 148 149 @Override 150 protected Map<String, Object> _toJSON(DefinitionContext context) 151 { 152 Map<String, Object> result = super._toJSON(context); 153 result.putAll(_getSearchServiceCriterionDefinitionHelper().getDefaultSearchServiceCriterionDefinitionJSON(this, isTooBigForStaticEnumerator())); 154 return result; 155 } 156 157 /** 158 * Retrieves the search service criterion definition helper 159 * @return the search service criterion definition helper 160 */ 161 protected SearchServiceCriterionDefinitionHelper _getSearchServiceCriterionDefinitionHelper() 162 { 163 if (_searchServiceCriterionDefinitionHelper == null) 164 { 165 try 166 { 167 _searchServiceCriterionDefinitionHelper = (SearchServiceCriterionDefinitionHelper) __serviceManager.lookup(SearchServiceCriterionDefinitionHelper.ROLE); 168 } 169 catch (ServiceException e) 170 { 171 throw new RuntimeException("Unable to lookup after the search service criterion definition helper", e); 172 } 173 } 174 175 return _searchServiceCriterionDefinitionHelper; 176 } 177}