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