001/* 002 * Copyright 2010 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; 017 018import java.io.IOException; 019import java.util.List; 020import java.util.stream.Collectors; 021 022import org.apache.avalon.framework.service.ServiceException; 023import org.apache.avalon.framework.service.ServiceManager; 024import org.apache.cocoon.ProcessingException; 025import org.apache.cocoon.environment.ObjectModelHelper; 026import org.apache.cocoon.environment.Request; 027import org.apache.cocoon.generation.ServiceableGenerator; 028import org.apache.cocoon.xml.XMLUtils; 029import org.apache.commons.lang.StringUtils; 030import org.apache.solr.client.solrj.SolrClient; 031import org.apache.solr.client.solrj.SolrQuery; 032import org.apache.solr.client.solrj.SolrServerException; 033import org.apache.solr.client.solrj.response.QueryResponse; 034import org.apache.solr.client.solrj.response.TermsResponse; 035import org.apache.solr.client.solrj.response.TermsResponse.Term; 036import org.apache.solr.common.params.TermsParams; 037import org.xml.sax.SAXException; 038 039import org.ametys.cms.content.indexing.solr.SolrFieldNames; 040import org.ametys.cms.search.solr.SolrClientProvider; 041import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 042import org.ametys.web.WebConstants; 043 044/** 045 * Generates the proposed fields for auto-completion while beginning a search 046 * 047 */ 048public class AutoCompletionGenerator extends ServiceableGenerator 049{ 050 051 private SolrClientProvider _solrClientProvider; 052 053 @Override 054 public void service(ServiceManager serviceManager) throws ServiceException 055 { 056 super.service(serviceManager); 057 _solrClientProvider = (SolrClientProvider) serviceManager.lookup(SolrClientProvider.ROLE); 058 } 059 060 @Override 061 public void generate() throws IOException, SAXException, ProcessingException 062 { 063 Request request = ObjectModelHelper.getRequest(objectModel); 064 065 String siteName = parameters.getParameter("siteName", ""); 066 if (StringUtils.isEmpty(siteName)) 067 { 068 throw new IllegalArgumentException("A site must be specified for auto completion"); 069 } 070 071 String lang = parameters.getParameter("lang", ""); 072 if (StringUtils.isEmpty(lang)) 073 { 074 throw new IllegalArgumentException("A language must be specified for auto completion"); 075 } 076 077 // Retrieve current workspace 078 String currentWsp = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 079 080 try 081 { 082 // TODO Do not force the workspace, to be transmitted. 083 // Use live workspace 084 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, WebConstants.LIVE_WORKSPACE); 085 086 String prefix = request.getParameter("q"); 087 String fieldName = SolrFieldNames.FULL_PREFIX + lang; 088 089 SolrClient solrClient = _solrClientProvider.getReadClient(); 090 091 SolrQuery query = new SolrQuery(); 092 query.setRequestHandler("/terms"); 093 query.setParam(TermsParams.TERMS_FIELD, fieldName); 094 query.setParam(TermsParams.TERMS_PREFIX_STR, prefix); 095 096 String collectionName = _solrClientProvider.getCollectionName(); 097 QueryResponse response = solrClient.query(collectionName, query); 098 099 TermsResponse termsResponse = response.getTermsResponse(); 100 101 contentHandler.startDocument(); 102 103 XMLUtils.startElement(contentHandler, "auto-completion"); 104 105 if (termsResponse != null) 106 { 107 // Extract the terms (words) and sort them alphabetically. 108 // Too bad forEach(Consumer) doesn't throw Exceptions... 109 List<String> words = termsResponse.getTerms(fieldName).stream().map(Term::getTerm).sorted().collect(Collectors.toList()); 110 for (String word : words) 111 { 112 XMLUtils.createElement(contentHandler, "item", word); 113 } 114 } 115 116 XMLUtils.endElement(contentHandler, "auto-completion"); 117 118 contentHandler.endDocument(); 119 } 120 catch (SolrServerException e) 121 { 122 getLogger().error("Error getting auto-complete list.", e); 123 throw new ProcessingException("Error getting auto-complete list.", e); 124 } 125 finally 126 { 127 // Restore context 128 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWsp); 129 } 130 } 131 132}