package fi.arcusys.koku.intalio;
import static fi.arcusys.koku.util.Constants.DATE_FORMAT;
import static fi.arcusys.koku.util.Constants.TIME_ZONE;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;
import javax.xml.datatype.XMLGregorianCalendar;
import org.apache.log4j.Logger;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import fi.arcusys.intalio.tms.Task.Input;
import fi.arcusys.intalio.tms.TaskMetadata;
import fi.arcusys.koku.exceptions.IntalioAuthException;
import fi.arcusys.koku.util.Properties;
import fi.arcusys.koku.util.TaskUtil;
/**
* Handles the intalio task processing including querying tasks, formatting task
* to be presented to web
* @author Jinhua Chen
* May 9, 2011
*/
public class TaskHandle {
private static final Logger logger = Logger.getLogger(TaskHandle.class);
// TODO: We probably need some sort filter here?
public static final String TASKMGR_REQUESTS_FILTER = "";
private static final String LOCAL_AJAXFORMS_WEB_APP_URL_PART = "/palvelut-portlet/ajaxforms/";
private static final String ADDRESS_REGEX = "http://.+/gi/";
private final TaskManagementService taskMngServ = new TaskManagementService();
private String message;
private String participantToken;
private String username;
/**
* Constructor and initialization
*/
public TaskHandle() {
this.message = "";
this.participantToken = null;
}
/**
* Constructor with intalio participant token and username
*/
public TaskHandle(String token, String username) {
this.participantToken = token;
this.username = username;
}
/**
* Gets available tasks by the given parameters and return task list
* @param taskType the intalio task type
* @param keyword the keyword for searching/filetering
* @param orderType order type of tasks
* @param first the beginning index of the tasks
* @param max the maximum tasks to be queried
* @return available task list
*/
public List<Task> getTasksByParams(int taskType, String keyword,
String orderType, String first, String max) {
String taskTypeStr = TaskUtil.getTaskType(taskType);
String subQuery = "";
subQuery = createTaskSubQuery(taskType, keyword, orderType);
return getTasks(taskTypeStr, subQuery, first, max);
}
/**
* Gets tasks from task management service
* @param taskType the intalio task type
* @param subQuery the sql string for intalio tasks database
* @param first the beginning index of the tasks
* @param max the maximum tasks to be queried
* @return a list of tasks
*/
public List<Task> getTasks(String taskType, String subQuery, String first, String max) {
List<TaskMetadata> tasklist = taskMngServ.getAvailableTasks(participantToken, taskType, subQuery,
first, max);
return createTasks(tasklist, participantToken);
}
public Task getTask(String taskId, String token) {
fi.arcusys.intalio.tms.Task task = taskMngServ.getTask(taskId, token);
return createTask(task.getMetadata(), task.getInput());
}
/**
* Gets task status such as 'READY', 'CLAIMED', 'COMPLETED'
* @param taskId intalio task id
* @return the intalio task status
*/
public String getTaskStatus(String taskId) {
return taskMngServ.getTask(taskId, participantToken).getMetadata().getTaskState();
}
/**
* Creates task model to be shown in portlet from intalio task
* @param tasklist a list of intalio tasks
* @return formatted task list to be presented on web
*/
private List<Task> createTasks(List<TaskMetadata> tasklist, String token) {
List<Task> myTasklist = new ArrayList<Task>();
/* Unfortunately getTasks WS call doesn't contain Input object which includes information
* what we want (like sender name). Only way seems to be call task details and this will generate
* more WS calls (default is 10). =\
*
* Better ideas?
* */
for (TaskMetadata task : tasklist) {
fi.arcusys.intalio.tms.Task taskDetails = taskMngServ.getTask(task.getTaskId(), token);
myTasklist.add(createTask(taskDetails.getMetadata(), taskDetails.getInput()));
}
return myTasklist;
}
private fi.arcusys.koku.intalio.Task createTask(TaskMetadata task, fi.arcusys.intalio.tms.Task.Input input) {
if (task == null) {
return null;
}
fi.arcusys.koku.intalio.Task myTask = new fi.arcusys.koku.intalio.Task();
myTask.setDescription(task.getDescription());
if (task.getTaskState() != null) {
myTask.setState(task.getTaskState().toString());
} else {
myTask.setState("");
}
myTask.setCreationDate(formatTaskDate(task.getCreationDate()));
myTask.setLink(createTaskLink(task));
myTask.setSenderName(getSenderNameFromTaskInput(task, input));
return myTask;
}
/**
* Returns task sender name (if available)
*
* @param task
* @param input
* @return sender name
*/
private String getSenderNameFromTaskInput(TaskMetadata task, Input input) {
final String descriptionName = task.getDescription();
if (descriptionName.startsWith(Properties.RECEIVED_REQUESTS_FILTER)) {
// Uusi pyyntö
return getSenderName(input, "User_SenderDisplay");
} else if (descriptionName.contains(Properties.RECEIVED_INFO_REQUESTS_FILTER)) {
// Uusi tietopyyntö
return getSenderName(input, "Perustiedot_Lahettaja");
} else if (descriptionName.endsWith(Properties.RECEIVED_WARRANTS_FILTER)) {
// Vastaanotetut valtakirjat
return getSenderName(input, "Tiedot_LahettajaDisplay");
} else {
// Hm?
return null;
}
}
private String getSenderName(final fi.arcusys.intalio.tms.Task.Input input, final String nodename) {
if (input == null || input.getAny() == null || input.getAny().isEmpty()) {
return null;
}
final Object object = input.getAny().get(0);
if (!(object instanceof Element)) {
return null;
}
final Element element = ((Element)object);
final NodeList senderNameList = element.getElementsByTagName(nodename);
if (senderNameList == null || senderNameList.getLength() == 0) {
return null;
}
final Node senderNameNode = senderNameList.item(0);
if (senderNameNode.getFirstChild() == null) {
return null;
}
return senderNameNode.getFirstChild().getNodeValue();
}
/**
* Formats the task date with given format and Helsinki timezone
* @param xmlGregorianCalendar
* @return formatted date string
*/
public String formatTaskDate(XMLGregorianCalendar xmlGregorianCalendar) {
Calendar cal = xmlGregorianCalendar.toGregorianCalendar();
SimpleDateFormat dataformat = new SimpleDateFormat(DATE_FORMAT);
dataformat.setTimeZone(TimeZone.getTimeZone(TIME_ZONE));
return dataformat.format(cal.getTime());
}
/**
* Creates form operation link of task
* @param task intalio task object
* @return intalio task form string
*/
public String createTaskLink(TaskMetadata task) {
String link = "";
String taskType = "";
Object[] params = null;
String type = task.getTaskType().toString();
if (type.equals("ACTIVITY")) { // tasks
taskType = TaskUtil.TASK_TYPE;
} else if (type.equals("NOTIFICATION")) { // notifications
taskType = TaskUtil.NOTIFICATION_TYPE;
} else if (type.equals("INIT")) { // processes
taskType = TaskUtil.PROCESS_TYPE;
} else {
taskType = TaskUtil.TASK_TYPE;
}
String url = task.getFormUrl().toString();
url = url.replaceFirst(ADDRESS_REGEX, LOCAL_AJAXFORMS_WEB_APP_URL_PART);
try {
params = new Object[] { url, task.getTaskId(), taskType, URLEncoder.encode(url, "UTF-8"), participantToken,
URLEncoder.encode(username, "UTF-8"), false };
} catch (UnsupportedEncodingException e) {
logger.error("Unsupported Encoding Exception");
}
link = MessageFormat.format("{0}?id={1}&type={2}&url={3}&token={4}&user={5}&claimTaskOnOpen={6}", params);
return link;
}
/**
* Gets total tasks number
* @param taskType the intalio task type
* @param subQuery the sql string for intalio tasks database
* @return total number of total tasks
*/
public int getTotalTasksNumber(int taskType, String keyword) {
int totalNum = 0;
String subQuery;
String totalNumStr;
String taskTypeStr;
taskTypeStr = TaskUtil.getTaskType(taskType);
subQuery = createTotalNumSubQuery(taskType, keyword);
totalNumStr = taskMngServ.getTotalTasksNumber(participantToken, taskTypeStr, subQuery);
totalNum = Integer.parseInt(totalNumStr);
return totalNum;
}
public int getTasksTotalNumber(final String keywordFilter) {
final String filter = (keywordFilter != null) ? keywordFilter : "";
return Integer.valueOf(taskMngServ.getTotalTasksNumber(participantToken, TaskUtil.TASK_TYPE, createTotalNumSubQuery(TaskUtil.TASK, filter)));
}
public int getRequestsTasksTotalNumber() {
return getTasksTotalNumber("");
// return Integer.valueOf(taskMngServ.getTotalTasksNumber(participantToken, TaskUtil.TASK_TYPE, createTotalNumSubQuery(TaskUtil.TASK, TASKMGR_REQUESTS_FILTER)));
}
/**
* Creates subquery to get total number of tasks
* @param taskType the intalio task type
* @param keyword the keyword for searching/filetering
* @return subquery the sql string for intalio tasks database
*/
public String createTotalNumSubQuery(int taskType, String keyword) {
String subQuery;
switch (taskType) {
case TaskUtil.TASK:
subQuery = "(T._state = TaskState.READY OR T._state = TaskState.CLAIMED)" + " AND T._description like '%" + keyword + "%'";
break;
case TaskUtil.NOTIFICATION:
subQuery = "T._state = TaskState.READY" + " AND T._description like '%" + keyword + "%'";
break;
case TaskUtil.PROCESS:
subQuery = "T._description like '%" + keyword + "%'";;
break;
default:
subQuery = "";
break;
}
return subQuery;
}
/**
* Creates subquery to get available tasks
* @param taskType the intalio task type
* @param keyword the keyword for searching/filetering
* @param orderType order type of tasks
* @return query string for intalio database
*/
public String createTaskSubQuery(int taskType, String keyword, String orderType) {
String subQuery;
String orderTypeStr = getOrderTypeStr(orderType);
switch (taskType) {
case TaskUtil.TASK:
subQuery = "(T._state = TaskState.READY OR T._state = TaskState.CLAIMED)"
+ " AND T._description like '%" + keyword + "%'"
+ " ORDER BY " + orderTypeStr;
break;
case TaskUtil.NOTIFICATION:
subQuery = "T._state = TaskState.READY"
+ " AND T._description like '%" + keyword + "%'"
+ " ORDER BY " + orderTypeStr;
break;
case TaskUtil.PROCESS:
subQuery = "T._description like '%" + keyword + "%'"
+ " ORDER BY " + orderTypeStr;
break;
default:
subQuery = "";
break;
}
return subQuery;
}
/**
* Gets query order type according to order string from jsp page
* @param orderType order type of tasks
* @return order type query for intalio tasks
*/
public String getOrderTypeStr(String orderType) {
String orderTypeStr;
if(orderType.equals("description_desc")) {
orderTypeStr = "T._description DESC";
}else if(orderType.equals("description_asc")) {
orderTypeStr = "T._description ASC";
}else if(orderType.equals("state_desc")) {
orderTypeStr = "T._state DESC";
}else if(orderType.equals("state_asc")) {
orderTypeStr = "T._state ASC";
}else if(orderType.equals("creationDate_desc")) {
orderTypeStr = "T._creationDate DESC";
}else if(orderType.equals("creationDate_asc")) {
orderTypeStr = "T._creationDate ASC";
}else {
orderTypeStr = "T._creationDate DESC";
}
return orderTypeStr;
}
/**
* Gets token authenticated by username and password
* @param username username of intalio user
* @param password password of intalio user
* @return intalio participant token
*/
public String getTokenByUser(String username, String password) throws IntalioAuthException {
String token = null;
token = taskMngServ.getParticipantToken(username, password);
return token;
}
/**
* Gets participant token
* @return intalio participant token
*/
public String getToken() {
return participantToken;
}
/**
* Sets participant token
* @param token intalio participant token
*/
public void setToken(String token) {
this.participantToken = token;
}
/**
* Shows handling message e.g. error message
* @return message log
*/
public String getMessage() {
return message;
}
}