001/* 002 * Copyright 2016 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.solr; 017 018import java.util.Arrays; 019import java.util.Collections; 020import java.util.HashSet; 021import java.util.List; 022import java.util.Map; 023import java.util.Set; 024 025import org.apache.avalon.framework.container.ContainerUtil; 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.cocoon.environment.Request; 029import org.apache.commons.lang3.StringUtils; 030 031import org.ametys.cms.contenttype.ContentTypesHelper; 032import org.ametys.cms.repository.Content; 033import org.ametys.cms.search.SearchResults; 034import org.ametys.cms.search.Sort; 035import org.ametys.cms.search.cocoon.SearchAction; 036import org.ametys.cms.search.query.ContentTypeQuery; 037import org.ametys.cms.search.query.Query; 038import org.ametys.cms.search.query.WorkflowStepQuery; 039import org.ametys.cms.search.ui.model.SearchUIModel; 040import org.ametys.core.util.AvalonLoggerAdapter; 041 042import com.google.common.primitives.Ints; 043 044/** 045 * Execute a solr query with custom columns and facets. 046 */ 047public class SolrQuerySearchAction extends SearchAction 048{ 049 /** The content types helper. */ 050 protected ContentTypesHelper _contentTypesHelper; 051 052 /** The searcher */ 053// protected Searcher _searcher; 054 055// protected ContentSearcherFactory _contentSearcher; 056 057 @Override 058 public void service(ServiceManager serviceManager) throws ServiceException 059 { 060 super.service(serviceManager); 061 _contentTypesHelper = (ContentTypesHelper) serviceManager.lookup(ContentTypesHelper.ROLE); 062// _searcher = (Searcher) serviceManager.lookup(Searcher.ROLE); 063// _contentSearcher = (ContentSearcherFactory) serviceManager.lookup(ContentSearcherFactory.ROLE); 064 } 065 066 @SuppressWarnings("unchecked") 067 @Override 068 protected void doSearch(Request request, SearchUIModel model, int offset, int maxResults, Map<String, Object> jsParameters, Map<String, Object> contextualParameters) throws Exception 069 { 070 Map<String, Object> values = (Map<String, Object>) jsParameters.get("values"); 071 072 String solrQuery = (String) values.get("query"); 073 074 String columnsStr = StringUtils.defaultString((String) values.get("columns")); 075 List<String> columns = Arrays.asList(StringUtils.split(columnsStr, ", ")); 076 077 Object facetObj = values.get("facets"); 078 List<String> facets = Collections.emptyList(); 079 if (facetObj != null && facetObj instanceof List<?>) 080 { 081 facets = (List<String>) facetObj; 082 } 083 084 Map<String, List<String>> facetValues = (Map<String, List<String>>) jsParameters.get("facetValues"); 085 if (facetValues == null) 086 { 087 facetValues = Collections.emptyMap(); 088 } 089 String sortInfo = (String) jsParameters.get("sort"); 090 List<Sort> sort = getSort(sortInfo); 091 092 Set<String> contentTypes = Collections.emptySet(); 093 094 Object cTypesObj = values.get("contentTypes"); 095 String baseContentType = null; 096 if (cTypesObj != null && cTypesObj instanceof List<?>) 097 { 098 contentTypes = new HashSet<>((List<String>) cTypesObj); 099 baseContentType = _contentTypesHelper.getCommonAncestor(contentTypes); 100 101 ContentTypeQuery cTypeQuery = new ContentTypeQuery(contentTypes); 102 String cTypeQueryString = cTypeQuery.build(); 103 104 solrQuery = cTypeQueryString + " AND (" + solrQuery + ")"; 105 } 106 107 Object wfStepsObj = values.get("workflowSteps"); 108 if (wfStepsObj != null && wfStepsObj instanceof List<?>) 109 { 110 Set<Integer> wfSteps = new HashSet<>(); 111 for (String wfStepObj : (List<String>) wfStepsObj) 112 { 113 if (StringUtils.isNotEmpty(wfStepObj)) 114 { 115 wfSteps.add(Integer.parseInt(wfStepObj)); 116 } 117 } 118 119 if (!wfSteps.isEmpty()) 120 { 121 WorkflowStepQuery wfStepQuery = new WorkflowStepQuery(Ints.toArray(wfSteps)); 122 String wfStepsQueryString = wfStepQuery.build(); 123 124 solrQuery = wfStepsQueryString + " AND (" + solrQuery + ")"; 125 } 126 } 127 128 CriteriaSearchUIModelWrapper modelWrapper = new CriteriaSearchUIModelWrapper(model, manager, _context, new AvalonLoggerAdapter(getLogger())); 129 ContainerUtil.service(modelWrapper, manager); 130 131 modelWrapper.setFacetedCriteria(baseContentType, facets, contextualParameters); 132 modelWrapper.setResultColumns(baseContentType, columns, contextualParameters); 133 134 final String finalSolrQuery = solrQuery; 135 Query query = () -> finalSolrQuery; 136 137 SearchResults<Content> results = _searcherFactory.create(contentTypes) 138 .withSort(sort) 139 .withFacets(facets) 140 .withLimits(offset, maxResults) 141 .searchWithFacets(query, facetValues); 142// AmetysObjectIterable<Content> contents = _searcher.search(solrQuery, sort, begin, maxResults); 143// SearchResults results = new LocalSearchResults(contents); 144 145 request.setAttribute(SEARCH_RESULTS, results); 146 request.setAttribute(SEARCH_MODEL, modelWrapper); 147 } 148}