Java tutorial
/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.kernel.workflow; import com.liferay.petra.string.StringBundler; import com.liferay.portal.kernel.exception.PortalException; import com.liferay.portal.kernel.log.Log; import com.liferay.portal.kernel.log.LogFactoryUtil; import com.liferay.portal.kernel.model.WorkflowDefinitionLink; import com.liferay.portal.kernel.model.WorkflowInstanceLink; import com.liferay.portal.kernel.service.ServiceContext; import com.liferay.portal.kernel.service.WorkflowInstanceLinkLocalServiceUtil; import com.liferay.portal.kernel.transaction.TransactionCommitCallbackUtil; import com.liferay.portal.kernel.util.GetterUtil; import com.liferay.portal.kernel.util.ListUtil; import com.liferay.portal.kernel.util.LocaleUtil; import com.liferay.registry.Registry; import com.liferay.registry.RegistryUtil; import com.liferay.registry.ServiceReference; import com.liferay.registry.ServiceRegistration; import com.liferay.registry.ServiceTracker; import com.liferay.registry.ServiceTrackerCustomizer; import com.liferay.registry.collections.ServiceRegistrationMap; import com.liferay.registry.collections.ServiceRegistrationMapImpl; import java.io.Serializable; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentSkipListMap; /** * @author Bruno Farache * @author Marcellus Tavares */ public class WorkflowHandlerRegistryUtil { public static List<WorkflowHandler<?>> getScopeableWorkflowHandlers() { return ListUtil.fromMapValues(_scopeableWorkflowHandlerMap); } public static <T> WorkflowHandler<T> getWorkflowHandler(String className) { return (WorkflowHandler<T>) _workflowHandlerMap.get(className); } public static List<WorkflowHandler<?>> getWorkflowHandlers() { return ListUtil.fromMapValues(_workflowHandlerMap); } public static void register(List<WorkflowHandler<?>> workflowHandlers) { for (WorkflowHandler<?> workflowHandler : workflowHandlers) { register(workflowHandler); } } public static void register(WorkflowHandler<?> workflowHandler) { Registry registry = RegistryUtil.getRegistry(); ServiceRegistration<WorkflowHandler<?>> serviceRegistration = registry .registerService((Class<WorkflowHandler<?>>) (Class<?>) WorkflowHandler.class, workflowHandler); _serviceRegistrations.put(workflowHandler, serviceRegistration); } public static <T> void startWorkflowInstance(long companyId, long groupId, long userId, String className, long classPK, T model, ServiceContext serviceContext) throws PortalException { Map<String, Serializable> workflowContext = (Map<String, Serializable>) serviceContext .removeAttribute("workflowContext"); if (workflowContext == null) { workflowContext = Collections.emptyMap(); } startWorkflowInstance(companyId, groupId, userId, className, classPK, model, serviceContext, workflowContext); } public static <T> T startWorkflowInstance(final long companyId, final long groupId, final long userId, String className, final long classPK, final T model, ServiceContext serviceContext, Map<String, Serializable> workflowContext) throws PortalException { if (serviceContext.getWorkflowAction() != WorkflowConstants.ACTION_PUBLISH) { return model; } final WorkflowHandler<T> workflowHandler = getWorkflowHandler(className); if (workflowHandler == null) { if (WorkflowThreadLocal.isEnabled()) { throw new WorkflowException("No workflow handler found for " + className); } return model; } boolean hasWorkflowInstanceInProgress = _hasWorkflowInstanceInProgress(companyId, groupId, className, classPK); if (hasWorkflowInstanceInProgress) { if (_log.isWarnEnabled()) { _log.warn(StringBundler.concat("Workflow already started for class ", className, " with primary key ", classPK, " in group ", groupId)); } return model; } WorkflowDefinitionLink workflowDefinitionLink = null; if (WorkflowThreadLocal.isEnabled() && WorkflowEngineManagerUtil.isDeployed()) { workflowDefinitionLink = workflowHandler.getWorkflowDefinitionLink(companyId, groupId, classPK); } int status = WorkflowConstants.STATUS_PENDING; if (workflowDefinitionLink == null) { status = WorkflowConstants.STATUS_APPROVED; } workflowContext = new HashMap<>(workflowContext); workflowContext.put(WorkflowConstants.CONTEXT_COMPANY_ID, String.valueOf(companyId)); workflowContext.put(WorkflowConstants.CONTEXT_ENTRY_CLASS_NAME, className); workflowContext.put(WorkflowConstants.CONTEXT_ENTRY_CLASS_PK, String.valueOf(classPK)); workflowContext.put(WorkflowConstants.CONTEXT_ENTRY_TYPE, workflowHandler.getType(LocaleUtil.getDefault())); workflowContext.put(WorkflowConstants.CONTEXT_GROUP_ID, String.valueOf(groupId)); workflowContext.put(WorkflowConstants.CONTEXT_SERVICE_CONTEXT, serviceContext); workflowContext.put(WorkflowConstants.CONTEXT_TASK_COMMENTS, GetterUtil.getString(serviceContext.getAttribute("comments"))); workflowContext.put(WorkflowConstants.CONTEXT_USER_ID, String.valueOf(userId)); T updatedModel = workflowHandler.updateStatus(status, workflowContext); if (workflowDefinitionLink != null) { final Map<String, Serializable> tempWorkflowContext = workflowContext; TransactionCommitCallbackUtil.registerCallback(new Callable<Void>() { @Override public Void call() throws Exception { boolean hasWorkflowInstanceInProgress = _hasWorkflowInstanceInProgress(companyId, groupId, className, classPK); if (!hasWorkflowInstanceInProgress) { workflowHandler.startWorkflowInstance(companyId, groupId, userId, classPK, model, tempWorkflowContext); } return null; } }); } return updatedModel; } public static <T> void startWorkflowInstance(long companyId, long userId, String className, long classPK, T model, ServiceContext serviceContext) throws PortalException { Map<String, Serializable> workflowContext = (Map<String, Serializable>) serviceContext .removeAttribute("workflowContext"); if (workflowContext == null) { workflowContext = Collections.emptyMap(); } startWorkflowInstance(companyId, WorkflowConstants.DEFAULT_GROUP_ID, userId, className, classPK, model, serviceContext, workflowContext); } public static <T> void startWorkflowInstance(long companyId, long userId, String className, long classPK, T model, ServiceContext serviceContext, Map<String, Serializable> workflowContext) throws PortalException { startWorkflowInstance(companyId, WorkflowConstants.DEFAULT_GROUP_ID, userId, className, classPK, model, serviceContext, workflowContext); } public static void unregister(List<WorkflowHandler<?>> workflowHandlers) { for (WorkflowHandler<?> workflowHandler : workflowHandlers) { unregister(workflowHandler); } } public static void unregister(WorkflowHandler<?> workflowHandler) { ServiceRegistration<WorkflowHandler<?>> serviceRegistration = _serviceRegistrations.remove(workflowHandler); if (serviceRegistration != null) { serviceRegistration.unregister(); } } public static <T> T updateStatus(int status, Map<String, Serializable> workflowContext) throws PortalException { String className = (String) workflowContext.get(WorkflowConstants.CONTEXT_ENTRY_CLASS_NAME); WorkflowHandler<T> workflowHandler = getWorkflowHandler(className); if (workflowHandler != null) { return workflowHandler.updateStatus(status, workflowContext); } return null; } private static boolean _hasWorkflowInstanceInProgress(long companyId, long groupId, String className, long classPK) throws PortalException { WorkflowInstanceLink workflowInstanceLink = WorkflowInstanceLinkLocalServiceUtil .fetchWorkflowInstanceLink(companyId, groupId, className, classPK); if (workflowInstanceLink == null) { return false; } WorkflowInstance workflowInstance = WorkflowInstanceManagerUtil.getWorkflowInstance(companyId, workflowInstanceLink.getWorkflowInstanceId()); if (!workflowInstance.isComplete()) { return true; } return false; } private static final Log _log = LogFactoryUtil.getLog(WorkflowHandlerRegistryUtil.class); private static final Map<String, WorkflowHandler<?>> _scopeableWorkflowHandlerMap = new ConcurrentSkipListMap<>(); private static final ServiceRegistrationMap<WorkflowHandler<?>> _serviceRegistrations = new ServiceRegistrationMapImpl<>(); private static final ServiceTracker<WorkflowHandler<?>, WorkflowHandler<?>> _serviceTracker; private static final Map<String, WorkflowHandler<?>> _workflowHandlerMap = new TreeMap<>(); private static class WorkflowHandlerServiceTrackerCustomizer implements ServiceTrackerCustomizer<WorkflowHandler<?>, WorkflowHandler<?>> { @Override public WorkflowHandler<?> addingService(ServiceReference<WorkflowHandler<?>> serviceReference) { Registry registry = RegistryUtil.getRegistry(); WorkflowHandler<?> workflowHandler = registry.getService(serviceReference); _workflowHandlerMap.put(workflowHandler.getClassName(), workflowHandler); if (workflowHandler.isScopeable()) { _scopeableWorkflowHandlerMap.put(workflowHandler.getClassName(), workflowHandler); } return workflowHandler; } @Override public void modifiedService(ServiceReference<WorkflowHandler<?>> serviceReference, WorkflowHandler<?> workflowHandler) { } @Override public void removedService(ServiceReference<WorkflowHandler<?>> serviceReference, WorkflowHandler<?> workflowHandler) { Registry registry = RegistryUtil.getRegistry(); registry.ungetService(serviceReference); _workflowHandlerMap.remove(workflowHandler.getClassName()); if (workflowHandler.isScopeable()) { _scopeableWorkflowHandlerMap.remove(workflowHandler.getClassName()); } } } static { Registry registry = RegistryUtil.getRegistry(); _serviceTracker = registry.trackServices((Class<WorkflowHandler<?>>) (Class<?>) WorkflowHandler.class, new WorkflowHandlerServiceTrackerCustomizer()); _serviceTracker.open(); } }