Skip to content

Commit

Permalink
Implementing ACT-2089 : Task sorting on due date needs to place those…
Browse files Browse the repository at this point in the history
… with due date null after those with a duedate

Note that this is implemented in a generic way. If other queries would benefit from nulls first/last it could easily be added now.
  • Loading branch information
jbarrez committed Sep 1, 2014
1 parent 40c4800 commit 424f373
Show file tree
Hide file tree
Showing 9 changed files with 342 additions and 35 deletions.
Expand Up @@ -17,6 +17,7 @@

import org.activiti.engine.ActivitiException;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.db.ListQueryParameterObject;
import org.activiti.engine.impl.interceptor.Command;
Expand All @@ -41,15 +42,25 @@ public abstract class AbstractQuery<T extends Query<?,?>, U> extends ListQueryPa
private static enum ResultType {
LIST, LIST_PAGE, SINGLE_RESULT, COUNT
}


protected transient CommandExecutor commandExecutor;
protected transient CommandContext commandContext;

protected String databaseType;

protected String orderBy;

protected ResultType resultType;

protected QueryProperty orderProperty;


public static enum NullHandlingOnOrder {
NULLS_FIRST, NULLS_LAST
}

protected NullHandlingOnOrder nullHandlingOnOrder;

protected AbstractQuery() {
parameter = this;
}
Expand All @@ -72,6 +83,13 @@ public T orderBy(QueryProperty property) {
this.orderProperty = property;
return (T) this;
}

@SuppressWarnings("unchecked")
public T orderBy(QueryProperty property, NullHandlingOnOrder nullHandlingOnOrder) {
orderBy(property);
this.nullHandlingOnOrder = nullHandlingOnOrder;
return (T) this;
}

public T asc() {
return direction(Direction.ASCENDING);
Expand All @@ -86,8 +104,9 @@ public T direction(Direction direction) {
if (orderProperty==null) {
throw new ActivitiIllegalArgumentException("You should call any of the orderBy methods first before specifying a direction");
}
addOrder(orderProperty.getName(), direction.getName());
addOrder(orderProperty.getName(), direction.getName(), nullHandlingOnOrder);
orderProperty = null;
nullHandlingOnOrder = null;
return (T) this;
}

Expand Down Expand Up @@ -164,13 +183,55 @@ public U executeSingleResult(CommandContext commandContext) {
return null;
}

protected void addOrder(String column, String sortOrder) {
if (orderBy==null) {
protected void addOrder(String column, String sortOrder, NullHandlingOnOrder nullHandlingOnOrder) {

if (orderBy==null) {
orderBy = "";
} else {
orderBy = orderBy+", ";
}
orderBy = orderBy+column+" "+sortOrder;

String defaultOrderByClause = column + " "+sortOrder;

if (nullHandlingOnOrder != null) {

if (nullHandlingOnOrder.equals(NullHandlingOnOrder.NULLS_FIRST)) {

if (ProcessEngineConfigurationImpl.DATABASE_TYPE_H2.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_POSTGRES.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_ORACLE.equals(databaseType)) {
orderBy = orderBy + defaultOrderByClause + " NULLS FIRST";
} else if (ProcessEngineConfigurationImpl.DATABASE_TYPE_MYSQL.equals(databaseType)) {
orderBy = orderBy + "isnull(" + column +") desc," + defaultOrderByClause;
} else if (ProcessEngineConfigurationImpl.DATABASE_TYPE_DB2.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_MSSQL.equals(databaseType)) {
orderBy = orderBy + "case when " + column + " is null then 1 else 0 end," + defaultOrderByClause;
} else {
orderBy = orderBy + defaultOrderByClause;
}


} else if (nullHandlingOnOrder.equals(NullHandlingOnOrder.NULLS_LAST)) {

if (ProcessEngineConfigurationImpl.DATABASE_TYPE_H2.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_POSTGRES.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_ORACLE.equals(databaseType)) {
orderBy = orderBy + column + " "+sortOrder + " NULLS LAST";
} else if (ProcessEngineConfigurationImpl.DATABASE_TYPE_MYSQL.equals(databaseType)) {
orderBy = orderBy + "order by isnull(" + column +") asc," + defaultOrderByClause;
} else if (ProcessEngineConfigurationImpl.DATABASE_TYPE_DB2.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_MSSQL.equals(databaseType)) {
orderBy = orderBy + "case when " + column + " is null then 0 else 1 end," + defaultOrderByClause;
} else {
orderBy = orderBy + defaultOrderByClause;
}

}

} else {
orderBy = orderBy + defaultOrderByClause;
}

}

public String getOrderBy() {
Expand All @@ -180,4 +241,13 @@ public String getOrderBy() {
return orderBy;
}
}

public String getDatabaseType() {
return databaseType;
}

public void setDatabaseType(String databaseType) {
this.databaseType = databaseType;
}

}
Expand Up @@ -12,14 +12,26 @@
*/
package org.activiti.engine.impl;

import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.interceptor.CommandExecutor;



/**
* @author Tom Baeyens
* @author Joram Barrez
*/
public class ServiceImpl {

protected ProcessEngineConfigurationImpl processEngineConfiguration;

public ServiceImpl() {

}

public ServiceImpl(ProcessEngineConfigurationImpl processEngineConfiguration) {
this.processEngineConfiguration = processEngineConfiguration;
}

protected CommandExecutor commandExecutor;

Expand Down
Expand Up @@ -37,6 +37,7 @@
public class TaskQueryImpl extends AbstractVariableQueryImpl<TaskQuery, Task> implements TaskQuery {

private static final long serialVersionUID = 1L;

protected String taskId;
protected String name;
protected String nameLike;
Expand Down Expand Up @@ -87,7 +88,7 @@ public class TaskQueryImpl extends AbstractVariableQueryImpl<TaskQuery, Task> im
protected boolean bothCandidateAndAssigned = false;
protected boolean orActive;
protected TaskQueryImpl orQueryObject;

public TaskQueryImpl() {
}

Expand All @@ -98,7 +99,12 @@ public TaskQueryImpl(CommandContext commandContext) {
public TaskQueryImpl(CommandExecutor commandExecutor) {
super(commandExecutor);
}


public TaskQueryImpl(CommandExecutor commandExecutor, String databaseType) {
super(commandExecutor);
this.databaseType = databaseType;
}

public TaskQueryImpl taskId(String taskId) {
if (taskId == null) {
throw new ActivitiIllegalArgumentException("Task id is null");
Expand Down Expand Up @@ -908,6 +914,15 @@ public TaskQuery orderByDueDate() {
return orderBy(TaskQueryProperty.DUE_DATE);
}

public TaskQuery orderByDueDateNullsFirst() {
return orderBy(TaskQueryProperty.DUE_DATE, NullHandlingOnOrder.NULLS_FIRST);
}

@Override
public TaskQuery orderByDueDateNullsLast() {
return orderBy(TaskQueryProperty.DUE_DATE, NullHandlingOnOrder.NULLS_LAST);
}

@Override
public TaskQuery orderByTenantId() {
return orderBy(TaskQueryProperty.TENANT_ID);
Expand Down
Expand Up @@ -22,6 +22,7 @@

import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.cmd.AddCommentCmd;
import org.activiti.engine.impl.cmd.AddIdentityLinkCmd;
import org.activiti.engine.impl.cmd.ClaimTaskCmd;
Expand Down Expand Up @@ -71,6 +72,14 @@
* @author Joram Barrez
*/
public class TaskServiceImpl extends ServiceImpl implements TaskService {

public TaskServiceImpl() {

}

public TaskServiceImpl(ProcessEngineConfigurationImpl processEngineConfiguration) {
super(processEngineConfiguration);
}

public Task newTask() {
return newTask(null);
Expand Down Expand Up @@ -195,7 +204,7 @@ public void setDueDate(String taskId, Date dueDate) {
}

public TaskQuery createTaskQuery() {
return new TaskQueryImpl(commandExecutor);
return new TaskQueryImpl(commandExecutor, processEngineConfiguration.getDatabaseType());
}

public NativeTaskQuery createNativeTaskQuery() {
Expand Down
Expand Up @@ -248,7 +248,7 @@ public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfig
protected RuntimeService runtimeService = new RuntimeServiceImpl();
protected HistoryService historyService = new HistoryServiceImpl();
protected IdentityService identityService = new IdentityServiceImpl();
protected TaskService taskService = new TaskServiceImpl();
protected TaskService taskService = new TaskServiceImpl(this);
protected FormService formService = new FormServiceImpl();
protected ManagementService managementService = new ManagementServiceImpl();

Expand Down Expand Up @@ -591,34 +591,41 @@ protected void initDataSource() {
}

protected static Properties databaseTypeMappings = getDefaultDatabaseTypeMappings();

public static final String DATABASE_TYPE_H2 = "h2";
public static final String DATABASE_TYPE_MYSQL = "mysql";
public static final String DATABASE_TYPE_ORACLE = "oracle";
public static final String DATABASE_TYPE_POSTGRES = "postgres";
public static final String DATABASE_TYPE_MSSQL = "mssql";
public static final String DATABASE_TYPE_DB2 = "db2";

protected static Properties getDefaultDatabaseTypeMappings() {
Properties databaseTypeMappings = new Properties();
databaseTypeMappings.setProperty("H2","h2");
databaseTypeMappings.setProperty("MySQL","mysql");
databaseTypeMappings.setProperty("Oracle","oracle");
databaseTypeMappings.setProperty("PostgreSQL","postgres");
databaseTypeMappings.setProperty("Microsoft SQL Server","mssql");
databaseTypeMappings.setProperty("DB2","db2");
databaseTypeMappings.setProperty("DB2","db2");
databaseTypeMappings.setProperty("DB2/NT","db2");
databaseTypeMappings.setProperty("DB2/NT64","db2");
databaseTypeMappings.setProperty("DB2 UDP","db2");
databaseTypeMappings.setProperty("DB2/LINUX","db2");
databaseTypeMappings.setProperty("DB2/LINUX390","db2");
databaseTypeMappings.setProperty("DB2/LINUXX8664","db2");
databaseTypeMappings.setProperty("DB2/LINUXZ64","db2");
databaseTypeMappings.setProperty("DB2/400 SQL","db2");
databaseTypeMappings.setProperty("DB2/6000","db2");
databaseTypeMappings.setProperty("DB2 UDB iSeries","db2");
databaseTypeMappings.setProperty("DB2/AIX64","db2");
databaseTypeMappings.setProperty("DB2/HPUX","db2");
databaseTypeMappings.setProperty("DB2/HP64","db2");
databaseTypeMappings.setProperty("DB2/SUN","db2");
databaseTypeMappings.setProperty("DB2/SUN64","db2");
databaseTypeMappings.setProperty("DB2/PTX","db2");
databaseTypeMappings.setProperty("DB2/2","db2");
databaseTypeMappings.setProperty("DB2 UDB AS400", "db2");
databaseTypeMappings.setProperty("H2", DATABASE_TYPE_H2);
databaseTypeMappings.setProperty("MySQL", DATABASE_TYPE_MYSQL);
databaseTypeMappings.setProperty("Oracle", DATABASE_TYPE_ORACLE);
databaseTypeMappings.setProperty("PostgreSQL", DATABASE_TYPE_POSTGRES);
databaseTypeMappings.setProperty("Microsoft SQL Server", DATABASE_TYPE_MSSQL);
databaseTypeMappings.setProperty(DATABASE_TYPE_DB2,DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty(DATABASE_TYPE_DB2,DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/NT",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/NT64",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2 UDP",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUX",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUX390",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXX8664",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXZ64",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/400 SQL",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/6000",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2 UDB iSeries",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/AIX64",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/HPUX",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/HP64",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/SUN",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/SUN64",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/PTX",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/2",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2 UDB AS400", DATABASE_TYPE_DB2);
return databaseTypeMappings;
}

Expand Down
Expand Up @@ -453,9 +453,24 @@ public interface TaskQuery extends Query<TaskQuery, Task>{
/** Order by execution id (needs to be followed by {@link #asc()} or {@link #desc()}). */
TaskQuery orderByExecutionId();

/** Order by due date (needs to be followed by {@link #asc()} or {@link #desc()}). */
/**
* Order by due date (needs to be followed by {@link #asc()} or {@link #desc()}).
* This will use the default handling of null values of the used database.
*/
TaskQuery orderByDueDate();

/**
* Order by due date (needs to be followed by {@link #asc()} or {@link #desc()}).
* If any of the tasks have null for the due date, these will be first in the result.
*/
TaskQuery orderByDueDateNullsFirst();

/**
* Order by due date (needs to be followed by {@link #asc()} or {@link #desc()}).
* If any of the tasks have null for the due date, these will be last in the result.
*/
TaskQuery orderByDueDateNullsLast();

/** Order by tenant id (needs to be followed by {@link #asc()} or {@link #desc()}). */
TaskQuery orderByTenantId();
}

0 comments on commit 424f373

Please sign in to comment.