Create mechanism for reusing common parts of the queries

This allows to reuse the part that filters tasks by intervals and can
be used to filter by resource.

FEA: ItEr75S11PreventLooseChanges
This commit is contained in:
Óscar González Fernández 2011-07-26 19:44:14 +02:00
parent 9cda34cb55
commit 2b47fed73d
2 changed files with 296 additions and 113 deletions

View file

@ -84,7 +84,8 @@ public interface IResourceAllocationDAO extends
* allocations} found
*/
List<SpecificResourceAllocation> findSpecificAllocationsRelatedTo(
Criterion criterion, Date intervalFilterStartDate,
Criterion criterion,
Date intervalFilterStartDate,
Date intervalFilterEndDate);
}

View file

@ -28,10 +28,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import org.hibernate.Criteria;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Query;
import org.hibernate.criterion.Restrictions;
import org.hibernate.Session;
import org.joda.time.LocalDate;
import org.navalplanner.business.common.daos.GenericDAOHibernate;
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
@ -74,52 +75,79 @@ public class ResourceAllocationDAO extends
@SuppressWarnings("unchecked")
private List<GenericResourceAllocation> findGenericAllocationsFor(
List<Resource> resources, LocalDate intervalFilterStartDate,
LocalDate intervalFilterEndDate) {
if(resources.isEmpty()) {
final List<Resource> resources,
final LocalDate intervalFilterStartDate,
final LocalDate intervalFilterEndDate) {
if (resources.isEmpty()) {
return new ArrayList<GenericResourceAllocation>();
}
Criteria criteria = getSession().createCriteria(GenericResourceAllocation.class);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.createCriteria(
"genericDayAssignmentsContainers").createCriteria(
"dayAssignments").add(
Restrictions.in("resource", resources));
QueryBuilder queryBuilder = new QueryBuilder() {
filterByDatesIfApplyable(criteria, intervalFilterStartDate,
intervalFilterEndDate);
return (List<GenericResourceAllocation>) criteria.list();
@Override
protected String getBaseQuery() {
return "select distinct generic from GenericResourceAllocation generic "
+ "join generic.task task "
+ "join generic.genericDayAssignmentsContainers container "
+ "join container.dayAssignments dayAssignment";
}
@Override
protected String getBaseConditions() {
return "where dayAssignment.resource in (:resources)";
}
@Override
protected void setBaseParameters(Query query) {
query.setParameterList("resources", resources);
}
@Override
protected IQueryPart[] getExtraParts() {
return new IQueryPart[] { new DatesInterval("task",
intervalFilterStartDate, intervalFilterEndDate) };
}
};
Query query = queryBuilder.build(getSession());
return query.list();
}
@SuppressWarnings("unchecked")
private List<SpecificResourceAllocation> findSpecificAllocationsRelatedTo(
List<Resource> resources, LocalDate intervalFilterStartDate,
LocalDate intervalFilterEndDate) {
if(resources.isEmpty()) {
final List<Resource> resources,
final LocalDate intervalFilterStartDate,
final LocalDate intervalFilterEndDate) {
if (resources.isEmpty()) {
return new ArrayList<SpecificResourceAllocation>();
}
Criteria criteria = getSession().createCriteria(
SpecificResourceAllocation.class);
criteria.add(Restrictions.in("resource", resources));
QueryBuilder queryBuilder = new QueryBuilder() {
filterByDatesIfApplyable(criteria, intervalFilterStartDate,
intervalFilterEndDate);
return (List<SpecificResourceAllocation>) criteria.list();
}
@Override
protected String getBaseQuery() {
return "select distinct specific from "
+ "SpecificResourceAllocation specific "
+ "join specific.task task";
}
private void filterByDatesIfApplyable(Criteria criteria,
LocalDate intervalFilterStartDate, LocalDate intervalFilterEndDate) {
if(intervalFilterStartDate != null || intervalFilterEndDate != null) {
Criteria dateCriteria = criteria.createCriteria("task");
if(intervalFilterEndDate != null) {
dateCriteria.add(Restrictions.le("startDate.date",
intervalFilterEndDate));
@Override
protected String getBaseConditions() {
return "where specific.resource in (:resources)";
}
if(intervalFilterStartDate != null) {
dateCriteria.add(Restrictions.ge("endDate.date",
intervalFilterStartDate));
@Override
protected void setBaseParameters(Query query) {
query.setParameterList("resources", resources);
}
}
@Override
protected IQueryPart[] getExtraParts() {
return new IQueryPart[] { new DatesInterval("task",
intervalFilterStartDate, intervalFilterEndDate) };
}
};
return (List<SpecificResourceAllocation>) queryBuilder.build(
getSession()).list();
}
@Override
@ -156,67 +184,74 @@ public class ResourceAllocationDAO extends
@Override
public Map<Criterion, List<GenericResourceAllocation>> findGenericAllocationsByCriterion(
Date intervalFilterStartDate, Date intervalFilterEndDate) {
String query = "select generic, criterion "
+ "from GenericResourceAllocation as generic "
+ "join generic.criterions as criterion ";
if(intervalFilterStartDate != null || intervalFilterEndDate != null) {
query += "inner join generic.task as task ";
if(intervalFilterEndDate != null) {
query += "where task.startDate.date <= :intervalFilterEndDate ";
final Date intervalFilterStartDate, final Date intervalFilterEndDate) {
QueryBuilder queryBuilder = new QueryBuilder() {
@Override
protected String getBaseQuery() {
return "select generic, criterion "
+ "from GenericResourceAllocation as generic "
+ "join generic.criterions as criterion "
+ "join generic.task as task";
}
if(intervalFilterStartDate != null) {
if(intervalFilterEndDate != null) {
query += "and ";
}
else {
query += "where ";
}
query += "task.endDate.date >= :intervalFilterStartDate ";
@Override
protected String getBaseConditions() {
return "";
}
}
Query q = getSession().createQuery(query);
if(intervalFilterStartDate != null) {
q.setParameter("intervalFilterStartDate",
LocalDate.fromDateFields(intervalFilterStartDate));
}
if(intervalFilterEndDate != null) {
q.setParameter("intervalFilterEndDate",
LocalDate.fromDateFields(intervalFilterEndDate));
}
return toCriterionMapFrom(q);
@Override
protected void setBaseParameters(Query query) {
}
@Override
protected IQueryPart[] getExtraParts() {
return new IQueryPart[] { new DatesInterval("task",
intervalFilterStartDate, intervalFilterEndDate) };
}
};
Query query = queryBuilder.build(getSession());
return toCriterionMapFrom(query);
}
@Override
public Map<Criterion, List<GenericResourceAllocation>> findGenericAllocationsBySomeCriterion(
List<Criterion> criterions, Date intervalFilterStartDate, Date intervalFilterEndDate) {
final List<Criterion> criterions,
final Date intervalFilterStartDate, final Date intervalFilterEndDate) {
if (criterions.isEmpty()) {
return new HashMap<Criterion, List<GenericResourceAllocation>>();
}
String query = "select generic, criterion "
+ "from GenericResourceAllocation as generic "
+ "join generic.criterions as criterion ";
if(intervalFilterStartDate != null || intervalFilterEndDate != null) {
query += "inner join generic.task as task ";
}
query += "where criterion in(:criterions) ";
if(intervalFilterEndDate != null) {
query += "and task.startDate.date <= :intervalFilterEndDate ";
}
if(intervalFilterStartDate != null) {
query += "and task.endDate.date >= :intervalFilterStartDate ";
}
Query q = getSession().createQuery(query);
q.setParameterList("criterions", criterions);
if(intervalFilterStartDate != null) {
q.setParameter("intervalFilterStartDate",
LocalDate.fromDateFields(intervalFilterStartDate));
}
if(intervalFilterEndDate != null) {
q.setParameter("intervalFilterEndDate",
LocalDate.fromDateFields(intervalFilterEndDate));
}
QueryBuilder queryBuilder = new QueryBuilder() {
@Override
protected String getBaseQuery() {
return "select generic, criterion "
+ "from GenericResourceAllocation as generic "
+ "join generic.task as task "
+ "join generic.criterions as criterion ";
}
@Override
protected String getBaseConditions() {
return "where criterion in(:criterions) ";
}
@Override
protected void setBaseParameters(Query query) {
query.setParameterList("criterions", criterions);
}
@Override
protected IQueryPart[] getExtraParts() {
return new IQueryPart[] { new DatesInterval("task",
intervalFilterStartDate, intervalFilterEndDate) };
}
};
Query q = queryBuilder.build(getSession());
return toCriterionMapFrom(q);
}
@ -300,34 +335,37 @@ public class ResourceAllocationDAO extends
@Override
public List<SpecificResourceAllocation> findSpecificAllocationsRelatedTo(
Criterion criterion, Date intervalFilterStartDate,
Date intervalFilterEndDate) {
String queryString = "select distinct s from SpecificResourceAllocation s "
+ "join s.resource r "
+ "join r.criterionSatisfactions satisfaction "
+ "join satisfaction.criterion c";
if (intervalFilterStartDate != null || intervalFilterEndDate != null) {
queryString += " inner join s.task t";
}
queryString += " where c = :criterion";
if (intervalFilterEndDate != null) {
queryString += " and t.startDate.date <= :intervalFilterEndDate";
}
if (intervalFilterStartDate != null) {
queryString += " and t.endDate.date >= :intervalFilterStartDate";
}
final Criterion criterion,
final Date intervalFilterStartDate, final Date intervalFilterEndDate) {
Query query = getSession().createQuery(queryString);
query.setParameter("criterion", criterion);
QueryBuilder builder = new QueryBuilder() {
if (intervalFilterStartDate != null) {
query.setParameter("intervalFilterStartDate",
asLocalDate(intervalFilterStartDate));
}
if (intervalFilterEndDate != null) {
query.setParameter("intervalFilterEndDate",
asLocalDate(intervalFilterEndDate));
}
@Override
protected String getBaseQuery() {
return "select distinct s from SpecificResourceAllocation s "
+ "join s.resource r "
+ "join r.criterionSatisfactions satisfaction "
+ "join satisfaction.criterion c join s.task t";
}
@Override
protected String getBaseConditions() {
return " where c = :criterion";
}
@Override
protected void setBaseParameters(Query query) {
query.setParameter("criterion", criterion);
}
@Override
protected IQueryPart[] getExtraParts() {
return new IQueryPart[] { new DatesInterval("t",
intervalFilterStartDate, intervalFilterEndDate) };
}
};
Query query = builder.build(getSession());
@SuppressWarnings("unchecked")
List<SpecificResourceAllocation> result = query.list();
@ -355,4 +393,148 @@ public class ResourceAllocationDAO extends
return result;
}
public static abstract class QueryBuilder {
private static Pattern wherePattern = Pattern.compile("WHERE",
Pattern.CASE_INSENSITIVE);
protected abstract String getBaseQuery();
protected abstract String getBaseConditions();
protected abstract void setBaseParameters(Query query);
protected abstract IQueryPart[] getExtraParts();
public Query build(Session session) {
final List<IQueryPart> extraParts = Arrays.asList(getExtraParts());
String queryString = getBaseQuery();
queryString = withExtraQueryParts(queryString, extraParts);
queryString += " " + getBaseConditions();
queryString = withExtraWhereConditions(queryString, extraParts);
Query query = session.createQuery(queryString);
setBaseParameters(query);
injectParameters(query, extraParts);
return query;
}
private String withExtraQueryParts(String initialQuery,
List<IQueryPart> extraParts) {
StringBuilder result = new StringBuilder(initialQuery);
for (IQueryPart each : extraParts) {
result.append(" ").append(each.queryPart());
}
return result.toString();
}
private String withExtraWhereConditions(String initialQuery,
List<IQueryPart> extraParts) {
StringBuilder result = new StringBuilder(initialQuery);
boolean alreadyHasWhere = hasWhere(initialQuery);
if (!alreadyHasWhere) {
result.append(" where ");
}
List<String> conditionsToAdd = notEmptyConditions(extraParts);
for (int i = 0; i < conditionsToAdd.size(); i++) {
if (alreadyHasWhere || i != 0) {
result.append(" and ");
}
result.append(conditionsToAdd.get(i));
}
return result.toString();
}
private List<String> notEmptyConditions(List<IQueryPart> extraParts) {
List<String> result = new ArrayList<String>();
for (IQueryPart each : extraParts) {
String toAdd = each.wherePart();
if (!StringUtils.isEmpty(toAdd)) {
result.add(toAdd);
}
}
return result;
}
private static boolean hasWhere(String initialQuery) {
return wherePattern.matcher(initialQuery).find();
}
private void injectParameters(Query query, List<IQueryPart> extraParts) {
for (IQueryPart each : extraParts) {
each.injectParameters(query);
}
}
}
public interface IQueryPart {
public abstract String queryPart();
public abstract String wherePart();
public abstract void injectParameters(Query query);
}
public static class DatesInterval implements IQueryPart {
private final LocalDate startInclusive;
private final LocalDate endInclusive;
private final String baseAlias;
public DatesInterval(String baseAlias, Date startInclusive,
Date endInclusive) {
this(baseAlias, asLocal(startInclusive), asLocal(endInclusive));
}
private static LocalDate asLocal(Date date) {
if (date == null) {
return null;
}
return LocalDate.fromDateFields(date);
}
public DatesInterval(String baseAlias, LocalDate startInclusive,
LocalDate endInclusive) {
this.baseAlias = baseAlias;
this.startInclusive = startInclusive;
this.endInclusive = endInclusive;
}
@Override
public String queryPart() {
return "";
}
@Override
public String wherePart() {
String result = "";
if (startInclusive != null) {
result += baseAlias + ".endDate.date >= :startInclusive";
}
if (!result.isEmpty() && endInclusive != null) {
result += " and ";
}
if (endInclusive != null) {
result += baseAlias + ".startDate.date <= :endInclusive";
}
return result;
}
@Override
public void injectParameters(Query query) {
if (startInclusive != null) {
query.setParameter("startInclusive", startInclusive);
}
if (endInclusive != null) {
query.setParameter("endInclusive", endInclusive);
}
}
}
}