/*
* Copyright 2012 Red Hat, Inc. and/or its affiliates.
*
* 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.jbpm.services.task.commands;
import org.drools.core.xml.jaxb.util.JaxbMapAdapter;
import org.jbpm.services.task.assignment.AssignmentService;
import org.jbpm.services.task.assignment.AssignmentServiceProvider;
import org.jbpm.services.task.impl.model.xml.JaxbTask;
import org.jbpm.services.task.rule.TaskRuleService;
import org.kie.api.runtime.Context;
import org.kie.api.task.model.Group;
import org.kie.api.task.model.OrganizationalEntity;
import org.kie.api.task.model.Status;
import org.kie.api.task.model.Task;
import org.kie.api.task.model.User;
import org.kie.internal.task.api.TaskDeadlinesService;
import org.kie.internal.task.api.TaskDeadlinesService.DeadlineType;
import org.kie.internal.task.api.model.ContentData;
import org.kie.internal.task.api.model.Deadline;
import org.kie.internal.task.api.model.Deadlines;
import org.kie.internal.task.api.model.InternalPeopleAssignments;
import org.kie.internal.task.api.model.InternalTask;
import org.kie.internal.task.api.model.InternalTaskData;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* Operation.Start : [ new OperationCommand().{ status = [ Status.Ready ],
* allowed = [ Allowed.PotentialOwner ], setNewOwnerToUser = true, newStatus =
* Status.InProgress }, new OperationCommand().{ status = [ Status.Reserved ],
* allowed = [ Allowed.Owner ], newStatus = Status.InProgress } ], *
*/
@XmlRootElement(name="add-task-command")
@XmlAccessorType(XmlAccessType.NONE)
public class AddTaskCommand extends UserGroupCallbackTaskCommand<Long> {
private static final long serialVersionUID = 743368767949233891L;
@XmlElement
private JaxbTask jaxbTask;
@XmlTransient
private Task task;
@XmlJavaTypeAdapter(JaxbMapAdapter.class)
@XmlElement(name="parameter")
private Map<String, Object> params;
// TODO support ContentData marshalling
@XmlTransient // remove and add @XmlElement when done
private ContentData data;
public AddTaskCommand() {
}
public AddTaskCommand(Task task, Map<String, Object> params) {
setTask(task);
this.params = params;
}
public AddTaskCommand(Task task, ContentData data) {
setTask(task);
this.data = data;
}
public Long execute(Context cntxt ) {
Long taskId = null;
TaskContext context = (TaskContext) cntxt;
if (task == null) {
task = jaxbTask;
}
Task taskImpl = null;
if (task instanceof JaxbTask) {
taskImpl = ((JaxbTask) task).getTask();
} else {
taskImpl = task;
}
initializeTask(taskImpl);
context.getTaskRuleService().executeRules(taskImpl, userId, data != null?data:params, TaskRuleService.ADD_TASK_SCOPE);
// use assignment service to directly assign actual owner if enabled
AssignmentService assignmentService = AssignmentServiceProvider.get();
if (assignmentService.isEnabled()) {
assignmentService.assignTask(taskImpl, context);
}
doCallbackOperationForPeopleAssignments((InternalPeopleAssignments) taskImpl.getPeopleAssignments(), context);
doCallbackOperationForTaskData((InternalTaskData) taskImpl.getTaskData(), context);
doCallbackOperationForTaskDeadlines(((InternalTask) taskImpl).getDeadlines(), context);
if (data != null) {
taskId = context.getTaskInstanceService().addTask(taskImpl, data);
} else {
((InternalTaskData)taskImpl.getTaskData()).setTaskInputVariables(params);
taskId = context.getTaskInstanceService().addTask(taskImpl, params);
}
scheduleDeadlinesForTask((InternalTask) taskImpl, context.getTaskDeadlinesService());
return taskId;
}
public JaxbTask getJaxbTask() {
return jaxbTask;
}
public void setJaxbTask(JaxbTask jaxbTask) {
this.jaxbTask = jaxbTask;
}
public Task getTask() {
return task;
}
public void setTask(Task task) {
this.task = task;
if (task instanceof JaxbTask) {
this.jaxbTask = (JaxbTask) task;
} else {
this.jaxbTask = new JaxbTask(task);
}
}
public Map<String, Object> getParams() {
return params;
}
public void setParams(Map<String, Object> params) {
this.params = params;
}
public ContentData getData() {
return data;
}
public void setData(ContentData data) {
this.data = data;
}
private void scheduleDeadlinesForTask(final InternalTask task, TaskDeadlinesService deadlineService) {
final long now = System.currentTimeMillis();
Deadlines deadlines = task.getDeadlines();
if (deadlines != null) {
final List<? extends Deadline> startDeadlines = deadlines.getStartDeadlines();
if (startDeadlines != null) {
scheduleDeadlines(startDeadlines, now, task.getId(), DeadlineType.START, deadlineService);
}
final List<? extends Deadline> endDeadlines = deadlines.getEndDeadlines();
if (endDeadlines != null) {
scheduleDeadlines(endDeadlines, now, task.getId(), DeadlineType.END, deadlineService);
}
}
}
private void scheduleDeadlines(final List<? extends Deadline> deadlines, final long now,
final long taskId, DeadlineType type, TaskDeadlinesService deadlineService) {
for (Deadline deadline : deadlines) {
if (!deadline.isEscalated()) {
// only escalate when true - typically this would only be true
// if the user is requested that the notification should never be escalated
Date date = deadline.getDate();
deadlineService.schedule(taskId, deadline.getId(), date.getTime() - now, type);
}
}
}
private void initializeTask(Task task){
Status assignedStatus = null;
if (task.getPeopleAssignments() != null && task.getPeopleAssignments().getPotentialOwners() != null && task.getPeopleAssignments().getPotentialOwners().size() == 1) {
// if there is a single potential owner, assign and set status to Reserved
OrganizationalEntity potentialOwner = task.getPeopleAssignments().getPotentialOwners().get(0);
// if there is a single potential user owner, assign and set status to Reserved
if (potentialOwner instanceof User) {
((InternalTaskData) task.getTaskData()).setActualOwner((User) potentialOwner);
assignedStatus = Status.Reserved;
}
//If there is a group set as potentialOwners, set the status to Ready ??
if (potentialOwner instanceof Group) {
assignedStatus = Status.Ready;
}
} else if (task.getPeopleAssignments() != null && task.getPeopleAssignments().getPotentialOwners() != null && task.getPeopleAssignments().getPotentialOwners().size() > 1) {
// multiple potential owners, so set to Ready so one can claim.
assignedStatus = Status.Ready;
} else {
//@TODO: we have no potential owners
}
if (assignedStatus != null) {
((InternalTaskData) task.getTaskData()).setStatus(assignedStatus);
}
}
}