podd.search.impl.SearchCriteriaImpl.java Source code

Java tutorial

Introduction

Here is the source code for podd.search.impl.SearchCriteriaImpl.java

Source

/*
 * Copyright (c) 2009 - 2010. School of Information Technology and Electrical
 * Engineering, The University of Queensland.  This software is being developed
 * for the "Phenomics Ontoogy Driven Data Management Project (PODD)" project.
 * PODD is a National e-Research Architecture Taskforce (NeAT) project
 * co-funded by ANDS and ARCS.
 *
 * PODD is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PODD 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PODD.  If not, see <http://www.gnu.org/licenses/>.
 */

package podd.search.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.springframework.util.StringUtils;

import podd.model.entity.impl.AbstractEntityImpl;
import podd.model.project.Project.ProjectPublicationStatus;
import podd.model.project.ProjectStatus;
import podd.search.IndexFields;
import podd.search.SearchCriteria;
import fedora.server.utilities.DateUtility;

/**
 * Search criteria for searching the index
 *
 * @author Philip Wu
 */
public class SearchCriteriaImpl extends AbstractEntityImpl implements SearchCriteria {

    private static final Logger LOGGER = LoggerFactory.getLogger(SearchCriteriaImpl.class);

    public static final String WHITE_SPACE = "\\s";
    public static final String AND = " AND ";
    public static final String OR = " OR ";
    public static final String NOT = " -";

    protected Long start;
    protected Integer pageSize;
    // Queries
    protected String queryAllTheseWords;
    protected String queryAnyTheseWords;
    protected String queryPhrase;
    protected String queryExclude;

    //Filters
    protected Date startCreationDate;
    protected Date endCreationDate;
    protected Collection<String> objectTypes;
    protected String poddObjectId;
    protected Collection<String> projectIdsInclusive;
    protected Collection<String> projectIdsExclusive;

    // project statuses
    protected ProjectStatus projectStatus;
    protected ProjectPublicationStatus publicationStatus;

    protected String barcode;
    protected List<IndexFieldValue> filterFields = new ArrayList<IndexFieldValue>();

    public SearchCriteriaImpl() {
        // Set the default page size
        setPageSize(SearchCriteria.DEFAULT_PAGE_SIZE);
    }

    @Override
    public void setStart(Long start) {
        this.start = start;
    }

    @Override
    public Long getStart() {
        return start;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

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

    public Integer getPageSize() {

        return pageSize;
    }

    @Override
    public String getQueryAllTheseWords() {
        return queryAllTheseWords;
    }

    @Override
    public String getQueryAnyTheseWords() {
        return queryAnyTheseWords;
    }

    @Override
    public String getQueryExclude() {
        return queryExclude;
    }

    @Override
    public String getQueryPhrase() {
        return queryPhrase;
    }

    @Override
    public void setQueryAnyTheseWords(String anyTheseWords) {
        this.queryAnyTheseWords = anyTheseWords;
    }

    @Override
    public void setQueryExclude(String queryExclude) {
        this.queryExclude = queryExclude;
    }

    @Override
    public void setQueryPhrase(String phrase) {
        this.queryPhrase = phrase;
    }

    @Override
    public Date getStartCreationDate() {
        return startCreationDate;
    }

    @Override
    public void setStartCreationDate(Date startCreationDate) {
        this.startCreationDate = startCreationDate;
    }

    @Override
    public Date getEndCreationDate() {
        return endCreationDate;
    }

    @Override
    public void setEndCreationDate(Date endCreationDate) {
        this.endCreationDate = endCreationDate;
    }

    @Override
    public Collection<String> getObjectTypes() {
        return objectTypes;
    }

    @Override
    public void setObjectTypes(Collection<String> objectTypes) {
        this.objectTypes = objectTypes;
    }

    @Override
    public void addObjectType(String type) {
        if (objectTypes == null) {
            objectTypes = new ArrayList<String>();
        }
        objectTypes.add(type);

    }

    @Override
    public String getPoddObjectId() {
        return poddObjectId;
    }

    @Override
    public void setPoddObjectId(String id) {
        this.poddObjectId = id;
    }

    @Override
    public void addProjectIdExclusive(String id) {
        if (projectIdsExclusive == null) {
            projectIdsExclusive = new HashSet<String>();
        }
        projectIdsExclusive.add(id);
    }

    @Override
    public void addProjectIdInclusive(String id) {
        if (projectIdsInclusive == null) {
            projectIdsInclusive = new HashSet<String>();
        }
        projectIdsInclusive.add(id);

    }

    @Override
    public Collection<String> getProjectIdsExclusive() {
        return projectIdsExclusive;
    }

    @Override
    public Collection<String> getProjectIdsInclusive() {
        return projectIdsInclusive;
    }

    @Override
    public void setProjectIdsExclusive(Collection<String> ids) {
        this.projectIdsExclusive = ids;
    }

    @Override
    public void setProjectIdsInclusive(Collection<String> ids) {
        this.projectIdsInclusive = ids;
    }

    @Override
    public ProjectStatus getProjectStatus() {
        return projectStatus;
    }

    @Override
    public void setProjectStatus(ProjectStatus projectStatus) {
        this.projectStatus = projectStatus;
    }

    @Override
    public ProjectPublicationStatus getPublicationStatus() {
        return publicationStatus;
    }

    @Override
    public void setPublicationStatus(ProjectPublicationStatus publicationStatus) {
        this.publicationStatus = publicationStatus;
    }

    @Override
    public String getBarcode() {
        return barcode;
    }

    @Override
    public void setBarcode(String barcode) {
        this.barcode = barcode;
    }

    /**
      * Helper class to put together AND/OR conditions from an array of queries
      *
      * @param indexField
      * @param array
      * @param condition
      * @param conditionAfterFirst if the condition is  NOT you'll want this to be false
      * @return
      */
    private String buildFromQueryArray(IndexFields indexField, String[] array, String condition,
            boolean conditionAfterFirst) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < array.length; i++) {
            String word = array[i];
            if (StringUtils.hasLength(word)) {
                if (!conditionAfterFirst || sb.length() > 0) {
                    sb.append(condition);
                }
                if (indexField != null) {
                    sb.append(indexField).append(":");
                }
                sb.append(ClientUtils.escapeQueryChars(word));
            }
        }

        return sb.toString();
    }

    private boolean hasProjectIdsExclusive() {
        return (this.getProjectIdsExclusive() != null && this.getProjectIdsExclusive().size() > 0);
    }

    private boolean hasProjectIdsInclusive() {
        return (this.getProjectIdsInclusive() != null && this.getProjectIdsInclusive().size() > 0);
    }

    /**
     * Process the project id inclusive and exclusive so that there are no overlapping values
     * @return
     */
    private Set<String> getFinalProjectIdsInclusive() {
        // Clean up by removing any project ids identified in exclusive from the list of inclusive
        Set<String> cleanInclusive = new HashSet<String>();
        if (hasProjectIdsInclusive())
            cleanInclusive.addAll(this.getProjectIdsInclusive());
        if (hasProjectIdsExclusive())
            cleanInclusive.removeAll(this.getProjectIdsExclusive());

        // clean up any null items in the collection
        for (Iterator<String> it = cleanInclusive.iterator(); it.hasNext();) {
            String projectId = it.next();
            if (projectId == null)
                it.remove();
        }

        return cleanInclusive;
    }

    @Override
    public String getQuery() {
        // Convert the queries into a single query for Solr

        StringBuilder sb = new StringBuilder();

        // All these words
        if (StringUtils.hasText(this.getQueryAllTheseWords())) {
            String[] allTheseWords = this.getQueryAllTheseWords().split(WHITE_SPACE);

            sb.append(buildFromQueryArray(null, allTheseWords, AND, true));
        }

        // Any these words
        if (StringUtils.hasText(this.getQueryAnyTheseWords())) {
            if (sb.length() > 0) {
                sb.append(AND);
            }

            String[] anyTheseWords = this.getQueryAnyTheseWords().split(WHITE_SPACE);
            sb.append(" ");
            sb.append("(");
            sb.append(buildFromQueryArray(null, anyTheseWords, OR, true));
            sb.append(")");
        }

        // Phrase
        if (StringUtils.hasText(this.getQueryPhrase())) {
            if (sb.length() > 0) {
                sb.append(AND);
            }
            // Remove all existing double quotes
            String phrase = this.getQueryPhrase().replaceAll("\"", "");
            // Now append quotes around the phrase
            sb.append(" ");
            sb.append("(");
            sb.append("\"").append(ClientUtils.escapeQueryChars(phrase)).append("\"");
            sb.append(")");
        }

        // Exclude
        if (StringUtils.hasText(this.getQueryExclude())) {
            String[] excludes = this.getQueryExclude().split(WHITE_SPACE);
            sb.append(buildFromQueryArray(null, excludes, NOT, false));
        }

        // PODD object id
        if (StringUtils.hasText(this.poddObjectId)) {
            if (sb.length() > 0) {
                sb.append(AND);
            }
            sb.append(" ").append(IndexFields.ID.toString()).append(":")
                    .append(ClientUtils.escapeQueryChars(this.getPoddObjectId()));
        }

        String q = sb.toString();

        // If there are no query terms, then search on everything
        if (!StringUtils.hasText(q.trim())) {
            q = "*:*";
        }

        LOGGER.info("solr query=" + q);

        return q;
    }

    @Override
    public String getQueryFilter() {
        StringBuilder sb = new StringBuilder();

        // Creation dates
        if (this.getStartCreationDate() != null || this.getEndCreationDate() != null) {
            if (sb.length() > 0) {
                sb.append(AND);
            }
            sb.append(" ");
            sb.append(IndexFields.CREATION_DATE.toString()).append(":");
            sb.append("[");

            if (this.getStartCreationDate() != null) {
                sb.append(DateUtility.convertDateToString(this.getStartCreationDate()));
            } else {
                sb.append("*");
            }

            sb.append(" TO ");

            if (this.getEndCreationDate() != null) {
                sb.append(DateUtility.convertDateToString(this.getEndCreationDate()));
            } else {
                sb.append("*");
            }

            sb.append("]");
        }

        // Object type
        if (this.getObjectTypes() != null && this.getObjectTypes().size() > 0) {

            // Convert to array
            String[] array = convertToArray(this.getObjectTypes());

            String typeQuery = buildFromQueryArray(IndexFields.OBJECT_TYPE, array, OR, true);
            if (StringUtils.hasText(typeQuery)) {
                if (sb.length() > 0) {
                    sb.append(AND);
                }
                sb.append("(");
                sb.append(typeQuery);
                sb.append(")");
            }

        }

        if (this.hasProjectIdsExclusive() || this.hasProjectIdsInclusive()) {

            Set<String> finalProjectIdsInclusive = getFinalProjectIdsInclusive();
            //LOGGER.info("finalProjectIdsInclusive="+finalProjectIdsInclusive+ " projectIdsExclusive="+this.getProjectIdsExclusive());
            if (this.hasProjectIdsExclusive() || finalProjectIdsInclusive.size() > 0) {
                if (sb.length() > 0)
                    sb.append(" AND ");

                sb.append("(");
                // Project IDs exclusive
                if (this.hasProjectIdsExclusive()) {

                    // Convert to array
                    String[] array = convertToArray(this.getProjectIdsExclusive());

                    String typeQuery = buildFromQueryArray(IndexFields.PROJECT_ID, array, NOT, false);
                    if (StringUtils.hasText(typeQuery)) {
                        if (sb.length() > 0) {
                            //sb.append(AND);
                            sb.append(" ");
                        }
                        sb.append("(");
                        sb.append(typeQuery);
                        sb.append(")");
                    }
                }

                // Project IDs inclusive
                if (finalProjectIdsInclusive.size() > 0) {

                    // Convert to array
                    String[] array = convertToArray(finalProjectIdsInclusive);

                    String typeQuery = buildFromQueryArray(IndexFields.PROJECT_ID, array, OR, true);
                    if (StringUtils.hasText(typeQuery)) {
                        if (sb.length() > 0) {
                            //sb.append(AND);
                            sb.append(" ");
                        }
                        sb.append("(");
                        sb.append(typeQuery);
                        sb.append(")");
                    }
                }

                sb.append(")");
            }
        }

        // Project status
        if (this.getProjectStatus() != null) {
            if (sb.length() > 0) {
                sb.append(AND);
            }
            sb.append(IndexFields.PROJECT_STATUS).append(":").append(this.getProjectStatus().toString());

        }

        // Publication status
        if (this.getPublicationStatus() != null) {
            if (sb.length() > 0) {
                sb.append(AND);
            }
            sb.append(IndexFields.PUBLICATION_STATUS).append(":").append(this.getPublicationStatus().toString());
        }

        // Barcode
        if (this.getBarcode() != null) {
            if (sb.length() > 0)
                sb.append(AND);

            sb.append(IndexFields.HAS_BARCODE);
            sb.append(":");
            sb.append(barcode);
        }

        // Generic filter fields
        if (this.filterFields != null && this.filterFields.size() > 0) {
            for (IndexFieldValue indexFieldValue : filterFields) {

                if (sb.length() > 0)
                    sb.append(AND);

                sb.append(indexFieldValue.getIndexField().toString());
                sb.append(":");
                sb.append(indexFieldValue.getValue());
            }
        }

        String f = sb.toString();

        LOGGER.info("solr filter=" + f);

        return f;
    }

    /**
     * Helper method to convert a collection of strings to an array
     *
     * @param col
     * @return
     */
    public static String[] convertToArray(Collection<String> col) {
        String[] array = new String[col.size()];
        int i = 0;
        for (Iterator<String> it = col.iterator(); it.hasNext();) {
            array[i] = it.next();
            i++;
        }

        return array;
    }

    @Override
    public void addFilterField(IndexFields indexField, String fieldValue) {

        if (indexField == null || fieldValue == null)
            throw new IllegalArgumentException("The arguments cannot be null");

        filterFields.add(new IndexFieldValue(indexField, fieldValue));
    }

}

/**
 * the value to be associated with an index field
 * @author Philip Wu
 *
 */
class IndexFieldValue {

    private IndexFields indexField;
    private String value;

    public IndexFieldValue(IndexFields indexField, String value) {
        this.indexField = indexField;
        this.value = value;
    }

    public IndexFields getIndexField() {
        return indexField;
    }

    public void setIndexField(IndexFields indexField) {
        this.indexField = indexField;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

}