@Override public GraphNode getStartNode() throws DocumentRouteException { for (GraphNode node : getNodes()) { if (node.isStart()) { return node; } } throw new DocumentRouteException("No start node for graph: " + getName()); }
@Override public void updateRouteElement(DocumentRouteElement routeElement, CoreSession session) throws DocumentRouteNotLockedException { if (!isLockedByCurrentUser(routeElement.getDocumentRoute(session), session)) { throw new DocumentRouteNotLockedException(); } routeElement.save(session); }
@Override public void lockDocumentRoute(DocumentRoute routeModel, CoreSession session) throws DocumentRouteAlredayLockedException { LockableDocumentRoute lockableRoute = routeModel.getDocument().getAdapter(LockableDocumentRoute.class); boolean lockedByCurrent = isLockedByCurrentUser(routeModel, session); if (lockableRoute.isLocked(session) && !lockedByCurrent) { throw new DocumentRouteAlredayLockedException(); } if (!lockedByCurrent) { lockableRoute.lockDocument(session); } }
@Override public List<DocumentModel> getWorkflowInputDocuments(CoreSession session, Task task) { String routeInstanceId; try { routeInstanceId = task.getProcessId(); } catch (PropertyException e) { throw new DocumentRouteException("Can not get the related workflow instance"); } if (StringUtils.isEmpty(routeInstanceId)) { throw new DocumentRouteException("Can not get the related workflow instance"); } DocumentModel routeDoc; try { routeDoc = session.getDocument(new IdRef(routeInstanceId)); } catch (DocumentNotFoundException e) { throw new DocumentRouteException("No workflow with the id:" + routeInstanceId); } DocumentRoute route = routeDoc.getAdapter(DocumentRoute.class); return route.getAttachedDocuments(session); }
@Override public void unlockDocumentRoute(DocumentRoute routeModel, CoreSession session) throws DocumentRouteNotLockedException { LockableDocumentRoute lockableRoute = routeModel.getDocument().getAdapter(LockableDocumentRoute.class); if (!lockableRoute.isLockedByCurrentUser(session)) { throw new DocumentRouteNotLockedException(); } lockableRoute.unlockDocument(session); }
protected <T> T valueOrExpression(Class<T> klass, String v, OperationContext context, String kind) throws DocumentRouteException { if (!v.startsWith(EXPR_PREFIX)) { return (T) v; } v = v.substring(EXPR_PREFIX.length()).trim(); Expression expr; if (v.contains(TEMPLATE_START)) { expr = Scripting.newTemplate(v); } else { expr = Scripting.newExpression(v); } Object res = null; try { res = expr.eval(context); // stupid eval() method throws generic Exception } catch (RuntimeException e) { throw new DocumentRouteException("Error evaluating expression: " + v, e); } if (!(klass.isAssignableFrom(res.getClass()))) { throw new DocumentRouteException( kind + " of node '" + getId() + "' of graph '" + graph.getName() + "' does not evaluate to " + klass.getSimpleName() + " but " + res.getClass().getName() + ": " + v); } return (T) res; }
@Override public void removeRouteElement(DocumentRouteElement routeElement, CoreSession session) throws DocumentRouteNotLockedException { DocumentRoute parentRoute = routeElement.getDocumentRoute(session); if (!isLockedByCurrentUser(parentRoute, session)) { throw new DocumentRouteNotLockedException(); } session.removeDocument(routeElement.getDocument().getRef()); session.save();// the document will be queried later on }
@Override public void endTask(CoreSession session, Task task, Map<String, Object> data, String status) { String comment = (String) data.get(GraphNode.NODE_VARIABLE_COMMENT); TaskService taskService = Framework.getService(TaskService.class); taskService.endTask(session, session.getPrincipal(), task, comment, null, false); Map<String, String> taskVariables = task.getVariables(); String routeInstanceId = taskVariables.get(DocumentRoutingConstants.TASK_ROUTE_INSTANCE_DOCUMENT_ID_KEY); if (StringUtils.isEmpty(routeInstanceId)) { throw new DocumentRouteException("Can not resume workflow, no related route"); } completeTask(routeInstanceId, null, task, data, status, session); }
@Override @Deprecated public void addRouteElementToRoute(DocumentRef parentDocumentRef, int idx, DocumentRouteElement routeElement, CoreSession session) throws DocumentRouteNotLockedException { DocumentRoute route = getParentRouteModel(parentDocumentRef, session); if (!isLockedByCurrentUser(route, session)) { throw new DocumentRouteNotLockedException(); } DocumentModelList children = session.query( String.format(ORDERED_CHILDREN_QUERY, session.getDocument(parentDocumentRef).getId())); DocumentModel sourceDoc; try { sourceDoc = children.get(idx); addRouteElementToRoute(parentDocumentRef, sourceDoc.getName(), routeElement, session); } catch (IndexOutOfBoundsException e) { addRouteElementToRoute(parentDocumentRef, null, routeElement, session); } }
throw new DocumentRouteException("Can not evaluate task assignees from " + taskAssigneesVar); throw e; } catch (RuntimeException e) { throw new DocumentRouteException("Error evaluating task assignees: " + taskAssigneesVar, e);
@Override public DocumentRoute validateRouteModel(final DocumentRoute routeModel, CoreSession userSession) throws DocumentRouteNotLockedException { if (!routeModel.getDocument().isLocked()) { throw new DocumentRouteNotLockedException(); } new UnrestrictedSessionRunner(userSession) { @Override public void run() { DocumentRoute route = session.getDocument(routeModel.getDocument().getRef()) .getAdapter(DocumentRoute.class); route.validate(session); } }.runUnrestricted(); return userSession.getDocument(routeModel.getDocument().getRef()).getAdapter(DocumentRoute.class); }
protected Date evaluateDueDate() throws DocumentRouteException { String taskDueDateExpr = getTaskDueDateExpr(); if (StringUtils.isEmpty(taskDueDateExpr)) { return new Date(); } try (OperationContext context = getExecutionContext(getSession())) { Expression expr = Scripting.newExpression(taskDueDateExpr); Object res = expr.eval(context); if (res instanceof DateWrapper) { return ((DateWrapper) res).getDate(); } else if (res instanceof Date) { return (Date) res; } else if (res instanceof Calendar) { return ((Calendar) res).getTime(); } else if (res instanceof String) { return DateParser.parseW3CDateTime((String) res); } else { throw new DocumentRouteException( "The following expression can not be evaluated to a date: " + taskDueDateExpr); } } catch (DocumentRouteException e) { throw e; } catch (RuntimeException e) { throw new DocumentRouteException("Error evaluating task due date: " + taskDueDateExpr, e); } }
@Override @Deprecated public void addRouteElementToRoute(DocumentRef parentDocumentRef, String sourceName, DocumentRouteElement routeElement, CoreSession session) throws DocumentRouteNotLockedException { DocumentRoute parentRoute = getParentRouteModel(parentDocumentRef, session); if (!isLockedByCurrentUser(parentRoute, session)) { throw new DocumentRouteNotLockedException(); } PathSegmentService pss = Framework.getService(PathSegmentService.class); DocumentModel docRouteElement = routeElement.getDocument(); DocumentModel parentDocument = session.getDocument(parentDocumentRef); docRouteElement.setPathInfo(parentDocument.getPathAsString(), pss.generatePathSegment(docRouteElement)); String lifecycleState = parentDocument.getCurrentLifeCycleState() .equals(DocumentRouteElement.ElementLifeCycleState.draft.name()) ? DocumentRouteElement.ElementLifeCycleState.draft.name() : DocumentRouteElement.ElementLifeCycleState.ready.name(); docRouteElement.putContextData(LifeCycleConstants.INITIAL_LIFECYCLE_STATE_OPTION_NAME, lifecycleState); docRouteElement = session.createDocument(docRouteElement); session.orderBefore(parentDocumentRef, docRouteElement.getName(), sourceName); session.save();// the new document will be queried later on }
public void executeChain(String chainId, String transitionId) throws DocumentRouteException { // TODO events if (StringUtils.isEmpty(chainId)) { return; } // get base context try (OperationContext context = getExecutionContext(getSession())) { if (transitionId != null) { context.put("transition", transitionId); } AutomationService automationService = Framework.getService(AutomationService.class); automationService.run(context, chainId); setAllVariables(context); } catch (OperationException e) { throw new DocumentRouteException("Error running chain: " + chainId, e); } }
protected String computeNodes() { CoreSession session = document.getCoreSession(); DocumentModelList children = session.getChildren(document.getRef()); nodes = new ArrayList<>(children.size()); nodesById = new HashMap<>(); String startNodeId = null; for (DocumentModel doc : children) { // TODO use adapters if (doc.getType().equals("RouteNode")) { GraphNode node = new GraphNodeImpl(doc, this); String id = node.getId(); if (nodesById.put(id, node) != null) { throw new DocumentRouteException("Duplicate nodes with id: " + id); } nodes.add(node); if (node.isStart()) { if (startNodeId != null) { throw new DocumentRouteException("Duplicate start nodes: " + startNodeId + " and " + id); } startNodeId = id; } } } return startNodeId; }
@Override public void finishTask(CoreSession session, DocumentRoute route, Task task, boolean delete) throws DocumentRouteException { DocumentModelList docs = route.getAttachedDocuments(session); try { removePermissionsForTaskActors(session, docs, task); // delete task if (delete) { session.removeDocument(new IdRef(task.getId())); } } catch (DocumentNotFoundException e) { throw new DocumentRouteException("Cannot finish task", e); } }
protected void updateTaskInfo(CoreSession session, GraphRoute graph, Task task, String status) { String nodeId = task.getVariable(DocumentRoutingConstants.TASK_NODE_ID_KEY); if (StringUtils.isEmpty(nodeId)) { throw new DocumentRouteException("No nodeId found on task: " + task.getId()); } GraphNode node = graph.getNode(nodeId); NuxeoPrincipal principal = session.getPrincipal(); String actor = principal.getActingUser(); node.updateTaskInfo(task.getId(), true, status, actor, null); }
@Override public List<EscalationRule> evaluateEscalationRules() { List<EscalationRule> rulesToExecute = new ArrayList<>(); // add specific helpers for escalation for (EscalationRule rule : getEscalationRules()) { try (OperationContext context = getExecutionContext(getSession())) { Expression expr = new RoutingScriptingExpression(rule.condition, new RoutingScriptingFunctions(context, rule)); Object res = expr.eval(context); if (!(res instanceof Boolean)) { throw new DocumentRouteException("Condition for rule " + rule + " of node '" + getId() + "' of graph '" + graph.getName() + "' does not evaluate to a boolean: " + rule.condition); } boolean bool = Boolean.TRUE.equals(res); if ((!rule.isExecuted() || rule.isMultipleExecution()) && bool) { rulesToExecute.add(rule); } } catch (DocumentRouteException e) { throw e; } catch (RuntimeException e) { throw new DocumentRouteException("Error evaluating condition: " + rule.condition, e); } } saveDocument(); return rulesToExecute; }
Task task = taskDoc.getAdapter(Task.class); if (task == null) { throw new DocumentRouteException("Invalid taskId: " + taskId); GraphRoute routeInstance = routeDoc.getAdapter(GraphRoute.class); if (routeInstance == null) { throw new DocumentRouteException("Invalid routeInstanceId: " + routeId);
protected void cancelTask(CoreSession session, final String taskId) throws DocumentRouteException { DocumentRef taskRef = new IdRef(taskId); if (!session.exists(taskRef)) { log.info(String.format("Task with id %s does not exist anymore", taskId)); DocumentModelList docs = graph.getAttachedDocumentModels(); Framework.getService(DocumentRoutingService.class).removePermissionsForTaskActors(session, docs, taskId); NuxeoPrincipal principal = session.getPrincipal(); String actor = principal.getActingUser(); updateTaskInfo(taskId, true, null, actor, null); return; } DocumentModel taskDoc = session.getDocument(new IdRef(taskId)); Task task = taskDoc.getAdapter(Task.class); if (task == null) { throw new DocumentRouteException("Invalid taskId: " + taskId); } DocumentModelList docs = graph.getAttachedDocumentModels(); Framework.getService(DocumentRoutingService.class).removePermissionsForTaskActors(session, docs, task); if (task.isOpened()) { task.cancel(session); } session.saveDocument(task.getDocument()); // task is considered processed with the status "null" when is // canceled // actor NuxeoPrincipal principal = session.getPrincipal(); String actor = principal.getActingUser(); updateTaskInfo(taskId, true, null, actor, null); }