org.xwiki.platform.search.solr.internal.SolrSearchService.java Source code

Java tutorial

Introduction

Here is the source code for org.xwiki.platform.search.solr.internal.SolrSearchService.java

Source

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.platform.search.solr.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Singleton;

import org.apache.commons.lang.StringUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.core.CoreContainer;
import org.slf4j.Logger;
import org.xwiki.component.annotation.Component;
import org.xwiki.context.Execution;
import org.xwiki.context.ExecutionContext;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.observation.EventListener;
import org.xwiki.observation.event.ApplicationStartedEvent;
import org.xwiki.observation.event.Event;
import org.xwiki.platform.search.SearchService;

import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.doc.XWikiDocument;

/**
 * SOLR Search service component.
 * 
 * @version $Id$
 */
@Component
@Singleton
public class SolrSearchService implements SearchService, EventListener {
    /**
     * Logger.
     */
    @Inject
    private Logger logger;

    /**
     * Execution.
     */
    @Inject
    private Execution execution;

    /**
     * Solr Server.
     */
    private static EmbeddedSolrServer solrServer;

    /**
     * {@inheritDoc}
     * 
     * @see org.xwiki.observation.EventListener#getEvents()
     */
    @Override
    public List<Event> getEvents() {
        return Collections.singletonList((Event) new ApplicationStartedEvent());
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.xwiki.observation.EventListener#getName()
     */
    @Override
    public String getName() {
        return "SOLR search service";
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.xwiki.observation.EventListener#onEvent(org.xwiki.observation.event.Event, java.lang.Object,
     *      java.lang.Object)
     */
    @Override
    public void onEvent(Event event, Object arg1, Object arg2) {
        try {
            System.setProperty("solr.solr.home", "~/code/binaries/apache-solr-3.5.0/example/solr");
            /* Initialize the SOLR backend using an embedded server */
            CoreContainer.Initializer initializer = new CoreContainer.Initializer();
            CoreContainer container = initializer.initialize();
            solrServer = new EmbeddedSolrServer(container, "");

            // Delete the existing index.
            solrServer.deleteByQuery("*:*");

            logger.info("SOLR initialized");
        } catch (Exception e) {
            logger.error("Unable to initialize SOLR");
        }
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.xwiki.platform.search.SearchService#getBackend()
     */
    @Override
    public String getBackend() {
        return "SOLR";
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.xwiki.platform.search.SearchService#indexDocuments()
     */
    @Override
    public void indexDocuments() {
        try {
            ExecutionContext context = execution.getContext();
            String hql = "select distinct doc.space, doc.name, doc.version, doc.language from XWikiDocument as doc ";

            XWikiContext xcontext = (XWikiContext) context.getProperty("xwikicontext");

            List<Object[]> documents = xcontext.getWiki().search(hql, xcontext);
            String wikiName = xcontext.getMainXWiki();

            for (Object[] document : documents) {

                String spaceName = (String) document[0];
                if (!spaceName.equalsIgnoreCase("Sandbox")) {
                    continue;
                }

                DocumentReference documentReference = new DocumentReference(wikiName, spaceName,
                        (String) document[1]);
                String version = (String) document[2];
                String language = (String) document[3];

                XWikiDocument xdoc = xcontext.getWiki().getDocument(documentReference, xcontext);

                if (StringUtils.isEmpty(language)) {
                    language = xdoc.getDefaultLanguage();
                }

                ArrayList<String> str = new ArrayList<String>();
                str.add("es");
                str.add("en");
                str.add("fr");
                if (!str.contains(language)) {
                    continue;
                }
                this.addDocument(xcontext, xdoc, language);

            }

            UpdateResponse response = solrServer.commit();
            logger.info("All the files are indexed and committed - Response " + response.toString());

        } catch (Exception e) {
            logger.error("Error while indexing the wiki documents " + e.getMessage());
        }

    }

    /**
     * @param xcontext - XWiki Context.
     * @param xdoc - Reference to xwiki document.
     * @param language - the language of the document.
     * @return true if adding the document is successful.
     */
    private boolean addDocument(XWikiContext xcontext, XWikiDocument xdoc, String language) {

        try {
            XWikiDocument tdoc = xdoc.getTranslatedDocument(language, xcontext);
            DocumentReference docRef = xdoc.getDocumentReference();

            SolrInputDocument sdoc = new SolrInputDocument();
            String lang = "_" + language;
            sdoc.addField(IndexFields.DOCUMENT_NAME + lang, docRef.getName());
            sdoc.addField(IndexFields.DOCUMENT_TITLE + lang, tdoc.getTitle());
            sdoc.addField(IndexFields.DOCUMENT_SPACE + lang, tdoc.getSpaceName());
            sdoc.addField(IndexFields.FULLTEXT + lang, tdoc.getContent());
            sdoc.addField("language", language);
            sdoc.addField("id", tdoc.getId());

            UpdateResponse response = solrServer.add(sdoc);
            logger.info("Document being added [" + tdoc.getTitle() + "] Language [" + language
                    + "]  with Update response " + response.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

    /**
     * {@inheritDoc}
     * 
     * @see org.xwiki.platform.search.SearchService#reIndexDocuments()
     */
    @Override
    public void reIndexDocuments() {
        // no op
        logger.warn("Dummy - no operation");

    }

    /**
     * {@inheritDoc}
     * 
     * @see org.xwiki.platform.search.SearchService#queryDocument(java.lang.String)
     */
    @Override
    public ArrayList<String> queryDocument(String query, String qfvalues) {
        SolrQuery squery = new SolrQuery();
        squery.setQuery(query).setFacet(true).addFacetField("title_en", "title_fr", "title_es", "ft_en", "ft_fr",
                "ft_es");

        // Edismax
        squery.setParam("defType", "edismax");
        squery.setParam("qt", "edismax");

        // qf values passed on from front end.
        squery.setParam("qf", qfvalues);
        squery.setParam("debugQuery", "on");

        // Highlighting
        squery.setHighlight(true);
        squery.setParam("hl.simple.pre", "**");
        squery.setParam("hl.simple.post", "**");

        logger.info("Querying document - " + query);

        QueryResponse response;
        Map<String, Map<String, List<String>>> highlightingMap = null;
        try {

            response = solrServer.query(squery);
            logger.info("Facet fields " + response.getFacetFields());

            ArrayList<String> docNames = new ArrayList<String>();
            highlightingMap = response.getHighlighting();
            logger.info("Highlighting :: " + highlightingMap);

            for (SolrDocument d : response.getResults()) {
                String language = "_" + (String) d.getFieldValue("language");
                logger.info("The language for the document is - " + language);

                String space = (String) d.getFieldValue(IndexFields.DOCUMENT_SPACE + language);
                String pageName = (String) d.getFieldValue(IndexFields.DOCUMENT_NAME + language);
                String title = (String) d.getFieldValue(IndexFields.DOCUMENT_TITLE + language);
                Float score = (Float) d.getFieldValue("score");
                String id = (String) d.getFieldValue("id");

                if (highlightingMap != null) {
                    Map<String, List<String>> docMap = highlightingMap.get(id);
                    if (docMap != null && docMap.containsKey(IndexFields.DOCUMENT_TITLE + language)) {
                        title = docMap.get(IndexFields.DOCUMENT_TITLE + language).toString();
                    }
                }

                // return a string with link to the page, score and page title ( varies from language to langauge for
                // same page).
                String retStr = "[[" + space + "." + pageName + "]] with a score (" + score + ") \\\\" + title;

                logger.info("Fields :: " + retStr);
                docNames.add(retStr);
            }
            return docNames;
        } catch (SolrServerException e) {
            e.printStackTrace();
        }

        return (ArrayList<String>) Collections.EMPTY_LIST;

    }

}