Java tutorial
/* * 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; } }