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}