001/*
002 *  Copyright 2024 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.solr;
017
018import java.util.ArrayList;
019import java.util.List;
020import java.util.Map;
021import java.util.Set;
022
023import org.apache.avalon.framework.activity.Initializable;
024import org.apache.avalon.framework.component.Component;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.avalon.framework.service.Serviceable;
028import org.apache.commons.lang3.exception.ExceptionUtils;
029import org.apache.solr.client.solrj.SolrClient;
030import org.apache.solr.client.solrj.impl.BaseHttpSolrClient.RemoteSolrException;
031import org.apache.solr.client.solrj.request.json.DirectJsonQueryRequest;
032import org.apache.solr.client.solrj.response.QueryResponse;
033
034import org.ametys.cms.content.indexing.solr.SolrIndexer;
035import org.ametys.cms.search.solr.SearcherFactory;
036import org.ametys.cms.search.solr.SolrClientProvider;
037import org.ametys.core.ui.Callable;
038import org.ametys.runtime.plugin.component.AbstractLogEnabled;
039
040/**
041 * Handler to execute Solr JSON queries
042 */
043public class SolrQueryHandler extends AbstractLogEnabled  implements Component, Serviceable, Initializable
044{
045    /** Avalon role. */
046    public static final String ROLE = SolrQueryHandler.class.getName();
047    
048    /** The searcher factory. */
049    protected SearcherFactory _searcherFactory;
050    /** The solr client */
051    protected SolrClient _solrClient;
052    /** The Solr indexer */
053    protected SolrIndexer _solrIndexer;
054    /** The solr client provider */
055    protected SolrClientProvider _solrClientProvider;
056    
057    public void service(ServiceManager manager) throws ServiceException
058    {
059        _searcherFactory = (SearcherFactory) manager.lookup(SearcherFactory.ROLE);
060        _solrClientProvider = (SolrClientProvider) manager.lookup(SolrClientProvider.ROLE);
061        _solrIndexer = (SolrIndexer) manager.lookup(SolrIndexer.ROLE);
062    }
063    
064    public void initialize() throws Exception
065    {
066        _solrClient = _solrClientProvider.getReadClient();
067    }
068    
069    /**
070     * Execute a solr query.
071     * @param query The query as a String representing a JSON.
072     * @param coreName The solr core name
073     * @return The result as a JSON String
074     * @throws Exception If an error occurs
075     */
076    @Callable(rights = "CMS_Rights_Solr_Query", context = "/admin")
077    public Map<String, Object> executeSolrQuery(String query, String coreName) throws Exception
078    {
079        DirectJsonQueryRequest queryRequest = new DirectJsonQueryRequest(query);
080        
081        try
082        {
083            QueryResponse response = queryRequest.process(_solrClient, _solrClientProvider.getCollectionName(coreName));
084            return Map.of("result", response.jsonStr());
085        }
086        catch (RemoteSolrException e)
087        {
088            return Map.of("errorMessage", e.getMessage(),
089                          "errorStackTrace", ExceptionUtils.getStackTrace(e));
090        }
091    }
092    
093    /**
094     * Get the solr core names
095     * @return The solr core names
096     * @throws Exception If an error occurs
097     */
098    @Callable(rights = "CMS_Rights_Solr_Query", context = "/admin")
099    public List<Map<String, String>> getSolrCoreNames() throws Exception
100    {
101        List<Map<String, String>> results = new ArrayList<>();
102        Set<String> coreNames = _solrIndexer.getCoreNames();
103        for (String coreName : coreNames)
104        {
105            results.add(Map.of("name", coreName));
106        }
107        return results;
108    }
109}