@Override public Iterator<Item> findByMetadataQuery( Context context, List<List<MetadataField>> listFieldList, List<String> query_op, List<String> query_val, List<UUID> collectionUuids, String regexClause, int offset, int limit) throws SQLException { Criteria criteria = createCriteria(context, Item.class, "item"); criteria.setFirstResult(offset); criteria.setMaxResults(limit); if (!collectionUuids.isEmpty()) { DetachedCriteria dcollCriteria = DetachedCriteria.forClass(Collection.class, "coll"); dcollCriteria.setProjection(Projections.property("coll.id")); dcollCriteria.add(Restrictions.eqProperty("coll.id", "item.owningCollection")); dcollCriteria.add(Restrictions.in("coll.id", collectionUuids)); criteria.add(Subqueries.exists(dcollCriteria)); } int index = Math.min(listFieldList.size(), Math.min(query_op.size(), query_val.size())); StringBuilder sb = new StringBuilder(); for (int i = 0; i < index; i++) { OP op = OP.valueOf(query_op.get(i)); if (op == null) { log.warn("Skipping Invalid Operator: " + query_op.get(i)); continue; } if (op == OP.matches || op == OP.doesnt_match) { if (regexClause.isEmpty()) { log.warn("Skipping Unsupported Regex Operator: " + query_op.get(i)); continue; } } DetachedCriteria subcriteria = DetachedCriteria.forClass(MetadataValue.class, "mv"); subcriteria.add(Property.forName("mv.dSpaceObject").eqProperty("item.id")); subcriteria.setProjection(Projections.property("mv.dSpaceObject")); if (!listFieldList.get(i).isEmpty()) { subcriteria.add(Restrictions.in("metadataField", listFieldList.get(i))); } sb.append(op.name() + " "); if (op == OP.equals || op == OP.not_equals) { subcriteria.add(Property.forName("mv.value").eq(query_val.get(i))); sb.append(query_val.get(i)); } else if (op == OP.like || op == OP.not_like) { subcriteria.add(Property.forName("mv.value").like(query_val.get(i))); sb.append(query_val.get(i)); } else if (op == OP.contains || op == OP.doesnt_contain) { subcriteria.add(Property.forName("mv.value").like("%" + query_val.get(i) + "%")); sb.append(query_val.get(i)); } else if (op == OP.matches || op == OP.doesnt_match) { subcriteria.add( Restrictions.sqlRestriction(regexClause, query_val.get(i), StandardBasicTypes.STRING)); sb.append(query_val.get(i)); } if (op == OP.exists || op == OP.equals || op == OP.like || op == OP.contains || op == OP.matches) { criteria.add(Subqueries.exists(subcriteria)); } else { criteria.add(Subqueries.notExists(subcriteria)); } } log.debug(String.format("Running custom query with %d filters", index)); return list(criteria).iterator(); }
private Criterion parseExpression(Expression expression) { ExpressionTypes type = expression.getType(); String propertyName = expression.getTargetPropertyName(); Object value = expression.getValue(); Class<?> clazz; if (log.isTraceEnabled()) { log.trace( String.format( "Parsing expression of type '%s' for propety '%s', value=%s", type.name(), propertyName, value)); } switch (type) { case EQUAL: return org.hibernate.criterion.Restrictions.eq(propertyName, value); case GREATER: return org.hibernate.criterion.Restrictions.gt(propertyName, value); case GREATER_OR_EQUAL: return org.hibernate.criterion.Restrictions.ge(propertyName, value); case LESS: return org.hibernate.criterion.Restrictions.lt(propertyName, value); case LESS_OR_EQUAL: return org.hibernate.criterion.Restrictions.le(propertyName, value); case LIKE: String sval = (String) value; if (sval.contains("%") || sval.contains("_")) { return org.hibernate.criterion.Restrictions.ilike(propertyName, sval); } else { return org.hibernate.criterion.Restrictions.ilike(propertyName, sval, MatchMode.ANYWHERE); } case LIKE_END: return org.hibernate.criterion.Restrictions.ilike( propertyName, (String) value, MatchMode.END); case LIKE_START: return org.hibernate.criterion.Restrictions.ilike( propertyName, (String) value, MatchMode.START); case LIKE_EXACT: return org.hibernate.criterion.Restrictions.ilike( propertyName, (String) value, MatchMode.EXACT); case BETWEEN: return org.hibernate.criterion.Restrictions.between( propertyName, ((Object[]) value)[0], ((Object[]) value)[1]); case IN: clazz = value.getClass(); if (clazz.isArray()) { return org.hibernate.criterion.Restrictions.in(propertyName, (Object[]) value); } else if (Collection.class.isAssignableFrom(clazz)) { return org.hibernate.criterion.Restrictions.in(propertyName, (Collection<?>) value); } else { throw new IllegalStateException( "Object for 'IN' criteria must be array or collection, but it is " + (clazz == null ? "(null)" : "'" + clazz.getName() + "'")); } case IS_NULL: return org.hibernate.criterion.Restrictions.isNull(propertyName); case IS_NOT_NULL: return org.hibernate.criterion.Restrictions.isNotNull(propertyName); case NOT_EQUAL: return org.hibernate.criterion.Restrictions.ne(propertyName, value); case EXISTS: return Subqueries.exists(subquery((SubqueryExpression) expression)); case NOT_EXISTS: return Subqueries.notExists(subquery((SubqueryExpression) expression)); case EQUAL_PROPERTY: if (!(value instanceof CharSequence)) { throw new IllegalStateException( "Value for 'EQUAL_PROPERTY' criteria must be CharSequence, but it is " + (value == null ? "(null)" : "'" + value.getClass().getName() + "'")); } return org.hibernate.criterion.Restrictions.eqProperty(propertyName, value.toString()); case GREATER_PROPERTY: return org.hibernate.criterion.Restrictions.gtProperty(propertyName, value.toString()); case LESS_PROPERTY: return org.hibernate.criterion.Restrictions.ltProperty(propertyName, value.toString()); case GREATER_EQUAL_PROPERTY: return org.hibernate.criterion.Restrictions.geProperty(propertyName, value.toString()); case LESS_EQUAL_PROPERTY: return org.hibernate.criterion.Restrictions.leProperty(propertyName, value.toString()); case SQL_RESTICTION: return org.hibernate.criterion.Restrictions.sqlRestriction(value.toString()); default: throw new IllegalStateException( String.format("Unknown query expression '%s'", type.name())); } }