001/* 002 * Copyright 2017 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.plugins.thesaurus.search; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.List; 021import java.util.Map; 022 023import org.apache.avalon.framework.configuration.Configuration; 024import org.apache.avalon.framework.configuration.ConfigurationException; 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.commons.lang.BooleanUtils; 028import org.apache.commons.lang.StringUtils; 029 030import org.ametys.cms.contenttype.MetadataType; 031import org.ametys.cms.repository.Content; 032import org.ametys.cms.search.query.OrQuery; 033import org.ametys.cms.search.query.Query; 034import org.ametys.cms.search.query.Query.Operator; 035import org.ametys.cms.search.query.StringQuery; 036import org.ametys.cms.search.ui.model.SearchUICriterion; 037import org.ametys.cms.search.ui.model.impl.IndexingFieldSearchUICriterion; 038import org.ametys.plugins.repository.AmetysObjectIterable; 039import org.ametys.plugins.thesaurus.ThesaurusDAO; 040import org.ametys.runtime.i18n.I18nizableText; 041import org.ametys.runtime.parameter.ParameterHelper; 042import org.ametys.runtime.parameter.ParameterHelper.ParameterType; 043 044/** 045 * Implementation of {@link SearchUICriterion} for a custom criteria for a metadata of type 'content' linked to a term of thesaurus. 046 */ 047public class TermSearchUICriterion extends IndexingFieldSearchUICriterion 048{ 049 /** The thesaurus DAO */ 050 protected ThesaurusDAO _thesaurusDAO; 051 052 @Override 053 public void service(ServiceManager smanager) throws ServiceException 054 { 055 super.service(smanager); 056 _thesaurusDAO = (ThesaurusDAO) smanager.lookup(ThesaurusDAO.ROLE); 057 } 058 059 @Override 060 public void configure(Configuration configuration) throws ConfigurationException 061 { 062 super.configure(configuration); 063 064 MetadataType type = getType(); 065 if (type == MetadataType.CONTENT || type == MetadataType.SUB_CONTENT) 066 { 067 setWidget("edition.select-term"); 068 069 // Override the widget parameters to disable search and creation 070 Map<String, I18nizableText> widgetParameters = getWidgetParameters(); 071 widgetParameters.put("allowCreation", new I18nizableText("false")); 072 widgetParameters.put("allowSearch", new I18nizableText("true")); 073 074 widgetParameters.put("allowSeeIndexedContent", new I18nizableText("false")); 075 widgetParameters.put("allowToggleAutoposting", new I18nizableText("true")); 076 widgetParameters.put("hideCandidates", new I18nizableText("false")); 077 widgetParameters.put("disableCandidateCreation", new I18nizableText("true")); 078 widgetParameters.put("showSelectedTermAlert", new I18nizableText("false")); 079 widgetParameters.put("genericTermAlertTitle", new I18nizableText("plugin.thesaurus", "PLUGINS_THESAURUS_CHOOSETERMHELPER_SEARCH_GENERIC_TERM_TITLE")); 080 widgetParameters.put("genericTermAlertDesc", new I18nizableText("plugin.thesaurus", "PLUGINS_THESAURUS_CHOOSETERMHELPER_SEARCH_GENERIC_TERM_DESC")); 081 082 setWidgetParameters(widgetParameters); 083 } 084 else 085 { 086 List<String> pathParts = new ArrayList<>(_joinPaths); 087 pathParts.add(_fieldPath); 088 throw new ConfigurationException("Invalid search criteria for metadata " + StringUtils.join(pathParts, '/') + ". The metadata have to be of type 'content'"); 089 } 090 } 091 092 093 @SuppressWarnings("unchecked") 094 @Override 095 protected Query getContentQuery(Object value, String language, String fieldPath, Operator operator) 096 { 097 if (value instanceof Map<?, ?>) 098 { 099 // Handle autoposting 100 Map<String, Object> valueAsMap = (Map<String, Object>) value; 101 102 List<String> termIds = new ArrayList<>(); 103 104 Object rawValue = valueAsMap.get("value"); 105 if (rawValue instanceof Collection<?>) 106 { 107 termIds.addAll((List<String>) rawValue); 108 } 109 else 110 { 111 String stringValue = (String) ParameterHelper.castValue((String) value, ParameterType.STRING); 112 termIds.add(stringValue); 113 } 114 115 boolean autoposting = BooleanUtils.isTrue((Boolean) valueAsMap.get("autoposting")); 116 if (autoposting) 117 { 118 return getAutopostingTermsQuery(termIds, language, fieldPath, operator); 119 } 120 else 121 { 122 return super.getContentQuery(termIds, language, fieldPath, operator); 123 } 124 } 125 else 126 { 127 return super.getContentQuery(value, language, fieldPath, operator); 128 } 129 } 130 131 /** 132 * Get a term query with autoposting. 133 * @param termIds The value to use for this criterion. 134 * @param language The search language. 135 * @param fieldPath The field path. 136 * @param operator The query operator to use. 137 * @return The query. 138 */ 139 protected Query getAutopostingTermsQuery (List<String> termIds, String language, String fieldPath, Operator operator) 140 { 141 List<Query> queries = new ArrayList<>(); 142 for (String termId : termIds) 143 { 144 queries.add(getAutopostingTermQuery(termId, language, fieldPath, operator)); 145 } 146 return new OrQuery(queries); 147 } 148 149 /** 150 * Get a term query with autoposting. 151 * @param termId The id of the term 152 * @param language The search language. 153 * @param fieldPath The field path. 154 * @param operator The query operator to use. 155 * @return The query. 156 */ 157 protected Query getAutopostingTermQuery(String termId, String language, String fieldPath, Operator operator) 158 { 159 List<String> aupostingTermIds = new ArrayList<>(); 160 aupostingTermIds.add(termId); 161 aupostingTermIds.addAll(getChildTermIds(termId)); 162 163 List<Query> queries = new ArrayList<>(); 164 for (String val : aupostingTermIds) 165 { 166 queries.add(new StringQuery(fieldPath, operator, val, language)); 167 } 168 169 return new OrQuery(queries); 170 } 171 172 /** 173 * Get the id of child terms recursively 174 * @param parentId The id of parent term 175 * @return The ids 176 */ 177 protected List<String> getChildTermIds(String parentId) 178 { 179 List<String> chilIds = new ArrayList<>(); 180 181 AmetysObjectIterable<Content> chidren = _thesaurusDAO.getChildTerms(parentId); 182 for (Content child : chidren) 183 { 184 chilIds.add(child.getId()); 185 chilIds.addAll(getChildTermIds(child.getId())); 186 } 187 188 return chilIds; 189 } 190}