/* * Copyright (c) 2010-2016 Evolveum * * 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 com.evolveum.midpoint.wf.impl; import com.evolveum.midpoint.model.api.ModelInteractionService; import com.evolveum.midpoint.model.common.SystemObjectCache; import com.evolveum.midpoint.prism.Containerable; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.query.ObjectQuery; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SearchResultList; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskDeletionListener; import com.evolveum.midpoint.task.api.TaskManager; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SecurityViolationException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.wf.api.ProcessListener; import com.evolveum.midpoint.wf.api.WorkItemListener; import com.evolveum.midpoint.wf.api.WorkflowManager; import com.evolveum.midpoint.wf.impl.activiti.dao.ProcessInstanceManager; import com.evolveum.midpoint.wf.impl.activiti.dao.ProcessInstanceProvider; import com.evolveum.midpoint.wf.impl.activiti.dao.WorkItemManager; import com.evolveum.midpoint.wf.impl.activiti.dao.WorkItemProvider; import com.evolveum.midpoint.wf.impl.tasks.WfTaskController; import com.evolveum.midpoint.wf.impl.tasks.WfTaskUtil; import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; import com.evolveum.midpoint.wf.util.ApprovalUtils; import com.evolveum.midpoint.wf.util.ChangesByState; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.Collection; import java.util.List; /** * @author mederly * * Note: don't autowire this class - because of Spring AOP use it couldn't be found by implementation class; only by its interface. */ @Component("workflowManager") public class WorkflowManagerImpl implements WorkflowManager, TaskDeletionListener { private static final transient Trace LOGGER = TraceManager.getTrace(WorkflowManagerImpl.class); @Autowired private PrismContext prismContext; @Autowired private WfConfiguration wfConfiguration; @Autowired private ProcessInstanceProvider processInstanceProvider; @Autowired private ProcessInstanceManager processInstanceManager; @Autowired private WfTaskController wfTaskController; @Autowired private WorkItemProvider workItemProvider; @Autowired private WorkItemManager workItemManager; @Autowired private WfTaskUtil wfTaskUtil; @Autowired private MiscDataUtil miscDataUtil; @Autowired private SystemObjectCache systemObjectCache; @Autowired private TaskManager taskManager; private static final String DOT_INTERFACE = WorkflowManager.class.getName() + "."; @PostConstruct public void initialize() { LOGGER.debug("Workflow manager starting."); taskManager.registerTaskDeletionListener(this); } /* * Work items * ========== */ @Override public <T extends Containerable> Integer countContainers(Class<T> type, ObjectQuery query, Collection<SelectorOptions<GetOperationOptions>> options, OperationResult parentResult) throws SchemaException { OperationResult result = parentResult.createSubresult(DOT_INTERFACE + ".countContainers"); result.addParams(new String[] { "type", "query" }, type, query); result.addCollectionOfSerializablesAsParam("options", options); try { if (!WorkItemType.class.equals(type)) { throw new UnsupportedOperationException("countContainers is available only for work items"); } return workItemProvider.countWorkItems(query, options, result); } catch (SchemaException|RuntimeException e) { result.recordFatalError("Couldn't count items: " + e.getMessage(), e); throw e; } finally { result.computeStatusIfUnknown(); } } @SuppressWarnings("unchecked") @Override public <T extends Containerable> SearchResultList<T> searchContainers(Class<T> type, ObjectQuery query, Collection<SelectorOptions<GetOperationOptions>> options, OperationResult parentResult) throws SchemaException { OperationResult result = parentResult.createSubresult(DOT_INTERFACE + ".searchContainers"); result.addParams(new String[] { "type", "query" }, type, query); result.addCollectionOfSerializablesAsParam("options", options); try { if (!WorkItemType.class.equals(type)) { throw new UnsupportedOperationException("searchContainers is available only for work items"); } return (SearchResultList<T>) workItemProvider.searchWorkItems(query, options, result); } catch (SchemaException|RuntimeException e) { result.recordFatalError("Couldn't count items: " + e.getMessage(), e); throw e; } finally { result.computeStatusIfUnknown(); } } @Override public void completeWorkItem(String taskId, boolean decision, String comment, ObjectDelta additionalDelta, WorkItemEventCauseInformationType causeInformation, OperationResult parentResult) throws SecurityViolationException, SchemaException { workItemManager.completeWorkItem(taskId, ApprovalUtils.toUri(decision), comment, additionalDelta, causeInformation, parentResult); } @Override public void claimWorkItem(String workItemId, OperationResult result) throws ObjectNotFoundException, SecurityViolationException { workItemManager.claimWorkItem(workItemId, result); } @Override public void releaseWorkItem(String workItemId, OperationResult result) throws SecurityViolationException, ObjectNotFoundException { workItemManager.releaseWorkItem(workItemId, result); } @Override public void delegateWorkItem(String workItemId, List<ObjectReferenceType> delegates, WorkItemDelegationMethodType method, OperationResult parentResult) throws SecurityViolationException, ObjectNotFoundException, SchemaException { workItemManager.delegateWorkItem(workItemId, delegates, method, null, null, null, parentResult); } /* * Process instances * ================= */ @Override public void stopProcessInstance(String instanceId, String username, OperationResult parentResult) { processInstanceManager.stopProcessInstance(instanceId, username, parentResult); } @Override public void synchronizeWorkflowRequests(OperationResult parentResult) { processInstanceManager.synchronizeWorkflowRequests(parentResult); } /* * Tasks * ===== */ @Override public <T extends ObjectType> void augmentTaskObject(PrismObject<T> object, Collection<SelectorOptions<GetOperationOptions>> options, Task task, OperationResult result) { processInstanceProvider.augmentTaskObject(object, options, task, result); } @Override public <T extends ObjectType> void augmentTaskObjectList(SearchResultList<PrismObject<T>> list, Collection<SelectorOptions<GetOperationOptions>> options, Task task, OperationResult result) { processInstanceProvider.augmentTaskObjectList(list, options, task, result); } @Override public void onTaskDelete(Task task, OperationResult result) { processInstanceManager.onTaskDelete(task, result); } /* * Other * ===== */ @Override public boolean isEnabled() { return wfConfiguration.isEnabled(); } @Override public PrismContext getPrismContext() { return prismContext; } public WfTaskUtil getWfTaskUtil() { return wfTaskUtil; } public MiscDataUtil getMiscDataUtil() { return miscDataUtil; } @Override public void registerProcessListener(ProcessListener processListener) { wfTaskController.registerProcessListener(processListener); } @Override public void registerWorkItemListener(WorkItemListener workItemListener) { wfTaskController.registerWorkItemListener(workItemListener); } @Override public Collection<ObjectReferenceType> getApprovedBy(Task task, OperationResult result) throws SchemaException { return wfTaskUtil.getApprovedByFromTaskTree(task, result); } @Override public boolean isCurrentUserAuthorizedToSubmit(WorkItemType workItem) { return miscDataUtil.isAuthorized(workItem, MiscDataUtil.RequestedOperation.COMPLETE); } @Override public boolean isCurrentUserAuthorizedToClaim(WorkItemType workItem) { return miscDataUtil.isAuthorizedToClaim(workItem); } @Override public boolean isCurrentUserAuthorizedToDelegate(WorkItemType workItem) { return miscDataUtil.isAuthorized(workItem, MiscDataUtil.RequestedOperation.DELEGATE); } @Override public ChangesByState getChangesByState(TaskType rootTask, ModelInteractionService modelInteractionService, PrismContext prismContext, OperationResult result) throws SchemaException, ObjectNotFoundException { // TODO op subresult return miscDataUtil.getChangesByStateForRoot(rootTask, modelInteractionService, prismContext, result); } @Override public ChangesByState getChangesByState(TaskType childTask, TaskType rootTask, ModelInteractionService modelInteractionService, PrismContext prismContext, OperationResult result) throws SchemaException, ObjectNotFoundException { // TODO op subresult return miscDataUtil.getChangesByStateForChild(childTask, rootTask, modelInteractionService, prismContext, result); } @Override public void cleanupActivitiProcesses(OperationResult parentResult) throws SchemaException { OperationResult result = parentResult.createSubresult(DOT_INTERFACE + ".cleanupActivitiProcesses"); try { processInstanceManager.cleanupActivitiProcesses(result); } catch (Throwable t) { result.recordFatalError("Couldn't cleanup Activiti processes: " + t.getMessage(), t); throw t; } finally { result.recordSuccessIfUnknown(); } } }