Java tutorial
/* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.activiti.engine.impl.bpmn.behavior; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; import net.emforge.activiti.WorkflowUtil; import org.activiti.engine.ActivitiException; import org.activiti.engine.ActivitiIllegalArgumentException; import org.activiti.engine.delegate.Expression; import org.activiti.engine.delegate.TaskListener; import org.activiti.engine.identity.User; import org.activiti.engine.impl.calendar.DueDateBusinessCalendar; import org.activiti.engine.impl.identity.Authentication; import org.activiti.engine.impl.persistence.entity.TaskEntity; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.activiti.engine.impl.task.TaskDefinition; import org.activiti.rest.api.ActivitiUtil; import org.apache.commons.lang.ArrayUtils; import com.liferay.portal.kernel.json.JSONFactoryUtil; import com.liferay.portal.kernel.json.JSONObject; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.notifications.ChannelException; import com.liferay.portal.kernel.notifications.ChannelHubManagerUtil; import com.liferay.portal.kernel.notifications.NotificationEvent; import com.liferay.portal.kernel.notifications.NotificationEventFactoryUtil; import com.liferay.portal.kernel.util.StringPool; import com.liferay.portal.kernel.workflow.WorkflowTaskManagerUtil; /** * activity implementation for the user task. * * @author Joram Barrez */ public class UserTaskActivityBehavior extends TaskActivityBehavior { private static Log _log = LogFactoryUtil.getLog(UserTaskActivityBehavior.class); private static final String WORKFLOW_TASKS_PORTLET_ID = "150"; private static final String SO_PORTLET_ID = "6_WAR_soportlet"; protected TaskDefinition taskDefinition; public UserTaskActivityBehavior(TaskDefinition taskDefinition) { this.taskDefinition = taskDefinition; } public void execute(ActivityExecution execution) throws Exception { TaskEntity task = TaskEntity.createAndInsert(execution); task.setExecution(execution); task.setTaskDefinition(taskDefinition); if (taskDefinition.getNameExpression() != null) { String name = (String) taskDefinition.getNameExpression().getValue(execution); task.setName(name); } if (taskDefinition.getDescriptionExpression() != null) { String description = (String) taskDefinition.getDescriptionExpression().getValue(execution); task.setDescription(description); } if (taskDefinition.getDueDateExpression() != null) { Object dueDate = taskDefinition.getDueDateExpression().getValue(execution); if (dueDate != null) { if (dueDate instanceof Date) { task.setDueDate((Date) dueDate); } else if (dueDate instanceof String) { task.setDueDate(new DueDateBusinessCalendar().resolveDuedate((String) dueDate)); } else { throw new ActivitiIllegalArgumentException( "Due date expression does not resolve to a Date or Date string: " + taskDefinition.getDueDateExpression().getExpressionText()); } } } if (taskDefinition.getPriorityExpression() != null) { final Object priority = taskDefinition.getPriorityExpression().getValue(execution); if (priority != null) { if (priority instanceof String) { try { task.setPriority(Integer.valueOf((String) priority)); } catch (NumberFormatException e) { throw new ActivitiIllegalArgumentException( "Priority does not resolve to a number: " + priority, e); } } else if (priority instanceof Number) { task.setPriority(((Number) priority).intValue()); } else { throw new ActivitiIllegalArgumentException("Priority expression does not resolve to a number: " + taskDefinition.getPriorityExpression().getExpressionText()); } } } handleAssignments(task, execution); // All properties set, now firing 'create' event task.fireEvent(TaskListener.EVENTNAME_CREATE); } public void signal(ActivityExecution execution, String signalName, Object signalData) throws Exception { leave(execution); } @SuppressWarnings({ "unchecked", "rawtypes" }) protected void handleAssignments(TaskEntity task, ActivityExecution execution) { // to send SO notification we need to extract workflow context, get // users to send to.. Map<String, Object> workflowContext = ActivitiUtil.getRuntimeService().getVariables(execution.getId()); _log.debug("User task for companyId = " + (String) workflowContext.get("companyId")); long companyId = Long.valueOf((String) workflowContext.get("companyId")); if (taskDefinition.getAssigneeExpression() != null) { String userId = (String) taskDefinition.getAssigneeExpression().getValue(execution); task.setAssignee(userId); try { List<Long> receiverUserIds = new ArrayList<Long>(); receiverUserIds.add(Long.valueOf(userId)); sendPortalNotification(task, receiverUserIds, workflowContext, false); } catch (ChannelException e) { _log.error("Could not send portal notification to user", e); } } if (!taskDefinition.getCandidateGroupIdExpressions().isEmpty()) { List<User> users = new ArrayList<User>(); for (Expression groupIdExpr : taskDefinition.getCandidateGroupIdExpressions()) { Object value = groupIdExpr.getValue(execution); if (value instanceof String) { List<String> candiates = extractCandidates((String) value); task.addCandidateGroups(candiates); users.addAll(resolveUsersForGroups(companyId, candiates)); } else if (value instanceof Collection) { task.addCandidateGroups((Collection) value); users.addAll(resolveUsersForGroups(companyId, (Collection) value)); } else { throw new ActivitiIllegalArgumentException( "Expression did not resolve to a string or collection of strings"); } } try { long[] pooledActorsIds = WorkflowTaskManagerUtil.getPooledActorsIds(companyId, Long.valueOf(task.getId())); List<Long> receiverUserIds = null; if (pooledActorsIds == null || pooledActorsIds.length == 0) { //try to use users list receiverUserIds = new ArrayList<Long>(users.size()); for (User user : users) { receiverUserIds.add(Long.valueOf(user.getId())); } } else { receiverUserIds = new ArrayList<Long>(Arrays.asList(ArrayUtils.toObject(pooledActorsIds))); } try { sendPortalNotification(task, receiverUserIds, workflowContext, true); } catch (ChannelException e) { _log.error("Could not send portal notification to group", e); } } catch (Exception e) { _log.error("Could not send portal notification to group", e); } } if (!taskDefinition.getCandidateUserIdExpressions().isEmpty()) { for (Expression userIdExpr : taskDefinition.getCandidateUserIdExpressions()) { Object value = userIdExpr.getValue(execution); if (value instanceof String) { List<String> candiates = extractCandidates((String) value); task.addCandidateUsers(candiates); } else if (value instanceof Collection) { task.addCandidateUsers((Collection) value); } else { throw new ActivitiException("Expression did not resolve to a string or collection of strings"); } } } } private List<User> resolveUsersForGroups(long companyId, Collection groupNames) { List<User> users = new ArrayList<User>(); for (Object name : groupNames) { String groupName = (String) name; users.addAll(WorkflowUtil.findUsersByGroup(companyId, groupName)); } return users; } protected void sendPortalNotification(TaskEntity task, List<Long> receiverUserIds, Map<String, Object> workflowContext, boolean isGroup) throws ChannelException { String currentUserId = Authentication.getAuthenticatedUserId(); JSONObject notificationEventJSONObject = JSONFactoryUtil.createJSONObject(); long companyId = Long.valueOf((String) workflowContext.get("companyId")); notificationEventJSONObject.put("body", task.getName()); notificationEventJSONObject.put("groupId", (String) workflowContext.get("groupId")); notificationEventJSONObject.put("entryClassName", (String) workflowContext.get("entryClassName")); notificationEventJSONObject.put("entryId", (String) workflowContext.get("entryClassPK")); // workflow tasks portlet id notificationEventJSONObject.put("portletId", WORKFLOW_TASKS_PORTLET_ID); notificationEventJSONObject.put("userId", currentUserId); notificationEventJSONObject.put("taskId", task.getId()); notificationEventJSONObject.put("taskName", task.getName()); notificationEventJSONObject.put("isGroup", isGroup); String title = StringPool.BLANK; if (isGroup) { title = "New workflow task \"" + task.getName() + "\" has been assigned to your role"; } else { title = "New workflow task \"" + task.getName() + "\" has been assigned to you"; } // FIXME localize notifications for (Long receiverUserId : receiverUserIds) { if (receiverUserId.toString().equals(currentUserId)) { // do not send notification in case action was performed by same user _log.debug( "User " + receiverUserId + " skipped from sending notification since it is current user"); continue; } _log.debug("Before sending notification receiverUserId = " + receiverUserId); notificationEventJSONObject.put("title", title); NotificationEvent notificationEvent = NotificationEventFactoryUtil.createNotificationEvent( System.currentTimeMillis(), SO_PORTLET_ID, notificationEventJSONObject); notificationEvent.setDeliveryRequired(0); ChannelHubManagerUtil.sendNotificationEvent(companyId, receiverUserId, notificationEvent); _log.debug("Notification for receiverUserId = " + receiverUserId + " sent"); } } /** * Extract a candidate list from a string. * * @param str * @return */ protected List<String> extractCandidates(String str) { return Arrays.asList(str.split("[\\s]*,[\\s]*")); } // getters and setters ////////////////////////////////////////////////////// public TaskDefinition getTaskDefinition() { return taskDefinition; } }