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.extraction.edition; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.LinkedHashSet; 021import java.util.List; 022import java.util.Map; 023import java.util.Optional; 024import java.util.Set; 025import java.util.function.Predicate; 026import java.util.stream.Collectors; 027 028import org.apache.avalon.framework.component.Component; 029import org.apache.avalon.framework.logger.AbstractLogEnabled; 030import org.apache.avalon.framework.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032import org.apache.avalon.framework.service.Serviceable; 033import org.apache.commons.lang3.StringUtils; 034 035import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 036import org.ametys.cms.search.GetQueryFromJSONHelper; 037import org.ametys.cms.search.QueryBuilder; 038import org.ametys.cms.search.model.SearchModel; 039import org.ametys.cms.search.query.AndQuery; 040import org.ametys.cms.search.query.ContentTypeOrMixinTypeQuery; 041import org.ametys.cms.search.query.ContentTypeQuery; 042import org.ametys.cms.search.query.MixinTypeQuery; 043import org.ametys.cms.search.query.Query.Operator; 044import org.ametys.cms.search.ui.model.SearchUIModelExtensionPoint; 045import org.ametys.core.ui.Callable; 046import org.ametys.core.util.I18nUtils; 047import org.ametys.core.util.JSONUtils; 048import org.ametys.plugins.extraction.ExtractionConstants; 049import org.ametys.plugins.queriesdirectory.Query; 050import org.ametys.plugins.repository.AmetysObjectIterable; 051import org.ametys.plugins.repository.AmetysObjectResolver; 052import org.ametys.plugins.thesaurus.Thesaurus; 053import org.ametys.plugins.thesaurus.ThesaurusDAO; 054import org.ametys.runtime.i18n.I18nizableText; 055 056/** 057 * Extraction node edition manager 058 */ 059public class EditExtractionNodeManager extends AbstractLogEnabled implements Component, Serviceable 060{ 061 /** The Avalon role name */ 062 public static final String ROLE = EditExtractionNodeManager.class.getName(); 063 064 private ThesaurusDAO _thesaurusDAO; 065 private AmetysObjectResolver _resolver; 066 private JSONUtils _jsonUtils; 067 private GetQueryFromJSONHelper _getQueryFromJSONHelper; 068 private QueryBuilder _queryBuilder; 069 private I18nUtils _i18nUtils; 070 private ContentTypeExtensionPoint _contentTypeExtensionPoint; 071 private SearchUIModelExtensionPoint _searchUIModelExtensionPoint; 072 073 public void service(ServiceManager serviceManager) throws ServiceException 074 { 075 _thesaurusDAO = (ThesaurusDAO) serviceManager.lookup(ThesaurusDAO.ROLE); 076 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 077 _jsonUtils = (JSONUtils) serviceManager.lookup(JSONUtils.ROLE); 078 _getQueryFromJSONHelper = (GetQueryFromJSONHelper) serviceManager.lookup(GetQueryFromJSONHelper.ROLE); 079 _queryBuilder = (QueryBuilder) serviceManager.lookup(QueryBuilder.ROLE); 080 _i18nUtils = (I18nUtils) serviceManager.lookup(I18nUtils.ROLE); 081 _contentTypeExtensionPoint = (ContentTypeExtensionPoint) serviceManager.lookup(ContentTypeExtensionPoint.ROLE); 082 _searchUIModelExtensionPoint = (SearchUIModelExtensionPoint) serviceManager.lookup(SearchUIModelExtensionPoint.ROLE); 083 } 084 085 /** 086 * Retrieves configuration for extraction node edition 087 * @return A map containing information about what is needed to create/edit an extraction node 088 */ 089 @Callable (rights = ExtractionConstants.MODIFY_EXTRACTION_RIGHT_ID) 090 public Map<String, Object> getNodeEditionConfiguration() 091 { 092 Map<String, Object> result = new HashMap<>(); 093 094 // Manages Search UI Models 095 Set<String> searchUIModelIds = _searchUIModelExtensionPoint.getExtensionsIds(); 096 List<Object> searchUIModelsConfigurations = new ArrayList<>(); 097 for (String searchUIModelId : searchUIModelIds) 098 { 099 Map<String, Object> searchUIModelMap = new HashMap<>(); 100 searchUIModelMap.put("value", searchUIModelId); 101 searchUIModelMap.put("label", searchUIModelId); 102 103 searchUIModelsConfigurations.add(searchUIModelMap); 104 } 105 result.put("searchUIModels", searchUIModelsConfigurations); 106 107 // Manages thesaurii 108 AmetysObjectIterable<Thesaurus> thesaurii = _thesaurusDAO.getThesaurii(); 109 List<Object> thesauriiConfigurations = new ArrayList<>(); 110 for (Thesaurus thesaurus : thesaurii) 111 { 112 Map<String, Object> thesaurusMap = new HashMap<>(); 113 thesaurusMap.put("value", thesaurus.getId()); 114 thesaurusMap.put("label", thesaurus.getLabel()); 115 116 thesauriiConfigurations.add(thesaurusMap); 117 } 118 result.put("thesaurii", thesauriiConfigurations); 119 120 return result; 121 } 122 123 /** 124 * Retrieves microthesaurii for the given thesaurus 125 * @param thesaurusId identifier of the thesaurus 126 * @return A map containing microthesaurii of the thesaurus 127 */ 128 @Callable (rights = ExtractionConstants.MODIFY_EXTRACTION_RIGHT_ID) 129 public Map<String, Object> getMicroThesaurii(String thesaurusId) 130 { 131 Map<String, Object> result = new HashMap<>(); 132 133 if (thesaurusId != null) 134 { 135 String thesaurusLabel = _thesaurusDAO.getThesaurusLabel(thesaurusId); 136 Thesaurus thesaurus = _thesaurusDAO.findThesaurusByLabel(thesaurusLabel); 137 138 if (thesaurus != null) 139 { 140 List<String> microthesaurii = _thesaurusDAO.getMicrothesaurii(thesaurus.getId()); 141 142 List<Map<String, Object>> microthesauriiConfigurations = new ArrayList<>(); 143 for (String microthesaurus : microthesaurii) 144 { 145 I18nizableText i18nLabel = _contentTypeExtensionPoint.getExtension(microthesaurus).getLabel(); 146 String label = _i18nUtils.translate(i18nLabel, null); // FIXME Use user preference language 147 148 Map<String, Object> thesaurusMap = new HashMap<>(); 149 thesaurusMap.put("value", microthesaurus); 150 thesaurusMap.put("text", label); 151 152 microthesauriiConfigurations.add(thesaurusMap); 153 } 154 155 result.put("microthesaurii", microthesauriiConfigurations); 156 } 157 } 158 return result; 159 } 160 161 /** 162 * Retrieves content types configured on the given saved query 163 * @param savedQueryId saved query identifier 164 * @return A list containing the content types 165 */ 166 @SuppressWarnings("unchecked") 167 @Callable (rights = ExtractionConstants.MODIFY_EXTRACTION_RIGHT_ID) 168 public List<String> getSavedQueryContentTypes(String savedQueryId) 169 { 170 List<String> result = new ArrayList<>(); 171 172 if (savedQueryId != null && !savedQueryId.isEmpty()) 173 { 174 Query referencedQuery = _resolver.resolveById(savedQueryId); 175 176 Map<String, Object> contentMap = _jsonUtils.convertJsonToMap(referencedQuery.getContent()); 177 Map<String, Object> exportParams = (Map<String, Object>) contentMap.get("exportParams"); 178 String modelId = (String) exportParams.get("model"); 179 180 if (modelId.contains("solr")) 181 { 182 Map<String, Object> values = (Map<String, Object>) exportParams.get("values"); 183 result.addAll((List<String>) values.get("contentTypes")); 184 } 185 else 186 { 187 SearchModel model = _getQueryFromJSONHelper.getSearchModel(exportParams); 188 Map<String, Object> contextualParameters = Optional.ofNullable((Map<String, Object>) exportParams.get("contextualParameters")).orElseGet(HashMap::new); 189 190 Map<String, Object> values = (Map<String, Object>) exportParams.get("values"); 191 String searchMode = StringUtils.defaultString((String) exportParams.get("searchMode"), "simple"); 192 193 org.ametys.cms.search.query.Query query = _queryBuilder.build(model, searchMode, true , values, contextualParameters); 194 if (query instanceof AndQuery) 195 { 196 Set<org.ametys.cms.search.query.Query> subqueries = new LinkedHashSet<>(((AndQuery) query).getQueries()); 197 Predicate<org.ametys.cms.search.query.Query> isCTypeOrMixinOrBothQuery = q -> ContentTypeQuery.class.isInstance(q) || MixinTypeQuery.class.isInstance(q) || ContentTypeOrMixinTypeQuery.class.isInstance(q); 198 List<org.ametys.cms.search.query.Query> matchingQueries = subqueries.stream().distinct().filter(isCTypeOrMixinOrBothQuery).collect(Collectors.toList()); 199 200 for (org.ametys.cms.search.query.Query matchingQuery : matchingQueries) 201 { 202 if (matchingQuery instanceof ContentTypeQuery) 203 { 204 ContentTypeQuery cTypeQuery = (ContentTypeQuery) matchingQuery; 205 if (cTypeQuery.getOperator() == Operator.EQ) 206 { 207 result.addAll(cTypeQuery.getValue()); 208 } 209 } 210 else if (matchingQuery instanceof MixinTypeQuery) 211 { 212 MixinTypeQuery mixinQuery = (MixinTypeQuery) matchingQuery; 213 if (mixinQuery.getOperator() == Operator.EQ) 214 { 215 result.addAll(mixinQuery.getValue()); 216 } 217 } 218 else if (matchingQuery instanceof ContentTypeOrMixinTypeQuery) 219 { 220 ContentTypeOrMixinTypeQuery cTypeOrMixinQuery = (ContentTypeOrMixinTypeQuery) matchingQuery; 221 if (cTypeOrMixinQuery.getOperator() == Operator.EQ) 222 { 223 result.addAll(cTypeOrMixinQuery.getIds()); 224 } 225 } 226 } 227 } 228 } 229 } 230 231 return result; 232 } 233}