package edu.ualberta.med.biobank.common.reports.filters.types; import java.util.Arrays; import java.util.Collection; import java.util.List; import org.hibernate.Criteria; import org.hibernate.criterion.Conjunction; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.Disjunction; import org.hibernate.criterion.Restrictions; import edu.ualberta.med.biobank.common.reports.ReportsUtil; import edu.ualberta.med.biobank.common.reports.filters.FilterOperator; import edu.ualberta.med.biobank.common.reports.filters.FilterType; import edu.ualberta.med.biobank.model.ReportFilterValue; public abstract class NumberFilterType<E extends Number> implements FilterType { @Override public void addCriteria(Criteria criteria, String aliasedProperty, FilterOperator op, List<ReportFilterValue> values) { switch (op) { case EQUALS: FilterTypeUtil.checkValues(values, 0, 1); for (ReportFilterValue value : values) { criteria.add(Restrictions.eq(aliasedProperty, getFirstNumber(value))); break; } break; case DOES_NOT_EQUAL: { FilterTypeUtil.checkValues(values, 0, 1); Disjunction or = ReportsUtil.idIsNullOr(aliasedProperty); for (ReportFilterValue value : values) { or.add(Restrictions.ne(aliasedProperty, getFirstNumber(value))); break; } criteria.add(or); } break; case IS_IN: { Disjunction or = Restrictions.disjunction(); for (ReportFilterValue value : values) { or.add(Restrictions.eq(aliasedProperty, getFirstNumber(value))); } criteria.add(or); } break; case IS_NOT_IN: { Disjunction or = ReportsUtil.idIsNullOr(aliasedProperty); Conjunction and = Restrictions.conjunction(); for (ReportFilterValue value : values) { and.add(Restrictions.ne(aliasedProperty, getFirstNumber(value))); } or.add(and); criteria.add(or); } break; case IS_NOT_SET: FilterTypeUtil.checkValues(values, 0, 0); criteria.add(ReportsUtil.isNotSet(aliasedProperty)); break; case BETWEEN: { FilterTypeUtil.checkValues(values, 0, 1); for (ReportFilterValue value : values) { criteria.add(between(aliasedProperty, value)); break; } } break; case BETWEEN_ANY: { Disjunction or = Restrictions.disjunction(); for (ReportFilterValue value : values) { or.add(between(aliasedProperty, value)); } criteria.add(or); } break; case NOT_BETWEEN: { FilterTypeUtil.checkValues(values, 0, 1); Disjunction or = ReportsUtil.idIsNullOr(aliasedProperty); for (ReportFilterValue value : values) { or.add(Restrictions.not(between(aliasedProperty, value))); break; } criteria.add(or); } break; case NOT_BETWEEN_ANY: { Disjunction or = ReportsUtil.idIsNullOr(aliasedProperty); Conjunction and = Restrictions.conjunction(); for (ReportFilterValue value : values) { and.add(Restrictions.not(between(aliasedProperty, value))); } or.add(and); criteria.add(or); } break; case LESS_THAN: FilterTypeUtil.checkValues(values, 0, 1); criteria.add(Restrictions.lt(aliasedProperty, getFirstNumber(values.get(0)))); break; case LESS_THAN_OR_EQUAL_TO: FilterTypeUtil.checkValues(values, 0, 1); criteria.add(Restrictions.le(aliasedProperty, getFirstNumber(values.get(0)))); break; case GREATER_THAN: FilterTypeUtil.checkValues(values, 0, 1); criteria.add(Restrictions.gt(aliasedProperty, getFirstNumber(values.get(0)))); break; case GREATER_THAN_OR_EQUAL_TO: FilterTypeUtil.checkValues(values, 0, 1); criteria.add(Restrictions.ge(aliasedProperty, getFirstNumber(values.get(0)))); break; } } @Override public Collection<FilterOperator> getOperators() { return Arrays.asList(FilterOperator.EQUALS, FilterOperator.DOES_NOT_EQUAL, FilterOperator.IS_IN, FilterOperator.IS_NOT_IN, FilterOperator.LESS_THAN, FilterOperator.LESS_THAN_OR_EQUAL_TO, FilterOperator.GREATER_THAN, FilterOperator.GREATER_THAN_OR_EQUAL_TO, FilterOperator.IS_NOT_SET, FilterOperator.BETWEEN, FilterOperator.BETWEEN_ANY, FilterOperator.NOT_BETWEEN, FilterOperator.NOT_BETWEEN_ANY); } protected abstract E getNumber(String string); private E getFirstNumber(ReportFilterValue value) { return getNumber(value.getValue()); } private E getSecondNumber(ReportFilterValue value) { return getNumber(value.getSecondValue()); } private Criterion between(String property, ReportFilterValue value) { return Restrictions.between(property, getFirstNumber(value), getSecondNumber(value)); } }