package nl.ipo.cds.admin.ba.filtering; import java.util.ArrayList; import java.util.List; import nl.ipo.cds.admin.ba.controller.beans.filtering.ConditionBean; import nl.ipo.cds.admin.ba.controller.beans.filtering.ConditionGroupBean; import nl.ipo.cds.admin.ba.controller.beans.filtering.DatasetFilterBean; import nl.ipo.cds.dao.ManagerDao; import nl.ipo.cds.dao.impl.ManagerDaoImpl; import nl.ipo.cds.domain.AttributeExpression; import nl.ipo.cds.domain.AttributeType; import nl.ipo.cds.domain.Dataset; import nl.ipo.cds.domain.DatasetFilter; import nl.ipo.cds.domain.FeatureType; import nl.ipo.cds.domain.FeatureTypeAttribute; import nl.ipo.cds.domain.FilterExpression; import nl.ipo.cds.domain.OperatorExpression; import nl.ipo.cds.domain.OperatorExpression.OperatorType; import nl.ipo.cds.domain.ValueExpression; import nl.ipo.cds.domain.ValueExpression.ValueType; import nl.ipo.cds.etl.filtering.FilterExpressionFactory; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; public class DatasetFilterFactory { private final Dataset dataset; private final ManagerDao dao; private final FeatureType featureType; public DatasetFilterFactory (final ManagerDao dao, final Dataset dataset, final FeatureType featureType) { this.dao = dao; this.dataset = dataset; this.featureType = featureType; } @Transactional (propagation = Propagation.MANDATORY) public DatasetFilter createDatasetFilter (final DatasetFilterBean bean, final DatasetFilter original) { final DatasetFilter filter; // Create or update a dataset filter: if (original != null) { filter = original; } else { filter = new DatasetFilter (); filter.setDataset (dataset); } // Clear the original filter: if (filter.getRootExpression () != null) { deleteExpression (filter.getRootExpression ()); filter.setRootExpression (null); } // Load condition groups: if (bean.getConditionGroups () != null && bean.getConditionGroups ().size () > 0) { filter.setRootExpression (createConditionGroups (bean.getConditionGroups ())); } else { if (original != null) { dao.delete (original); ((ManagerDaoImpl)dao).getEntityManager ().flush (); } return null; } // Create or update the filter: if (original != null) { dao.update (filter); } else { dao.create (filter); } ((ManagerDaoImpl)dao).getEntityManager ().flush (); return filter; } private void deleteExpression (final FilterExpression expression) { // Delete children: final List<FilterExpression> inputs = expression.getInputs (); if (inputs != null) { for (final FilterExpression exp: inputs) { deleteExpression (exp); } expression.setInputs (new ArrayList<FilterExpression> ()); } // Delete this expression: dao.delete (expression); } private FilterExpression createConditionGroups (final List<ConditionGroupBean> groups) { if (groups.size () == 0) { // No condition groups -> no filter expression. return null; } else if (groups.size () == 1) { // Single group -> no 'or' expression required. return createConditionGroup (groups.get (0)); } else { // Multiple groups -> create 'or' expression from groups. final OperatorExpression[] children = new OperatorExpression[groups.size ()]; for (int i = 0; i < groups.size (); ++ i) { children[i] = createConditionGroup (groups.get (i)); } final OperatorExpression exp = FilterExpressionFactory.or (children); dao.create (exp); return exp; } } private OperatorExpression createConditionGroup (final ConditionGroupBean group) { final List<ConditionBean> conditions = group.getConditions (); if (conditions == null || conditions.size () == 0) { // No conditions -> no filter expression. return null; } else if (conditions.size () == 1) { // Single condition -> no 'and' expression required. return createCondition (conditions.get (0)); } else { // Multiple conditions -> create 'and' expression from conditions. final OperatorExpression[] children = new OperatorExpression[conditions.size ()]; for (int i = 0; i < conditions.size (); ++ i) { children[i] = createCondition (conditions.get (i)); } final OperatorExpression exp = FilterExpressionFactory.and (children); dao.create (exp); return exp; } } private OperatorExpression createCondition (final ConditionBean condition) { if (condition == null) { return null; } // Create attribute reference and value: final AttributeExpression attribute = createAttributeExpression (condition.getField ()); final ValueExpression value = createValueExpression (condition.getValue (), attribute == null ? null : attribute.getAttributeType ()); // Create expression: final OperatorExpression exp; final String op = condition.getOperation (); if ("equals".equals (op)) { exp = FilterExpressionFactory.equal (attribute, value); } else if ("not_equals".equals (op)) { exp = FilterExpressionFactory.notEqual (attribute, value); } else if ("less_than".equals (op)) { exp = FilterExpressionFactory.lessThan (attribute, value); } else if ("less_than_equal".equals (op)) { exp = FilterExpressionFactory.lessThanEqual (attribute, value); } else if ("greater_than".equals (op)) { exp = FilterExpressionFactory.greaterThan (attribute, value); } else if ("greater_than_equal".equals (op)) { exp = FilterExpressionFactory.greaterThanEqual (attribute, value); } else if ("like".equals (op)) { exp = FilterExpressionFactory.operatorExpression (OperatorType.LIKE, attribute, value); } else if ("in".equals (op)) { exp = FilterExpressionFactory.operatorExpression (OperatorType.IN, attribute, value); } else if ("not_null".equals (op)) { exp = FilterExpressionFactory.operatorExpression (OperatorType.NOT_NULL, attribute); } else { exp = FilterExpressionFactory.equal (attribute, value); } exp.setCaseSensitive (condition.isCaseSensitive ()); dao.create (exp); return exp; } private ValueExpression createValueExpression (final String value, final AttributeType originalType) { final AttributeType type = originalType == null ? AttributeType.STRING : originalType; final ValueExpression exp = FilterExpressionFactory.valueExpression (value, createValueType (type)); dao.create (exp); return exp; } private AttributeExpression createAttributeExpression (final String attributePath) { if (attributePath == null) { return null; } // Extract the attribute name from the path: final int offset = attributePath.indexOf ('/'); final String attributeName; if (offset > 0) { attributeName = attributePath.substring (0, offset); } else { attributeName = attributePath; } // Locate the attribute: for (final FeatureTypeAttribute attr: featureType.getAttributes ()) { if (attr.getName ().getLocalPart ().equals (attributeName)) { final AttributeExpression exp = FilterExpressionFactory.attribute (attributePath, attr.getType ()); dao.create (exp); return exp; } } return null; } private ValueType createValueType (final AttributeType type) { switch (type) { case BOOLEAN: return ValueType.BOOLEAN; case DATE: return ValueType.DATE; case DATE_TIME: return ValueType.DATE_TIME; case DECIMAL: case GEOMETRY: case DOUBLE: case FLOAT: return ValueType.DOUBLE; case INTEGER: return ValueType.INTEGER; case TIME: return ValueType.TIME; default: case STRING: return ValueType.STRING; } } }