xc.mst.action.browse.BrowseRecords.java Source code

Java tutorial

Introduction

Here is the source code for xc.mst.action.browse.BrowseRecords.java

Source

/**
 * Copyright (c) 2009 eXtensible Catalog Organization
 *
 * This program is free software; you can redistribute it and/or modify it under the terms of the MIT/X11 license. The text of the
 * license can be found at http://www.opensource.org/licenses/mit-license.php and copy of the license can be found on the project
 * website http://www.extensiblecatalog.org/.
 *
 */

package xc.mst.action.browse;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.struts2.interceptor.ServletResponseAware;

import xc.mst.bo.record.FacetFilter;
import xc.mst.bo.record.InputRecord;
import xc.mst.bo.record.OutputRecord;
import xc.mst.bo.record.Record;
import xc.mst.bo.record.SolrBrowseResult;
import xc.mst.bo.service.Service;
import xc.mst.constants.Constants;
import xc.mst.dao.DatabaseConfigException;
import xc.mst.manager.IndexException;
import xc.mst.manager.processingDirective.ServicesService;
import xc.mst.manager.record.BrowseRecordService;
import xc.mst.manager.record.RecordService;
import xc.mst.repo.RepositoryService;
import xc.mst.services.SolrIndexService;
import xc.mst.utils.MSTConfiguration;
import xc.mst.utils.XmlHelper;

/**
 * Browse records
 *
 * @author Sharmila Ranganathan
 *
 */
public class BrowseRecords extends Pager implements ServletResponseAware {

    /** Generated Id */
    private static final long serialVersionUID = -2599819216740526000L;

    /** A reference to the logger for this class */
    static Logger log = Logger.getLogger(Constants.LOGGER_GENERAL);
    static Logger LOG = Logger.getLogger(BrowseRecords.class);

    /** Browse result */
    private SolrBrowseResult result;

    /** Facet Name selected */
    private String addFacetName;

    /** Facet values selected */
    private String addFacetValue;

    /** Facet name to be removed */
    private String removeFacetName;

    /** Facet value to be removed */
    private String removeFacetValue;

    /** Facet names separated by | */
    private String selectedFacetNames = "";

    /** Facet values separated by | */
    private String selectedFacetValues = "";

    /** Search text entered by user */
    private String query = "";

    /** Id of record */
    private int recordId;

    /** Record XML */
    private String recordXML;

    /** Response */
    private HttpServletResponse servletResponse;

    /** The end row number to retrieve */
    private long rowEnd;

    /** Denotes whether to search XML or not */
    private boolean searchXML;

    /** Denotes whether its initial page load */
    private boolean isInitialLoad;

    /** Record for which successor are queried and displayed */
    private Record successorRecord;

    /** Record for which predecessor are queried and displayed */
    private Record predecessorRecord;

    /** Error to display its information */
    private String error;

    /** Error description */
    private String errorDescription;

    /** Record to be viewed */
    private Record record;

    /** Error type */
    private String errorType;

    private LinkedHashMap<String, String> identifiers;
    private ArrayList<String> idKeys;

    /** for individual query can pick one from identifiers list **/
    private String identifier;

    /**
     * Execute method to load initial screen with just the facets
     */
    public String execute() {
        searchXML = true;
        isInitialLoad = true;
        try {
            initializeIdentifiers();
        } catch (DatabaseConfigException e) {
            log.error(
                    "Search failed. Problem with connecting to database using the parameters in configuration file.",
                    e);
            errorType = "error";
            addFieldError("dbError",
                    "Search failed.Problem with connecting to database using the parameters in configuration file.");
            return INPUT;
        }
        browse();
        return SUCCESS;
    }

    protected void addFilterQuery(SolrQuery solrQuery, String name, String value) {
        RepositoryService repositoryService = (RepositoryService) MSTConfiguration.getInstance()
                .getBean("RepositoryService");
        if ("successor".equals(name) || "processed_from".equals(name)) {
            Record r = repositoryService.getRecord(Long.parseLong(value));
            List<Record> records = new ArrayList<Record>();
            if ("successor".equals(name)) {
                List<InputRecord> irs = ((Record) r).getPredecessors();
                if (irs != null) {
                    for (InputRecord ir : irs) {
                        records.add((Record) ir);
                    }
                }
            } else {
                List<OutputRecord> ors = ((Record) r).getSuccessors();
                if (ors != null) {
                    for (OutputRecord or : ors) {
                        records.add((Record) or);
                    }
                }
            }
            name = "record_id";
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < records.size(); i++) {
                Record r2 = records.get(i);
                sb.append("record_id:");
                sb.append(r2.getId() + "");
                if (i < records.size() - 1) {
                    sb.append(" OR ");
                }
            }
            solrQuery.addFilterQuery(sb.toString());
        } else {
            solrQuery.addFilterQuery(name + ":\"" + value.replaceAll(":", "\\\\:") + "\"");
        }
    }

    /**
     * Search for records
     */
    public String browse() {
        RecordService recordService = (RecordService) MSTConfiguration.getInstance().getBean("RecordService");
        if (log.isDebugEnabled()) {
            log.debug("User entered query::" + query);
        }
        try {
            SolrQuery solrQuery = new SolrQuery();

            // If Query is empty retrieve all records
            if ((query == null) || (query.equals(""))) {
                solrQuery.setQuery("*:*");
            } else {
                if (!StringUtils.isEmpty(identifier)) {
                    String qFld = getIdentifiers().get(identifier);
                    if (query.indexOf(" ") != -1) {
                        query = "(" + query + ")";
                    }
                    if (qFld != null) {
                        query = query.replaceAll(":", "\\\\:"); // replacing with \\: and solr ends up thinking the token before : is a field
                                                                //  warning:  replacing the 1st : (the delim between field and text) breaks
                                                                //             the search, no results returned.
                        String q = new String(qFld + ":" + query);
                        solrQuery.setQuery(q);
                        if (log.isDebugEnabled()) {
                            LOG.debug("*** browse() ident=" + qFld + " query=" + q);
                        }
                    } else {
                        if (log.isDebugEnabled()) {
                            LOG.debug("*** NO field associated with IDENTIFIER! " + " query=" + query
                                    + " identifier=" + identifier);
                        }
                        // solr schema: <copyField source="*_key"  dest="text" />
                        if (query.indexOf(" ") != -1) {
                            query = "(" + query + ")";
                        }
                        // TODO having trouble getting this working, leave as a TODO for now, and drop back to default search on record_id.
                        // (should never get here anyways, an identifier will always be picked.
                        //solrQuery.setQuery("text:"+ query);
                        solrQuery.setQuery(query.replaceAll(":", "\\\\:"));
                    }
                } else {
                    if (log.isDebugEnabled()) {
                        LOG.debug("*** NO IDENTIFIER FOUND! " + " query=" + query);
                    }
                    solrQuery.setQuery("*:*");
                }
            }

            StringTokenizer nameTokenizer = new StringTokenizer(selectedFacetNames, "|");
            StringTokenizer valueTokenizer = new StringTokenizer(selectedFacetValues, "|");

            while (nameTokenizer.hasMoreTokens()) {
                String name = nameTokenizer.nextToken();
                String value = valueTokenizer.nextToken();
                addFilterQuery(solrQuery, name, value);
            }

            // Add selected facet to query
            if (addFacetName != null && addFacetName.length() > 0) {
                addFilterQuery(solrQuery, addFacetName, addFacetValue);
                // Add facet names and values to | separated list
                selectedFacetNames = selectedFacetNames + "|" + addFacetName;
                selectedFacetValues = selectedFacetValues + "|" + addFacetValue;
            }

            // Remove selected facet from query
            if (removeFacetName != null && removeFacetName.length() > 0) {
                solrQuery.removeFilterQuery(
                        removeFacetName + ":\"" + removeFacetValue.replaceAll(":", "\\\\:") + "\"");
            }

            if (log.isDebugEnabled()) {
                log.debug("Query after adding/removing facet ::" + query);
                log.debug("After Adding facet names ::" + selectedFacetNames);
                log.debug("After Adding facet values ::" + selectedFacetValues);
            }
            // Create facet names and values List
            StringTokenizer facetNameTokenizer = new StringTokenizer(selectedFacetNames, "|");
            List<String> facetNamesList = new ArrayList<String>();

            StringTokenizer facetValueTokenizer = new StringTokenizer(selectedFacetValues, "|");
            List<String> facetValuesList = new ArrayList<String>();

            StringBuffer newSelectedFacetNames = new StringBuffer();
            StringBuffer newSelectedFacetValues = new StringBuffer();
            String myNameToken = "";
            String myValueToken = "";
            while (facetNameTokenizer.hasMoreTokens()) {
                myNameToken = facetNameTokenizer.nextToken();
                myValueToken = facetValueTokenizer.nextToken();
                if (removeFacetName != null && removeFacetName.length() > 0) {
                    // Create facet names String separated by |
                    if (!(removeFacetName.equalsIgnoreCase(myNameToken)
                            && removeFacetValue.equalsIgnoreCase(myValueToken))) {
                        newSelectedFacetNames.append("|");
                        newSelectedFacetNames.append(myNameToken);
                        facetNamesList.add(myNameToken);

                        newSelectedFacetValues.append("|");
                        newSelectedFacetValues.append(myValueToken);
                        facetValuesList.add(myValueToken);
                    }
                } else {
                    facetNamesList.add(myNameToken);
                    facetValuesList.add(myValueToken);
                }
            }

            if (removeFacetValue != null && removeFacetValue.length() > 0) {
                selectedFacetNames = newSelectedFacetNames.toString();
                selectedFacetValues = newSelectedFacetValues.toString();
            }

            if (log.isDebugEnabled()) {
                log.debug("After removing facet names(final):" + selectedFacetNames);
                log.debug("After removing facet values(final):" + selectedFacetValues);
            }

            // Query formation
            solrQuery.setFacet(true).setFacetMinCount(1);
            solrQuery.addFacetField("status");
            solrQuery.addFacetField("provider_name");
            solrQuery.addFacetField("service_name");
            solrQuery.addFacetField("format_name");
            solrQuery.addFacetField("set_name");
            solrQuery.addFacetField("error");

            // Fields to load
            solrQuery.addField(RecordService.FIELD_RECORD_ID);
            solrQuery.addField(RecordService.FIELD_FORMAT_ID);
            solrQuery.addField(RecordService.FIELD_PROVIDER_ID);
            solrQuery.addField(RecordService.FIELD_SERVICE_ID);
            solrQuery.addField(RecordService.FIELD_HARVEST_SCHEDULE_NAME);
            solrQuery.addField(RecordService.FIELD_ERROR);
            solrQuery.addField(RecordService.FIELD_PROCESSED_FROM);
            solrQuery.addField(RecordService.FIELD_SUCCESSOR);
            solrQuery.addField(RecordService.FIELD_OAI_IDENTIFIER);

            getIdentifiers();

            rowEnd = rowStart + numberOfResultsToShow;

            // In initial page load, we are not going to show any records. Only facets will be shown
            if (isInitialLoad) {
                solrQuery.setStart(0);
                solrQuery.setRows(0);
            } else {
                solrQuery.setStart(rowStart);
                solrQuery.setRows(numberOfResultsToShow);
            }
            BrowseRecordService browseRecordService = (BrowseRecordService) MSTConfiguration.getInstance()
                    .getBean("BrowseRecordService");
            result = browseRecordService.search(solrQuery);

            if (log.isDebugEnabled()) {
                log.debug("Search result::" + result);
            }

            if ((result != null) && (rowEnd > result.getTotalNumberOfResults())) {
                rowEnd = result.getTotalNumberOfResults();
            }

            // Add facet name and value list to SolrBrowseResult(result) object for display in UI
            if (result != null) {
                for (int i = 0; i < facetNamesList.size(); i++) {
                    // Get successor/predecessor of the record to display its information
                    if (facetNamesList.get(i).equalsIgnoreCase("successor")) {
                        successorRecord = recordService.getById(Long.parseLong(facetValuesList.get(i)));
                    }
                    if (facetNamesList.get(i).equalsIgnoreCase("processed_from")) {

                        predecessorRecord = recordService.getById(Long.parseLong(facetValuesList.get(i)));
                    }

                    result.addFacetFilter(new FacetFilter(facetNamesList.get(i), facetValuesList.get(i)));
                }
            }
        } catch (DatabaseConfigException dce) {
            log.error(
                    "Search failed. Problem with connecting to database using the parameters in configuration file.",
                    dce);
            errorType = "error";
            addFieldError("dbError",
                    "Search failed.Problem with connecting to database using the parameters in configuration file.");
            return INPUT;
        } catch (IndexException ie) {
            log.error("Search failed. Problem with connecting to Solr server. Check the path to solr folder.", ie);
            errorType = "error";
            addFieldError("dbError",
                    "Search failed. Problem with connecting to Solr server. Check the path to solr folder.");
            return INPUT;
        }

        return SUCCESS;
    }

    /**
     * View record XML
     */
    public String viewRecord() throws IOException {

        if (log.isDebugEnabled()) {
            log.debug("viewRecord:  view record Id : " + recordId);
        }

        try {
            RepositoryService repositoryService = (RepositoryService) MSTConfiguration.getInstance()
                    .getBean("RepositoryService");
            record = repositoryService.getRecord(recordId);
            recordXML = record.getOaiXml();
            if (recordXML != null) {
                XmlHelper xh = new XmlHelper();
                recordXML = StringEscapeUtils
                        .escapeHtml(xh.getStringPretty(xh.getJDomDocument(recordXML).getRootElement()));
            }
        } catch (Throwable t) {
            log.error("", t);
            errorType = "error";
            addFieldError("dbError",
                    "Problem with connecting to database using the parameters in configuration file.");
            return INPUT;
        }

        return SUCCESS;
    }

    /**
     * View error description  (additional help file)
     */
    public String viewErrorDescription() {

        if (log.isDebugEnabled()) {
            log.debug("viewErrorDescription: error to view : " + error);
        }

        try {
            ServicesService servicesService = (ServicesService) MSTConfiguration.getInstance()
                    .getBean("ServicesService");
            // at this point we don't have much to go on, as far as I can tell, we only know the message text (error)
            // ,one negative of this new workaround way is if 2 services contain same error text, we'll grab 1st one we find,
            // and its associated help file,
            Service service = null;
            String fileName = null;
            String errorCode = error.substring(0, error.indexOf(":"));
            for (Service s : servicesService.getAllServices()) {
                String codez = s.getMetadataService().getConfig().getProperty("error." + errorCode + ".text");
                log.info("Error= " + error + " errorCode=" + errorCode + " this service's text=" + codez
                        + " tried prop:" + "error." + errorCode + ".text");
                if (codez != null) {
                    if (error.indexOf(codez) > -1) {
                        service = s;
                        fileName = s.getMetadataService().getConfig()
                                .getProperty("error." + errorCode + ".descriptionFile");
                        break;
                    }
                }
            }
            if (service != null && fileName != null) {
                // Get error code
                FileInputStream fis = new FileInputStream(MSTConfiguration.getInstance().getServicePath()
                        + service.getName() + "/errors/" + fileName);
                BufferedInputStream bis = new BufferedInputStream(fis);
                DataInputStream dis = new DataInputStream(bis);
                BufferedReader br = new BufferedReader(new InputStreamReader(dis));
                StringBuffer buffer = new StringBuffer();
                String strLine;
                // Read File Line By Line
                while ((strLine = br.readLine()) != null) {
                    buffer.append(strLine);
                }
                errorDescription = buffer.toString();
            } else {
                log.debug("No errorDescription found for " + error);
                errorDescription = "No further information is available for this error.";
            }
        } catch (DatabaseConfigException dce) {
            log.error(
                    "Problem with getting error information. Exception occured while connecting to database using the parameters in configuration file.",
                    dce);
            errorType = "error";
            addFieldError("dbError",
                    "Problem with getting error information. Exception occured while connecting to database using the parameters in configuration file.");
            return INPUT;
        } catch (Exception e) {
            log.error("Problem with getting error information.", e);
            errorType = "error";
            addFieldError("dbError", "Exception occured while getting error information.");
            return INPUT;
        }
        return SUCCESS;
    }

    public SolrBrowseResult getResult() {
        return result;
    }

    public void setResult(SolrBrowseResult result) {
        this.result = result;
    }

    public String getRemoveFacetName() {
        return removeFacetName;
    }

    public void setRemoveFacetName(String removeFacetName) {
        this.removeFacetName = removeFacetName;
    }

    public String getRemoveFacetValue() {
        return removeFacetValue;
    }

    public void setRemoveFacetValue(String removeFacetValue) {
        this.removeFacetValue = removeFacetValue;
    }

    public String getAddFacetName() {
        return addFacetName;
    }

    public void setAddFacetName(String addFacetName) {
        this.addFacetName = addFacetName;
    }

    public String getAddFacetValue() {
        return addFacetValue;
    }

    public void setAddFacetValue(String addFacetValue) {
        this.addFacetValue = addFacetValue;
    }

    public String getSelectedFacetNames() {
        return selectedFacetNames;
    }

    public void setSelectedFacetNames(String selectedFacetNames) {
        this.selectedFacetNames = selectedFacetNames;
    }

    public String getSelectedFacetValues() {
        return selectedFacetValues;
    }

    public void setSelectedFacetValues(String selectedFacetValues) {
        this.selectedFacetValues = selectedFacetValues;
    }

    public String getQuery() {
        return query;
    }

    public void setQuery(String query) {
        this.query = query;
    }

    public int getRecordId() {
        return recordId;
    }

    public void setRecordId(int recordId) {
        this.recordId = recordId;
    }

    public String getRecordXML() {
        return recordXML;
    }

    public HttpServletResponse getServletResponse() {
        return servletResponse;
    }

    public void setServletResponse(HttpServletResponse servletResponse) {
        this.servletResponse = servletResponse;
    }

    public long getRowEnd() {
        return rowEnd;
    }

    public void setRowEnd(long rowEnd) {
        this.rowEnd = rowEnd;
    }

    /**
     * Returns the total number of hits
     *
     * @see xc.mst.action.browse.Pager#getTotalHits()
     */
    public long getTotalHits() {
        return result.getTotalNumberOfResults();
    }

    public boolean isSearchXML() {
        return searchXML;
    }

    public void setSearchXML(boolean searchXML) {
        this.searchXML = searchXML;
    }

    public boolean isInitialLoad() {
        return isInitialLoad;
    }

    public void setInitialLoad(boolean isInitialLoad) {
        this.isInitialLoad = isInitialLoad;
    }

    public Record getSuccessorRecord() {
        return successorRecord;
    }

    public Record getPredecessorRecord() {
        return predecessorRecord;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }

    public String getErrorDescription() {
        return errorDescription;
    }

    public void setErrorDescription(String errorDescription) {
        this.errorDescription = errorDescription;
    }

    public Record getRecord() {
        return record;
    }

    public String getErrorType() {
        return errorType;
    }

    public void setErrorType(String errorType) {
        this.errorType = errorType;
    }

    public HashMap<String, String> getIdentifiers() {
        if (identifiers == null || identifiers.size() < 1) {
            try {
                initializeIdentifiers();
            } catch (DatabaseConfigException e) {
                log.error("", e);
                errorType = "error";
                addFieldError("dbError",
                        "Problem with connecting to database using the parameters in configuration file.");
            }
        }
        return identifiers;
    }

    public void setIdentifiers(LinkedHashMap<String, String> id) {
        this.identifiers = id;
    }

    public ArrayList<String> getIdKeys() {
        if (idKeys == null || idKeys.size() < 1) {
            try {
                initializeIdentifiers();
            } catch (DatabaseConfigException e) {
                log.error("", e);
                errorType = "error";
                addFieldError("dbError",
                        "Problem with connecting to database using the parameters in configuration file.");
            }
        }
        return idKeys;
    }

    public void setIdKeys(ArrayList<String> key) {
        this.idKeys = key;
    }

    public String getIdentifier() {
        return this.identifier;
    }

    public void setIdentifier(String id) {
        this.identifier = id;
    }

    public void initializeIdentifiers() throws DatabaseConfigException {

        SolrIndexService solrIndexService = getSolrIndexService();
        Map<String, String> ids = solrIndexService.getIdentifiers();
        if (identifiers == null) {
            identifiers = new LinkedHashMap<String, String>();
        }
        if (idKeys == null) {
            idKeys = new ArrayList<String>();
        }
        if (ids != null && ids.size() > 0) {
            identifiers.putAll(ids);
            idKeys.addAll(ids.keySet());
        }
    }
}