org.openmrs.module.solr.web.DWRChartSearchService.java Source code

Java tutorial

Introduction

Here is the source code for org.openmrs.module.solr.web.DWRChartSearchService.java

Source

/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.module.solr.web;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Vector;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.openmrs.api.APIException;
import org.openmrs.api.context.Context;
import org.openmrs.module.solr.SolrEngine;
import org.openmrs.util.OpenmrsUtil;
import org.openmrs.web.dwr.ConceptListItem;

public class DWRChartSearchService {

    protected static final Log log = LogFactory.getLog(DWRChartSearchService.class);

    /**
     * Returns a map of results with the values as count of matches and a partial list of the
     * matching concepts (depending on values of start and length parameters) while the keys are are
     * 'count' and 'objectList' respectively, if the length parameter is not specified, then all
     * matches will be returned from the start index if specified.
     * 
     * @param phrase concept name or conceptId
     * @param includeRetired boolean if false, will exclude retired concepts
     * @param includeClassNames List of ConceptClasses to restrict to
     * @param excludeClassNames List of ConceptClasses to leave out of results
     * @param includeDatatypeNames List of ConceptDatatypes to restrict to
     * @param excludeDatatypeNames List of ConceptDatatypes to leave out of results
     * @param start the beginning index
     * @param length the number of matching concepts to return
     * @param getMatchCount Specifies if the count of matches should be included in the returned map
     * @return a map of results
     * @throws APIException
     * @since 1.8
     */
    public Map<String, Object> findCountAndConcepts(Integer patientId, String phrase, boolean includeRetired,
            List<String> includeClassNames, List<String> excludeClassNames, List<String> includeDatatypeNames,
            List<String> excludeDatatypeNames, Integer start, Integer length, boolean getMatchCount)
            throws APIException {
        //Map to return
        Map<String, Object> resultsMap = new HashMap<String, Object>();
        Vector<Object> objectList = new Vector<Object>();

        try {
            if (!StringUtils.isBlank(phrase)) {

                long matchCount = 0;
                if (getMatchCount) {
                    //get the count of matches
                    matchCount += getDocumentListCount(patientId, phrase);
                }

                //if we have any matches or this isn't the first ajax call when the caller
                //requests for the count
                if (matchCount > 0 || !getMatchCount) {
                    objectList.addAll(findBatchOfConcepts(patientId, phrase, includeRetired, includeClassNames,
                            excludeClassNames, includeDatatypeNames, excludeDatatypeNames, start, length));
                }

                resultsMap.put("count", matchCount);
                resultsMap.put("objectList", objectList);
            } else {
                resultsMap.put("count", 0);
                objectList.add(Context.getMessageSourceService().getMessage("searchWidget.noMatchesFound"));
            }

        } catch (Exception e) {
            log.error("Error while searching for concepts", e);
            objectList.clear();
            objectList.add(
                    Context.getMessageSourceService().getMessage("Concept.search.error") + " - " + e.getMessage());
            resultsMap.put("count", 0);
            resultsMap.put("objectList", objectList);
        }

        return resultsMap;
    }

    /**
     * Gets a list of conceptListItems matching the given arguments
     * 
     * @param phrase the concept name string to match against
     * @param includeRetired boolean if false, will exclude retired concepts
     * @param includeClassNames List of ConceptClasses to restrict to
     * @param excludeClassNames List of ConceptClasses to leave out of results
     * @param includeDatatypeNames List of ConceptDatatypes to restrict to
     * @param excludeDatatypeNames List of ConceptDatatypes to leave out of results
     * @param start the beginning index
     * @param length the number of matching concepts to return
     * @return a list of conceptListItems matching the given arguments
     * @should return concept by given id if exclude and include lists are empty
     * @should return concept by given id if classname is included
     * @should not return concept by given id if classname is not included
     * @should not return concept by given id if classname is excluded
     * @should return concept by given id if datatype is included
     * @should not return concept by given id if datatype is not included
     * @should not return concept by given id if datatype is excluded
     * @should include
     * @since 1.8
     */
    public List<Object> findBatchOfConcepts(Integer patientId, String phrase, boolean includeRetired,
            List<String> includeClassNames, List<String> excludeClassNames, List<String> includeDatatypeNames,
            List<String> excludeDatatypeNames, Integer start, Integer length) {
        //TODO factor out the reusable code in this and findCountAndConcepts methods to a single utility method
        // List to return
        // Object type gives ability to return error strings
        Vector<Object> objectList = new Vector<Object>();

        // TODO add localization for messages

        Locale defaultLocale = Context.getLocale();

        // get the list of locales to search on
        List<Locale> searchLocales = Context.getAdministrationService().getAllowedLocales(); //getSearchLocales();

        try {
            //List<ConceptSearchResult> searchResults = new Vector<ConceptSearchResult>();
            List<Object> searchResults = new Vector<Object>();

            if (!StringUtils.isBlank(phrase)) {
                // perform the search
                //searchResults.addAll(getDocumentList(patientId, phrase));
                SolrDocumentList documents = getDocumentList(patientId, phrase, start, length);
                for (SolrDocument document : documents) {
                    Integer obsId = (Integer) document.get("obs_id");
                    Integer person_id = (Integer) document.get("person_id");
                    String conceptName = (String) document.get("concept_name");
                    Date date = (Date) document.get("obs_datetime");
                    String text = (String) document.get("value_text");
                    String conceptDescription = (String) document.get("concept_description");
                    //load this obs from the database using its id

                    if (StringUtils.isBlank(conceptName))
                        conceptName = (String) document.get("value_coded_concept_name");

                    if (StringUtils.isBlank(conceptDescription))
                        conceptDescription = (String) document.get("value_coded_concept_description");

                    ConceptListItem conceptListItem = new ConceptListItem();
                    conceptListItem.setConceptId(obsId);
                    conceptListItem.setName(conceptName + " - " + Context.getDateFormat().format(date));
                    conceptListItem.setDescription(conceptDescription);
                    objectList.add(conceptListItem);
                }
            }

            if (objectList.size() < 1) {
                objectList.add(Context.getMessageSourceService().getMessage("general.noMatchesFoundInLocale",
                        new Object[] { "<b>" + phrase + "</b>", OpenmrsUtil.join(searchLocales, ", ") },
                        Context.getLocale()));
            } else {
                // turn searchResults into concept list items
                // if user wants drug concepts included, append those
                //for (ConceptSearchResult searchResult : searchResults)
                //   objectList.add(new ConceptListItem(searchResult));
            }
        } catch (Exception e) {
            log.error("Error while finding concepts + " + e.getMessage(), e);
            objectList.add(
                    Context.getMessageSourceService().getMessage("Concept.search.error") + " - " + e.getMessage());
        }

        if (objectList.size() == 0)
            objectList.add(Context.getMessageSourceService().getMessage("general.noMatchesFoundInLocale",
                    new Object[] { "<b>" + phrase + "</b>", defaultLocale }, Context.getLocale()));

        return objectList;
    }

    private SolrDocumentList getDocumentList(Integer patientId, String searchText, Integer start, Integer length)
            throws Exception {
        SolrQuery query = new SolrQuery("*" + searchText + "* AND person_id:" + patientId);
        query.setStart(start);
        query.setRows(length);
        QueryResponse response = SolrEngine.getInstance().getServer().query(query);
        return response.getResults();
    }

    private Long getDocumentListCount(Integer patientId, String searchText) throws Exception {
        SolrServer solrServer = SolrEngine.getInstance().getServer();
        solrServer.commit(); //Just incase there is imported data which is not yet commited.

        SolrQuery query = new SolrQuery("*" + searchText + "* AND person_id:" + patientId);
        query.setRows(0); //Intentionally setting to this value such that we get the count very quickly.
        QueryResponse response = solrServer.query(query);
        return response.getResults().getNumFound();
    }
}