fr.paris.lutece.plugins.helpdesk.modules.solr.search.SolrHelpdeskIndexer.java Source code

Java tutorial

Introduction

Here is the source code for fr.paris.lutece.plugins.helpdesk.modules.solr.search.SolrHelpdeskIndexer.java

Source

/*
 * Copyright (c) 2002-2014, Mairie de Paris
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice
 *     and the following disclaimer.
 *
 *  2. Redistributions in binary form must reproduce the above copyright notice
 *     and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *
 *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
 *     contributors may be used to endorse or promote products derived from
 *     this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * License 1.0
 */
package fr.paris.lutece.plugins.helpdesk.modules.solr.search;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.lucene.demo.html.HTMLParser;

import fr.paris.lutece.plugins.helpdesk.business.Faq;
import fr.paris.lutece.plugins.helpdesk.business.FaqHome;
import fr.paris.lutece.plugins.helpdesk.business.QuestionAnswer;
import fr.paris.lutece.plugins.helpdesk.business.Subject;
import fr.paris.lutece.plugins.helpdesk.business.SubjectHome;
import fr.paris.lutece.plugins.helpdesk.service.HelpdeskPlugin;
import fr.paris.lutece.plugins.helpdesk.service.helpdesksearch.HelpdeskSearchItem;
import fr.paris.lutece.plugins.helpdesk.utils.HelpdeskIndexerUtils;
import fr.paris.lutece.plugins.helpdesk.web.HelpdeskApp;
import fr.paris.lutece.plugins.search.solr.business.field.Field;
import fr.paris.lutece.plugins.search.solr.indexer.SolrIndexer;
import fr.paris.lutece.plugins.search.solr.indexer.SolrIndexerService;
import fr.paris.lutece.plugins.search.solr.indexer.SolrItem;
import fr.paris.lutece.plugins.search.solr.util.SolrConstants;
import fr.paris.lutece.portal.service.content.XPageAppService;
import fr.paris.lutece.portal.service.plugin.Plugin;
import fr.paris.lutece.portal.service.plugin.PluginService;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import fr.paris.lutece.util.url.UrlItem;

/**
 * The Helpdesk indexer for Solr search platform
 *
 */
public class SolrHelpdeskIndexer implements SolrIndexer {
    private static final String PROPERTY_DESCRIPTION = "helpdesk-solr.indexer.description";
    private static final String PROPERTY_NAME = "helpdesk-solr.indexer.name";
    private static final String PROPERTY_VERSION = "helpdesk-solr.indexer.version";
    private static final String PROPERTY_INDEXER_ENABLE = "helpdesk-solr.indexer.enable";
    public static final String SHORT_NAME_SUBJECT = "hds";
    public static final String SHORT_NAME_QUESTION_ANSWER = "hdq";
    private static final String BLANK = " ";
    private static final String PROPERTY_PAGE_PATH_LABEL = "helpdesk.pagePathLabel";
    private static final String PROPERTY_FAQ_ID_LABEL = "helpdesk-solr.indexer.faq_id.label";
    private static final String PROPERTY_FAQ_ID_DESCRIPTION = "helpdesk-solr.indexer.faq_id.description";
    private static final String PROPERTY_SUBJECT_LABEL = "helpdesk-solr.indexer.subject.label";
    private static final String PROPERTY_SUBJECT_DESCRIPTION = "helpdesk-solr.indexer.subject.description";

    // Site name
    private static final List<String> LIST_RESSOURCES_NAME = new ArrayList<String>();
    private static final String SUBJECT_INDEXATION_ERROR = "An error occured during the indexation of the subject number ";

    public SolrHelpdeskIndexer() {
        super();
        LIST_RESSOURCES_NAME.add(HelpdeskIndexerUtils.CONSTANT_QUESTION_ANSWER_TYPE_RESOURCE);
        LIST_RESSOURCES_NAME.add(HelpdeskIndexerUtils.CONSTANT_SUBJECT_TYPE_RESOURCE);
    }

    /**
     * {@inheritDoc}
     */
    public String getDescription() {
        return AppPropertiesService.getProperty(PROPERTY_DESCRIPTION);
    }

    /**
     * {@inheritDoc}
     */
    public String getName() {
        return AppPropertiesService.getProperty(PROPERTY_NAME);
    }

    /**
     * {@inheritDoc}
     */
    public String getVersion() {
        return AppPropertiesService.getProperty(PROPERTY_VERSION);
    }

    /**
     * {@inheritDoc}
     */
    public List<String> indexDocuments() {
        Plugin plugin = PluginService.getPlugin(HelpdeskPlugin.PLUGIN_NAME);
        List<String> lstErrors = new ArrayList<String>();

        //FAQ
        for (Faq faq : FaqHome.findAll(plugin)) {
            for (Subject subject : (Collection<Subject>) SubjectHome.getInstance().findByIdFaq(faq.getId(),
                    plugin)) {
                try {
                    indexSubject(faq, subject);
                } catch (IOException e) {
                    lstErrors.add(SolrIndexerService.buildErrorMessage(e));
                    AppLogService.error(SUBJECT_INDEXATION_ERROR + subject.getId(), e);
                }
            }
        }

        return lstErrors;
    }

    /**
     * Get the subject document
     * @param strDocument id of the subject to index
     * @return The list of Solr items
     */
    public List<SolrItem> getDocuments(String strDocument) {
        List<SolrItem> listDocs = new ArrayList<SolrItem>();
        String strPortalUrl = SolrIndexerService.getBaseUrl();
        Plugin plugin = PluginService.getPlugin(HelpdeskPlugin.PLUGIN_NAME);

        Subject subject = (Subject) SubjectHome.getInstance().findByPrimaryKey(Integer.parseInt(strDocument),
                plugin);

        if (subject != null) {
            UrlItem urlSubject = new UrlItem(strPortalUrl);
            urlSubject.addParameter(XPageAppService.PARAM_XPAGE_APP,
                    AppPropertiesService.getProperty(PROPERTY_PAGE_PATH_LABEL)); //FIXME

            //if it's a sub-subject, we need to get the first parent to have the faq
            int nIdParent = subject.getIdParent();
            Subject parentSubject = subject;

            while (nIdParent != SubjectHome.FIRST_ORDER) {
                parentSubject = (Subject) SubjectHome.getInstance().findByPrimaryKey(nIdParent, plugin);
                nIdParent = parentSubject.getIdParent();
            }

            Faq faq = FaqHome.findBySubjectId(parentSubject.getId(), plugin);

            if (faq != null) {
                urlSubject.addParameter(HelpdeskApp.PARAMETER_FAQ_ID, faq.getId());
                urlSubject.setAnchor(HelpdeskApp.ANCHOR_SUBJECT + subject.getId());

                SolrItem docSubject;

                try {
                    docSubject = getDocument(subject, faq.getRoleKey(), urlSubject.getUrl(), plugin);

                    listDocs.add(docSubject);

                    for (QuestionAnswer questionAnswer : (List<QuestionAnswer>) subject.getQuestions()) {
                        if (questionAnswer.isEnabled()) {
                            UrlItem urlQuestionAnswer = new UrlItem(strPortalUrl);
                            urlQuestionAnswer.addParameter(XPageAppService.PARAM_XPAGE_APP,
                                    AppPropertiesService.getProperty(PROPERTY_PAGE_PATH_LABEL)); //FIXME
                            urlQuestionAnswer.addParameter(HelpdeskApp.PARAMETER_FAQ_ID, faq.getId());
                            urlQuestionAnswer.setAnchor(
                                    HelpdeskApp.ANCHOR_QUESTION_ANSWER + questionAnswer.getIdQuestionAnswer());

                            SolrItem docQuestionAnswer = getDocument(faq.getId(), questionAnswer,
                                    urlQuestionAnswer.getUrl(), faq.getRoleKey(), plugin);
                            listDocs.add(docQuestionAnswer);
                        }
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }

        return listDocs;
    }

    /**
     * {@inheritDoc}
     */
    public boolean isEnable() {
        return "true".equalsIgnoreCase(AppPropertiesService.getProperty(PROPERTY_INDEXER_ENABLE));
    }

    /**
     * {@inheritDoc}
     */
    public List<Field> getAdditionalFields() {
        List<Field> fields = new ArrayList<Field>();
        Field fieldFaqId = new Field();
        fieldFaqId.setEnableFacet(false);
        fieldFaqId.setName(HelpdeskSearchItem.FIELD_FAQ_ID);
        fieldFaqId.setLabel(AppPropertiesService.getProperty(PROPERTY_FAQ_ID_LABEL));
        fieldFaqId.setDescription(AppPropertiesService.getProperty(PROPERTY_FAQ_ID_DESCRIPTION));
        fields.add(fieldFaqId);

        Field fieldSubjectId = new Field();
        fieldSubjectId.setEnableFacet(true);
        fieldSubjectId.setName(HelpdeskSearchItem.FIELD_SUBJECT);
        fieldSubjectId.setLabel(AppPropertiesService.getProperty(PROPERTY_SUBJECT_LABEL));
        fieldSubjectId.setDescription(AppPropertiesService.getProperty(PROPERTY_SUBJECT_DESCRIPTION));
        fields.add(fieldSubjectId);

        return fields;
    }

    /**
     * Recursive method for indexing a subject and his children
     *
     * @param faq the faq linked to the subject
     * @param subject the subject
     * @throws IOException I/O Exception
     * @throws InterruptedException interruptedException
     */
    private void indexSubject(Faq faq, Subject subject) throws IOException {
        Plugin plugin = PluginService.getPlugin(HelpdeskPlugin.PLUGIN_NAME);

        String strWebappName = SolrIndexerService.getBaseUrl();
        UrlItem urlSubject = new UrlItem(strWebappName);
        urlSubject.addParameter(XPageAppService.PARAM_XPAGE_APP,
                AppPropertiesService.getProperty(PROPERTY_PAGE_PATH_LABEL)); //FIXME
        urlSubject.addParameter(HelpdeskApp.PARAMETER_FAQ_ID, faq.getId());
        urlSubject.setAnchor(HelpdeskApp.ANCHOR_SUBJECT + subject.getId());

        // Indexing the subject
        SolrItem itemSubject = getDocument(subject, faq.getRoleKey(), urlSubject.getUrl(), plugin);
        SolrIndexerService.write(itemSubject);

        for (QuestionAnswer questionAnswer : (List<QuestionAnswer>) subject.getQuestions()) {
            if (questionAnswer.isEnabled()) {
                UrlItem urlQuestionAnswer = new UrlItem(strWebappName);
                urlQuestionAnswer.addParameter(XPageAppService.PARAM_XPAGE_APP,
                        AppPropertiesService.getProperty(PROPERTY_PAGE_PATH_LABEL)); //FIXME
                urlQuestionAnswer.addParameter(HelpdeskApp.PARAMETER_FAQ_ID, faq.getId());
                urlQuestionAnswer
                        .setAnchor(HelpdeskApp.ANCHOR_QUESTION_ANSWER + questionAnswer.getIdQuestionAnswer());

                // Indexing the questionAnswer
                SolrItem itemQuestionAnswer = getDocument(faq.getId(), questionAnswer, urlQuestionAnswer.getUrl(),
                        faq.getRoleKey(), plugin);
                SolrIndexerService.write(itemQuestionAnswer);
            }
        }

        Collection<Subject> children = subject.getChilds(plugin);

        for (Subject childSubject : children) {
            indexSubject(faq, childSubject);
        }
    }

    /**
     * Builds a {@link SolrItem} which will be used by Solr during the indexing of the question/answer list
     *
     * @param nIdFaq The {@link Faq} Id
     * @param questionAnswer the {@link QuestionAnswer} to index
     * @param strUrl the url of the subject
     * @param strRoleKey The role key
     * @param plugin The {@link Plugin}
     * @return A Solr {@link SolrItem} containing QuestionAnswer Data
     * @throws IOException The IO Exception
     */
    private SolrItem getDocument(int nIdFaq, QuestionAnswer questionAnswer, String strUrl, String strRoleKey,
            Plugin plugin) throws IOException {
        // make a new, empty document
        SolrItem item = new SolrItem();

        // Setting the Id faq field
        item.addDynamicField(HelpdeskSearchItem.FIELD_FAQ_ID, String.valueOf(nIdFaq));

        // Setting the Role field
        item.setRole(strRoleKey);

        // Setting the URL field
        item.setUrl(strUrl);

        // Setting the subject field
        item.addDynamicField(HelpdeskSearchItem.FIELD_SUBJECT, String.valueOf(questionAnswer.getIdSubject()));

        // Setting the Uid field
        String strIdQuestionAnswer = String.valueOf(questionAnswer.getIdQuestionAnswer());
        item.setUid(
                getResourceUid(strIdQuestionAnswer, HelpdeskIndexerUtils.CONSTANT_QUESTION_ANSWER_TYPE_RESOURCE));

        // Setting the Date field
        // Add the last modified date of the file a field named "modified".
        item.setDate(questionAnswer.getCreationDate());

        //Setting the Content field
        String strContentToIndex = getContentToIndex(questionAnswer, plugin);
        StringReader readerPage = new StringReader(strContentToIndex);
        HTMLParser parser = new HTMLParser(readerPage);

        Reader reader = parser.getReader();
        int c;
        StringBuffer sb = new StringBuffer();

        while ((c = reader.read()) != -1) {
            sb.append(String.valueOf((char) c));
        }

        reader.close();
        item.setContent(sb.toString());

        // Setting the Title field
        item.setTitle(questionAnswer.getQuestion());

        // Setting the Site field
        item.setSite(SolrIndexerService.getWebAppName());

        // Setting the Type field
        item.setType(HelpdeskPlugin.PLUGIN_NAME);

        // return the document
        return item;
    }

    /**
     * Builds a {@link SolrItem} element which will be used by Solr during the indexing of the subject list
     *
     * @param subject the {@link Subject} to index
     * @param strUrl the url of the subject
     * @param strRoleKey The role key
     * @param plugin The {@link Plugin}
     * @return The Solr {@link SolrItem} containing Subject data
     * @throws IOException The IO Exception
     */
    private SolrItem getDocument(Subject subject, String strRoleKey, String strUrl, Plugin plugin)
            throws IOException {
        // make a new, empty document
        SolrItem item = new SolrItem();

        // Setting the URL field
        item.setUrl(strUrl);

        // Setting the Uid field
        String strIdSubject = String.valueOf(subject.getId());
        item.setUid(getResourceUid(strIdSubject, HelpdeskIndexerUtils.CONSTANT_SUBJECT_TYPE_RESOURCE));

        //Setting the Content field
        String strContentToIndex = subject.getText();
        StringReader readerPage = new StringReader(strContentToIndex);
        HTMLParser parser = new HTMLParser(readerPage);

        Reader reader = parser.getReader();
        int c;
        StringBuffer sb = new StringBuffer();

        while ((c = reader.read()) != -1) {
            sb.append(String.valueOf((char) c));
        }

        reader.close();
        item.setContent(sb.toString());

        // Setting the Title field
        item.setTitle(subject.getText());

        // Setting the Site field
        item.setSite(SolrIndexerService.getWebAppName());

        // Setting the Type field
        item.setType(HelpdeskPlugin.PLUGIN_NAME);

        // Setting the Role field
        item.setRole(strRoleKey);

        // return the document
        return item;
    }

    /**
     * Set the Content to index (Question and Answer)
     * @param questionAnswer The {@link QuestionAnswer} to index
     * @param plugin The {@link Plugin}
     * @return The content to index
     */
    private static String getContentToIndex(QuestionAnswer questionAnswer, Plugin plugin) {
        StringBuffer sbContentToIndex = new StringBuffer();
        //Do not index question here
        sbContentToIndex.append(questionAnswer.getQuestion());
        sbContentToIndex.append(BLANK);
        sbContentToIndex.append(questionAnswer.getAnswer());

        return sbContentToIndex.toString();
    }

    /**
     * {@inheritDoc}
     */
    public List<String> getResourcesName() {
        return LIST_RESSOURCES_NAME;
    }

    /**
     * {@inheritDoc}
     */
    public String getResourceUid(String strResourceId, String strResourceType) {
        StringBuffer sb = new StringBuffer();

        if (HelpdeskIndexerUtils.CONSTANT_QUESTION_ANSWER_TYPE_RESOURCE.equals(strResourceType)) {
            sb.append(strResourceId).append(SolrConstants.CONSTANT_UNDERSCORE).append(SHORT_NAME_QUESTION_ANSWER);
        } else if (HelpdeskIndexerUtils.CONSTANT_SUBJECT_TYPE_RESOURCE.equals(strResourceType)) {
            sb.append(strResourceId).append(SolrConstants.CONSTANT_UNDERSCORE).append(SHORT_NAME_SUBJECT);
        }

        return StringUtils.isNotBlank(sb.toString()) ? sb.toString() : null;
    }
}