/** * The contents of this file are subject to the license and copyright * detailed in the LICENSE and NOTICE files at the root of the source * tree and available online at * * http://www.dspace.org/license/ */ package org.dspace.xoai.filter; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.solr.client.solrj.util.ClientUtils; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.xoai.data.DSpaceItem; import org.dspace.xoai.exceptions.InvalidMetadataFieldException; import org.dspace.xoai.filter.data.DSpaceMetadataFilterOperator; import org.dspace.xoai.filter.results.DatabaseFilterResult; import org.dspace.xoai.filter.results.SolrFilterResult; import com.google.common.base.Function; import com.lyncode.builder.ListBuilder; import com.lyncode.xoai.dataprovider.xml.xoaiconfig.parameters.ParameterList; import com.lyncode.xoai.dataprovider.xml.xoaiconfig.parameters.ParameterValue; import com.lyncode.xoai.dataprovider.xml.xoaiconfig.parameters.SimpleType; /** * @author Lyncode Development Team <dspace@lyncode.com> */ public class DSpaceAtLeastOneMetadataFilter extends DSpaceFilter { private static Logger log = LogManager.getLogger(DSpaceAtLeastOneMetadataFilter.class); private String field; private DSpaceMetadataFilterOperator operator = DSpaceMetadataFilterOperator.UNDEF; private List<String> values; private String getField() { if (field == null) { field = getConfiguration().get("field").asSimpleType().asString(); } return field; } private List<String> getValues() { if (values == null) { ParameterValue parameterValue = getConfiguration().get("value"); if (parameterValue == null) parameterValue = getConfiguration().get("values"); if (parameterValue instanceof SimpleType) { values = new ArrayList<String>(); values.add(((SimpleType) parameterValue).asString()); } else if (parameterValue instanceof ParameterList) { values = new ListBuilder<ParameterValue>() .add(parameterValue.asParameterList().getValues()) .build(new Function<ParameterValue, String>() { @Override public String apply(ParameterValue elem) { return elem.asSimpleType().asString(); } }); } else values = new ArrayList<String>(); } return values; } private DSpaceMetadataFilterOperator getOperator() { if (operator == DSpaceMetadataFilterOperator.UNDEF) operator = DSpaceMetadataFilterOperator.valueOf(getConfiguration() .get("operator").asSimpleType().asString().toUpperCase()); return operator; } @Override public DatabaseFilterResult buildDatabaseQuery(Context context) { if (this.getField() != null) { try { int id = fieldResolver.getFieldID(context, this.getField()); return this.getWhere(id, this.getValues()); } catch (InvalidMetadataFieldException ex) { log.error(ex.getMessage(), ex); } catch (SQLException ex) { log.error(ex.getMessage(), ex); } } return new DatabaseFilterResult(); } @Override public boolean isShown(DSpaceItem item) { if (this.getField() == null) return true; List<String> values = item.getMetadata(this.getField()); for (String praticalValue : values) { for (String theoreticValue : this.getValues()) { switch (this.getOperator()) { case STARTS_WITH: if (praticalValue.startsWith(theoreticValue)) return true; break; case ENDS_WITH: if (praticalValue.endsWith(theoreticValue)) return true; break; case EQUAL: if (praticalValue.equals(theoreticValue)) return true; break; case GREATER: if (praticalValue.compareTo(theoreticValue) > 0) return true; break; case GREATER_OR_EQUAL: if (praticalValue.compareTo(theoreticValue) >= 0) return true; break; case LOWER: if (praticalValue.compareTo(theoreticValue) < 0) return true; break; case LOWER_OR_EQUAL: if (praticalValue.compareTo(theoreticValue) <= 0) return true; break; case CONTAINS: default: if (praticalValue.contains(theoreticValue)) return true; break; } } } return false; } private DatabaseFilterResult getWhere(int mdid, List<String> values) { List<String> parts = new ArrayList<String>(); List<Object> params = new ArrayList<Object>(); params.add(mdid); for (String v : values) this.buildWhere(v, parts, params); if (parts.size() > 0) { String query = "EXISTS (SELECT tmp.* FROM metadatavalue tmp WHERE tmp.resource_id=i.item_id AND tmp.resource_type_id=" + Constants.ITEM+ " AND tmp.metadata_field_id=?" + " AND (" + StringUtils.join(parts.iterator(), " OR ") + "))"; return new DatabaseFilterResult(query, params); } return new DatabaseFilterResult(); } private void buildWhere(String value, List<String> parts, List<Object> params) { switch (this.getOperator()) { case ENDS_WITH: parts.add("(tmp.text_value LIKE ?)"); params.add("%" + value); break; case STARTS_WITH: parts.add("(tmp.text_value LIKE ?)"); params.add(value + "%"); break; case EQUAL: parts.add("(tmp.text_value LIKE ?)"); params.add(value); break; case GREATER: parts.add("(tmp.text_value > ?)"); params.add(value); break; case LOWER: parts.add("(tmp.text_value < ?)"); params.add(value); break; case LOWER_OR_EQUAL: parts.add("(tmp.text_value <= ?)"); params.add(value); break; case GREATER_OR_EQUAL: parts.add("(tmp.text_value >= ?)"); params.add(value); break; case CONTAINS: default: parts.add("(tmp.text_value LIKE ?)"); params.add("%" + value + "%"); break; } } @Override public SolrFilterResult buildSolrQuery() { String field = this.getField(); List<String> parts = new ArrayList<String>(); if (this.getField() != null) { for (String v : this.getValues()) this.buildQuery("metadata." + field, ClientUtils.escapeQueryChars(v), parts); if (parts.size() > 0) { return new SolrFilterResult(StringUtils.join(parts.iterator(), " OR ")); } } return new SolrFilterResult(); } private void buildQuery(String field, String value, List<String> parts) { switch (this.getOperator()) { case ENDS_WITH: parts.add("(" + field + ":*" + value + ")"); break; case STARTS_WITH: parts.add("(" + field + ":" + value + "*)"); break; case EQUAL: parts.add("(" + field + ":" + value + ")"); break; case GREATER: parts.add("(" + field + ":[" + value + " TO *])"); break; case LOWER: parts.add("(" + field + ":[* TO " + value + "])"); break; case LOWER_OR_EQUAL: parts.add("(-(" + field + ":[" + value + " TO *]))"); break; case GREATER_OR_EQUAL: parts.add("(-(" + field + ":[* TO " + value + "]))"); break; case CONTAINS: default: parts.add("(" + field + ":*" + value + "*)"); break; } } }