001/* 002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * ldoguin, Antoine Taillefer 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.ecm.platform.task.core.service; 023 024import java.io.Serializable; 025import java.util.ArrayList; 026import java.util.Date; 027import java.util.HashMap; 028import java.util.List; 029import java.util.Map; 030 031import org.apache.commons.lang.StringUtils; 032import org.nuxeo.common.utils.Path; 033import org.nuxeo.ecm.core.api.CoreSession; 034import org.nuxeo.ecm.core.api.DocumentModel; 035import org.nuxeo.ecm.core.api.DocumentModelList; 036import org.nuxeo.ecm.core.api.DocumentNotFoundException; 037import org.nuxeo.ecm.core.api.DocumentRef; 038import org.nuxeo.ecm.core.api.IdRef; 039import org.nuxeo.ecm.core.api.NuxeoException; 040import org.nuxeo.ecm.core.api.NuxeoGroup; 041import org.nuxeo.ecm.core.api.NuxeoPrincipal; 042import org.nuxeo.ecm.core.api.PathRef; 043import org.nuxeo.ecm.core.api.SortInfo; 044import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner; 045import org.nuxeo.ecm.core.api.security.ACE; 046import org.nuxeo.ecm.core.api.security.ACL; 047import org.nuxeo.ecm.core.api.security.ACP; 048import org.nuxeo.ecm.core.api.security.SecurityConstants; 049import org.nuxeo.ecm.platform.ec.notification.NotificationConstants; 050import org.nuxeo.ecm.platform.task.Task; 051import org.nuxeo.ecm.platform.task.TaskConstants; 052import org.nuxeo.ecm.platform.task.TaskEventNames; 053import org.nuxeo.ecm.platform.task.TaskPersisterDescriptor; 054import org.nuxeo.ecm.platform.task.TaskProvider; 055import org.nuxeo.ecm.platform.task.TaskProviderDescriptor; 056import org.nuxeo.ecm.platform.task.TaskService; 057import org.nuxeo.runtime.model.ComponentContext; 058import org.nuxeo.runtime.model.ComponentInstance; 059import org.nuxeo.runtime.model.ComponentName; 060import org.nuxeo.runtime.model.DefaultComponent; 061 062/** 063 * @author <a href="mailto:ldoguin@nuxeo.com">Laurent Doguin</a> 064 * @since 5.5 065 */ 066public class TaskServiceImpl extends DefaultComponent implements TaskService { 067 068 private static final long serialVersionUID = 1L; 069 070 public static final ComponentName NAME = new ComponentName("org.nuxeo.ecm.platform.task.core.TaskService"); 071 072 public static final String DEFAULT_TASK_PROVIDER = "documentTaskProvider"; 073 074 private static final String TASK_PROVIDER_XP = "taskProvider"; 075 076 private static final String TASK_PERSISTER_XP = "taskPersister"; 077 078 private Map<String, TaskProvider> tasksProviders; 079 080 private String parentPath = "/task-root"; 081 082 @Override 083 public void activate(ComponentContext context) { 084 super.activate(context); 085 tasksProviders = new HashMap<>(); 086 } 087 088 @Override 089 public void deactivate(ComponentContext context) { 090 super.deactivate(context); 091 tasksProviders = null; 092 } 093 094 @Override 095 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 096 if (extensionPoint.equals(TASK_PROVIDER_XP)) { 097 if (contribution instanceof TaskProviderDescriptor) { 098 TaskProviderDescriptor taskProviderDescriptor = (TaskProviderDescriptor) contribution; 099 String providerId = taskProviderDescriptor.getId(); 100 if (taskProviderDescriptor.isEnabled()) { 101 tasksProviders.put(providerId, taskProviderDescriptor.getNewInstance()); 102 } else { 103 if (tasksProviders.get(providerId) != null) { 104 tasksProviders.remove(providerId); 105 } 106 } 107 } 108 } else if (extensionPoint.equals(TASK_PERSISTER_XP)) { 109 if (contribution instanceof TaskPersisterDescriptor) { 110 TaskPersisterDescriptor taskPersisterDescriptor = (TaskPersisterDescriptor) contribution; 111 parentPath = taskPersisterDescriptor.getPath(); 112 } 113 } 114 } 115 116 @Override 117 public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 118 if (extensionPoint.equals(TASK_PROVIDER_XP)) { 119 if (contribution instanceof TaskProviderDescriptor) { 120 TaskProviderDescriptor taskProviderDescriptor = (TaskProviderDescriptor) contribution; 121 String providerId = taskProviderDescriptor.getId(); 122 if (tasksProviders.get(providerId) != null) { 123 tasksProviders.remove(providerId); 124 } 125 } 126 } 127 } 128 129 @Override 130 public List<Task> createTask(CoreSession coreSession, NuxeoPrincipal principal, DocumentModel document, 131 String taskName, List<String> actorIds, boolean createOneTaskPerActor, String directive, String comment, 132 Date dueDate, Map<String, String> taskVariables, String parentPath) { 133 return createTask(coreSession, principal, document, taskName, null, null, actorIds, createOneTaskPerActor, 134 directive, comment, dueDate, taskVariables, parentPath); 135 } 136 137 /** 138 * @since 5.6 139 */ 140 @Override 141 public List<Task> createTask(CoreSession coreSession, NuxeoPrincipal principal, DocumentModel document, 142 String taskDocumentType, String taskName, String taskType, String processId, List<String> actorIds, 143 boolean createOneTaskPerActor, String directive, String comment, Date dueDate, 144 Map<String, String> taskVariables, String parentPath, Map<String, Serializable> eventInfo) { 145 List<DocumentModel> docs = new ArrayList<>(); 146 docs.add(document); 147 return createTaskForProcess(coreSession, principal, docs, taskDocumentType, taskName, taskType, processId, 148 null, actorIds, createOneTaskPerActor, directive, comment, dueDate, taskVariables, parentPath, 149 eventInfo); 150 } 151 152 /** 153 * @since 5.6 154 */ 155 @Override 156 public List<Task> createTask(CoreSession coreSession, NuxeoPrincipal principal, DocumentModel document, 157 String taskName, String taskType, String processId, List<String> prefixedActorIds, 158 boolean createOneTaskPerActor, String directive, String comment, Date dueDate, 159 Map<String, String> taskVariables, String parentPath) { 160 return createTask(coreSession, principal, document, TaskConstants.TASK_TYPE_NAME, taskName, taskType, 161 processId, prefixedActorIds, createOneTaskPerActor, directive, comment, dueDate, taskVariables, 162 parentPath, null); 163 } 164 165 @Override 166 public String acceptTask(CoreSession coreSession, NuxeoPrincipal principal, Task task, String comment) { 167 return endTask(coreSession, principal, task, comment, TaskEventNames.WORKFLOW_TASK_COMPLETED, true); 168 } 169 170 @Override 171 public String rejectTask(CoreSession coreSession, NuxeoPrincipal principal, Task task, String comment) { 172 return endTask(coreSession, principal, task, comment, TaskEventNames.WORKFLOW_TASK_REJECTED, false); 173 } 174 175 /** 176 * Use the task provider held by the {@link Task#TASK_PROVIDER_KEY} task variable to end the {@code task}. If null 177 * use the {@link #DEFAULT_TASK_PROVIDER}. 178 */ 179 @Override 180 public String endTask(CoreSession coreSession, NuxeoPrincipal principal, Task task, String comment, 181 String eventName, boolean isValidated) { 182 183 if (!canEndTask(principal, task)) { 184 throw new NuxeoException(String.format("User with id '%s' cannot end this task", principal.getName())); 185 } 186 String taskProviderId = task.getVariable(Task.TASK_PROVIDER_KEY); 187 if (taskProviderId == null) { 188 taskProviderId = DEFAULT_TASK_PROVIDER; 189 } 190 TaskProvider taskProvider = tasksProviders.get(taskProviderId); 191 if (taskProvider == null) { 192 throw new NuxeoException( 193 String.format( 194 "No task provider registered, cannot end task. Please contribute at least the default task provider: %s.", 195 DEFAULT_TASK_PROVIDER)); 196 } 197 return taskProvider.endTask(coreSession, principal, task, comment, eventName, isValidated); 198 } 199 200 @Override 201 public boolean canEndTask(NuxeoPrincipal principal, Task task) { 202 if (task != null && (!task.isCancelled() && !task.hasEnded())) { 203 return principal.isAdministrator() || principal.getName().equals(task.getInitiator()) 204 || isTaskAssignedToUser(task, principal, true); 205 } 206 return false; 207 } 208 209 protected boolean isTaskAssignedToUser(Task task, NuxeoPrincipal user, boolean checkDelegatedActors) { 210 if (task != null && user != null) { 211 // user actors 212 List<String> actors = user.getAllGroups(); 213 actors.add(user.getName()); 214 215 // initiator 216 if (actors.contains(task.getInitiator())) { 217 return true; 218 } 219 // users 220 List<String> users = task.getActors(); 221 if (checkDelegatedActors) { 222 users.addAll(task.getDelegatedActors()); 223 } 224 if (users != null) { 225 for (String userName : users) { 226 if (userName.startsWith(NuxeoPrincipal.PREFIX)) { 227 if (actors.contains(userName.substring(NuxeoPrincipal.PREFIX.length()))) { 228 return true; 229 } 230 } else if (userName.startsWith(NuxeoGroup.PREFIX)) { 231 if (actors.contains(userName.substring(NuxeoGroup.PREFIX.length()))) { 232 return true; 233 } 234 } else if(actors.contains(userName)) { 235 return true; 236 } 237 } 238 } 239 } 240 return false; 241 } 242 243 @Override 244 public Task getTask(CoreSession coreSession, String taskId) { 245 DocumentRef docRef = new IdRef(taskId); 246 DocumentModel taskDoc = coreSession.getDocument(docRef); 247 if (taskDoc != null) { 248 Task task = taskDoc.getAdapter(Task.class); 249 if (task != null) { 250 return task; 251 } 252 } 253 return null; 254 } 255 256 @Override 257 public void deleteTask(CoreSession coreSession, String taskId) { 258 final DocumentRef docRef = new IdRef(taskId); 259 UnrestrictedSessionRunner runner = new UnrestrictedSessionRunner(coreSession) { 260 @Override 261 public void run() { 262 session.removeDocument(docRef); 263 } 264 }; 265 runner.runUnrestricted(); 266 } 267 268 @Override 269 public DocumentModel getTargetDocumentModel(Task task, CoreSession coreSession) { 270 try { 271 return coreSession.getDocument(new IdRef(task.getTargetDocumentId())); 272 } catch (DocumentNotFoundException e) { 273 return null; 274 } 275 } 276 277 @Override 278 public List<Task> getCurrentTaskInstances(CoreSession coreSession) { 279 List<Task> tasks = new ArrayList<>(); 280 List<Task> newTasks; 281 for (TaskProvider taskProvider : tasksProviders.values()) { 282 newTasks = taskProvider.getCurrentTaskInstances(coreSession); 283 if (newTasks != null) { 284 tasks.addAll(newTasks); 285 } 286 } 287 return tasks; 288 } 289 290 /** 291 * Provide @param sortInfo to handle sort page-provider contributions (see {@link #getCurrentTaskInstances}) 292 * 293 * @since 5.9.3 294 */ 295 @Override 296 public List<Task> getCurrentTaskInstances(CoreSession coreSession, List<SortInfo> sortInfos) { 297 List<Task> tasks = new ArrayList<>(); 298 List<Task> newTasks; 299 for (TaskProvider taskProvider : tasksProviders.values()) { 300 newTasks = taskProvider.getCurrentTaskInstances(coreSession, sortInfos); 301 if (newTasks != null) { 302 tasks.addAll(newTasks); 303 } 304 } 305 return tasks; 306 } 307 308 @Override 309 public List<Task> getAllCurrentTaskInstances(CoreSession coreSession, List<SortInfo> sortInfos) { 310 List<Task> tasks = new ArrayList<>(); 311 List<Task> newTasks; 312 for (TaskProvider taskProvider : tasksProviders.values()) { 313 newTasks = taskProvider.getAllCurrentTaskInstances(coreSession, sortInfos); 314 if (newTasks != null) { 315 tasks.addAll(newTasks); 316 } 317 } 318 return tasks; 319 } 320 321 /** 322 * Returns a list of task instances assigned to one of the actors in the list or to its pool. 323 * 324 * @param actors a list used as actorId to retrieve the tasks. 325 * @return 326 */ 327 @Override 328 public List<Task> getCurrentTaskInstances(List<String> actors, CoreSession coreSession) { 329 List<Task> tasks = new ArrayList<>(); 330 List<Task> newTasks; 331 for (TaskProvider taskProvider : tasksProviders.values()) { 332 newTasks = taskProvider.getCurrentTaskInstances(actors, coreSession); 333 if (newTasks != null) { 334 tasks.addAll(newTasks); 335 } 336 } 337 return tasks; 338 } 339 340 /** 341 * Provide @param sortInfo to handle sort page-provider contributions (see {@link #getCurrentTaskInstances}) 342 * 343 * @since 5.9.3 344 */ 345 @Override 346 public List<Task> getCurrentTaskInstances(List<String> actors, CoreSession coreSession, List<SortInfo> sortInfos) { 347 List<Task> tasks = new ArrayList<>(); 348 List<Task> newTasks; 349 for (TaskProvider taskProvider : tasksProviders.values()) { 350 newTasks = taskProvider.getCurrentTaskInstances(actors, coreSession, sortInfos); 351 if (newTasks != null) { 352 tasks.addAll(newTasks); 353 } 354 } 355 return tasks; 356 } 357 358 @Override 359 public List<Task> getTaskInstances(DocumentModel dm, NuxeoPrincipal user, CoreSession coreSession) { 360 List<Task> tasks = new ArrayList<>(); 361 List<Task> newTasks; 362 for (TaskProvider taskProvider : tasksProviders.values()) { 363 newTasks = taskProvider.getTaskInstances(dm, user, coreSession); 364 if (newTasks != null) { 365 tasks.addAll(newTasks); 366 } 367 } 368 return tasks; 369 } 370 371 @Override 372 public List<Task> getTaskInstances(DocumentModel dm, List<String> actors, CoreSession coreSession) { 373 List<Task> tasks = new ArrayList<>(); 374 List<Task> newTasks; 375 for (TaskProvider taskProvider : tasksProviders.values()) { 376 newTasks = taskProvider.getTaskInstances(dm, actors, coreSession); 377 if (newTasks != null) { 378 tasks.addAll(newTasks); 379 } 380 } 381 return tasks; 382 } 383 384 @Override 385 public List<Task> getAllTaskInstances(String processId, CoreSession session) { 386 List<Task> tasks = new ArrayList<>(); 387 List<Task> newTasks; 388 for (TaskProvider taskProvider : tasksProviders.values()) { 389 newTasks = taskProvider.getAllTaskInstances(processId, session); 390 if (newTasks != null) { 391 tasks.addAll(newTasks); 392 } 393 } 394 return tasks; 395 } 396 397 @Override 398 public List<Task> getAllTaskInstances(String processId, NuxeoPrincipal user, CoreSession session) { 399 List<Task> tasks = new ArrayList<>(); 400 List<Task> newTasks; 401 for (TaskProvider taskProvider : tasksProviders.values()) { 402 newTasks = taskProvider.getAllTaskInstances(processId, user, session); 403 if (newTasks != null) { 404 tasks.addAll(newTasks); 405 } 406 } 407 return tasks; 408 } 409 410 @Override 411 public List<Task> getAllTaskInstances(String processId, List<String> actors, CoreSession session) { 412 List<Task> tasks = new ArrayList<>(); 413 List<Task> newTasks; 414 for (TaskProvider taskProvider : tasksProviders.values()) { 415 newTasks = taskProvider.getAllTaskInstances(processId, actors, session); 416 if (newTasks != null) { 417 tasks.addAll(newTasks); 418 } 419 } 420 return tasks; 421 } 422 423 /** 424 * @deprecated since 5.6 425 */ 426 @Deprecated 427 protected List<Task> wrapDocModelInTask(DocumentModelList taskDocuments) { 428 List<Task> tasks = new ArrayList<>(); 429 for (DocumentModel doc : taskDocuments) { 430 tasks.add(doc.getAdapter(Task.class)); 431 } 432 return tasks; 433 } 434 435 @Override 436 public String getTaskRootParentPath(CoreSession coreSession) { 437 GetTaskRootParentPathUnrestricted runner = new GetTaskRootParentPathUnrestricted(coreSession); 438 runner.runUnrestricted(); 439 return runner.getParentPath(); 440 } 441 442 public class GetTaskRootParentPathUnrestricted extends UnrestrictedSessionRunner { 443 444 protected DocumentModel taskRootDoc; 445 446 public GetTaskRootParentPathUnrestricted(CoreSession session) { 447 super(session); 448 } 449 450 @Override 451 public void run() { 452 DocumentRef pathRef = new PathRef(parentPath); 453 if (session.exists(pathRef)) { 454 taskRootDoc = session.getDocument(pathRef); 455 } else { 456 Path path = new Path(parentPath); 457 taskRootDoc = session.createDocumentModel(path.removeLastSegments(1).toString(), path.lastSegment(), 458 TaskConstants.TASK_ROOT_TYPE_NAME); 459 taskRootDoc = session.createDocument(taskRootDoc); 460 ACP acp = taskRootDoc.getACP(); 461 ACL acl = acp.getOrCreateACL(ACL.LOCAL_ACL); 462 acl.add(new ACE("Everyone", "Everything", false)); 463 taskRootDoc.setACP(acp, true); 464 taskRootDoc = session.saveDocument(taskRootDoc); 465 } 466 } 467 468 public DocumentModel getTaskRootDoc() { 469 return taskRootDoc; 470 } 471 472 public String getParentPath() { 473 return taskRootDoc.getPathAsString(); 474 } 475 } 476 477 @Override 478 public List<Task> getAllTaskInstances(String processId, String nodeId, CoreSession session) { 479 List<Task> tasks = new ArrayList<>(); 480 List<Task> newTasks; 481 for (TaskProvider taskProvider : tasksProviders.values()) { 482 newTasks = taskProvider.getAllTaskInstances(processId, nodeId, session); 483 if (newTasks != null) { 484 tasks.addAll(newTasks); 485 } 486 } 487 return tasks; 488 } 489 490 @Override 491 public void reassignTask(CoreSession session, final String taskId, final List<String> newActors, 492 final String comment) { 493 494 new UnrestrictedSessionRunner(session) { 495 496 @Override 497 public void run() { 498 DocumentModel taskDoc = session.getDocument(new IdRef(taskId)); 499 Task task = taskDoc.getAdapter(Task.class); 500 if (task == null) { 501 throw new NuxeoException("Invalid taskId: " + taskId); 502 } 503 List<String> currentAssignees = task.getActors(); 504 List<String> currentActors = new ArrayList<>(); 505 for (String currentAssignee : currentAssignees) { 506 if (currentAssignee.startsWith(NotificationConstants.GROUP_PREFIX) 507 || currentAssignee.startsWith(NotificationConstants.USER_PREFIX)) { 508 // prefixed assignees with "user:" or "group:" 509 currentActors.add(currentAssignee.substring(currentAssignee.indexOf(":") + 1)); 510 } else { 511 currentActors.add(currentAssignee); 512 } 513 } 514 String taskInitator = task.getInitiator(); 515 516 // remove ACLs set for current assignees 517 ACP acp = taskDoc.getACP(); 518 ACL acl = acp.getOrCreateACL(ACL.LOCAL_ACL); 519 List<ACE> toRemove = new ArrayList<>(); 520 521 for (ACE ace : acl.getACEs()) { 522 if (currentActors.contains(ace.getUsername()) || taskInitator.equals(ace.getUsername())) { 523 toRemove.add(ace); 524 } 525 } 526 acl.removeAll(toRemove); 527 528 // grant EVERYTHING on task doc to the new actors 529 List<String> actorIds = new ArrayList<>(); 530 for (String actor : newActors) { 531 if (actor.startsWith(NotificationConstants.GROUP_PREFIX) 532 || actor.startsWith(NotificationConstants.USER_PREFIX)) { 533 // prefixed assignees with "user:" or "group:" 534 actorIds.add(actor.substring(actor.indexOf(":") + 1)); 535 } else { 536 actorIds.add(actor); 537 } 538 } 539 for (String actorId : actorIds) { 540 acl.add(new ACE(actorId, SecurityConstants.EVERYTHING, true)); 541 } 542 543 taskDoc.setACP(acp, true); 544 task.setActors(actorIds); 545 String currentUser = ((NuxeoPrincipal) session.getPrincipal()).getActingUser(); 546 task.addComment(currentUser, comment); 547 session.saveDocument(taskDoc); 548 549 List<DocumentModel> docs = new ArrayList<>(); 550 for (String string : task.getTargetDocumentsIds()) { 551 docs.add(session.getDocument(new IdRef(string))); 552 553 } 554 notifyEvent(session, task, docs, TaskEventNames.WORKFLOW_TASK_REASSIGNED, new HashMap<>(), comment, 555 (NuxeoPrincipal) session.getPrincipal(), actorIds); 556 557 } 558 }.runUnrestricted(); 559 560 } 561 562 @Override 563 public void delegateTask(CoreSession session, final String taskId, final List<String> delegatedActors, 564 final String comment) { 565 566 new UnrestrictedSessionRunner(session) { 567 @Override 568 public void run() { 569 DocumentModel taskDoc = session.getDocument(new IdRef(taskId)); 570 Task task = taskDoc.getAdapter(Task.class); 571 if (task == null) { 572 throw new NuxeoException("Invalid taskId: " + taskId); 573 } 574 // grant EVERYTHING on task doc to the delegated actors 575 List<String> actorIds = new ArrayList<>(); 576 ACP acp = taskDoc.getACP(); 577 ACL acl = acp.getOrCreateACL(ACL.LOCAL_ACL); 578 579 for (String actor : delegatedActors) { 580 if (actor.startsWith(NotificationConstants.GROUP_PREFIX) 581 || actor.startsWith(NotificationConstants.USER_PREFIX)) { 582 // prefixed assignees with "user:" or "group:" 583 actorIds.add(actor.substring(actor.indexOf(":") + 1)); 584 } else { 585 actorIds.add(actor); 586 } 587 } 588 for (String actorId : actorIds) { 589 ACE ace = new ACE(actorId, SecurityConstants.EVERYTHING, true); 590 if (!acl.contains(ace)) { 591 acl.add(ace); 592 } 593 } 594 taskDoc.setACP(acp, true); 595 596 List<String> allDelegatedActors = new ArrayList<>(); 597 allDelegatedActors.addAll(task.getDelegatedActors()); 598 for (String actor : actorIds) { 599 if (!allDelegatedActors.contains(actor)) { 600 allDelegatedActors.add(actor); 601 } 602 } 603 task.setDelegatedActors(allDelegatedActors); 604 605 String currentUser = ((NuxeoPrincipal) session.getPrincipal()).getActingUser(); 606 task.addComment(currentUser, comment); 607 session.saveDocument(taskDoc); 608 List<DocumentModel> docs = new ArrayList<>(); 609 for (String string : task.getTargetDocumentsIds()) { 610 docs.add(session.getDocument(new IdRef(string))); 611 612 } 613 notifyEvent(session, task, docs, TaskEventNames.WORKFLOW_TASK_DELEGATED, new HashMap<>(), 614 String.format("Task delegated by '%s' to '%s'", currentUser, StringUtils.join(actorIds, ",")) 615 + (!StringUtils.isEmpty(comment) ? " with the following comment: " + comment : ""), 616 (NuxeoPrincipal) session.getPrincipal(), actorIds); 617 } 618 619 }.runUnrestricted(); 620 } 621 622 protected void notifyEvent(CoreSession session, Task task, List<DocumentModel> docs, String event, 623 Map<String, Serializable> eventInfo, String comment, NuxeoPrincipal principal, List<String> actorIds) { 624 Map<String, Serializable> eventProperties = new HashMap<>(); 625 ArrayList<String> notificationRecipients = new ArrayList<>(); 626 notificationRecipients.addAll(actorIds); 627 eventProperties.put(NotificationConstants.RECIPIENTS_KEY, 628 notificationRecipients.toArray(new String[notificationRecipients.size()])); 629 if (eventInfo != null) { 630 eventProperties.putAll(eventInfo); 631 } 632 for (DocumentModel doc : docs) { 633 TaskEventNotificationHelper.notifyEvent(session, doc, principal, task, event, eventProperties, comment, 634 null); 635 } 636 } 637 638 @Override 639 public List<Task> getTaskInstances(DocumentModel dm, List<String> actors, boolean includeDelegatedTasks, 640 CoreSession session) { 641 List<Task> tasks = new ArrayList<>(); 642 for (TaskProvider taskProvider : tasksProviders.values()) { 643 tasks.addAll(taskProvider.getTaskInstances(dm, actors, includeDelegatedTasks, session)); 644 } 645 return tasks; 646 } 647 648 /** 649 * @since 5.8 650 * @deprecated since 7.4 use 651 * {@link #createTaskForProcess(CoreSession, NuxeoPrincipal, List, String, String, String, String, String, List, boolean, String, String, Date, Map, String, Map)} 652 * instead 653 */ 654 @Override 655 @Deprecated 656 public List<Task> createTask(CoreSession coreSession, NuxeoPrincipal principal, List<DocumentModel> documents, 657 String taskDocumentType, String taskName, String taskType, String processId, List<String> actorIds, 658 boolean createOneTaskPerActor, String directive, String comment, Date dueDate, 659 Map<String, String> taskVariables, String parentPath, Map<String, Serializable> eventInfo) { 660 return createTaskForProcess(coreSession, principal, documents, taskDocumentType, taskName, taskType, processId, 661 null, actorIds, createOneTaskPerActor, directive, comment, dueDate, taskVariables, parentPath, 662 eventInfo); 663 } 664 665 /** 666 * @since 7.4 667 */ 668 @Override 669 public List<Task> createTaskForProcess(CoreSession coreSession, NuxeoPrincipal principal, 670 List<DocumentModel> documents, String taskDocumentType, String taskName, String taskType, String processId, 671 String processName, List<String> actorIds, boolean createOneTaskPerActor, String directive, String comment, 672 Date dueDate, Map<String, String> taskVariables, String parentPath, Map<String, Serializable> eventInfo) { 673 if (StringUtils.isBlank(parentPath)) { 674 parentPath = getTaskRootParentPath(coreSession); 675 } 676 CreateTaskUnrestricted runner = new CreateTaskUnrestricted(coreSession, principal, documents, taskDocumentType, 677 taskName, taskType, processId, processName, actorIds, createOneTaskPerActor, directive, comment, 678 dueDate, taskVariables, parentPath); 679 runner.runUnrestricted(); 680 681 List<Task> tasks = runner.getTasks(); 682 683 for (Task task : tasks) { 684 // notify 685 notifyEvent(coreSession, task, documents, TaskEventNames.WORKFLOW_TASK_ASSIGNED, eventInfo, comment, 686 principal, task.getActors()); 687 } 688 return tasks; 689 } 690}