/* * Copyright 2010 the original author or authors * * 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.activiti.spring.components.registry; import org.activiti.engine.ProcessEngine; import org.activiti.engine.impl.bpmn.behavior.ReceiveTaskActivityBehavior; import org.activiti.engine.impl.pvm.delegate.ActivityBehavior; import org.activiti.engine.impl.pvm.delegate.ActivityExecution; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.util.ArrayList; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; /** * this class records and manages all known {@link org.activiti.engine.annotations.State} - responding * beans in the JVM. It <em>should</em> have metadata on all methods, and what * those methods expect from a given invocation (ie: which process, which process variables). * * @author Josh Long * @since 1.0 */ public class ActivitiStateHandlerRegistry extends ReceiveTaskActivityBehavior implements BeanFactoryAware, BeanNameAware, ActivityBehavior, InitializingBean { private Logger logger = Logger.getLogger(getClass().getName()); private String beanName; private BeanFactory beanFactory; private volatile ConcurrentHashMap<String, ActivitiStateHandlerRegistration> registrations = new ConcurrentHashMap<String, ActivitiStateHandlerRegistration>(); private ProcessEngine processEngine; public void setProcessEngine(ProcessEngine processEngine) { this.processEngine = processEngine; } @Override public void execute(ActivityExecution execution) throws Exception { } @Override public void signal(ActivityExecution execution, String signalName, Object data) throws Exception { leave(execution); } protected String registrationKey(String stateName, String processName) { return (org.apache.commons.lang.StringUtils.defaultString(processName) + ":" + org.apache.commons.lang.StringUtils.defaultString(stateName)).toLowerCase(); } /** * used at runtime to register state handlers as they are registered with the spring context * * @param registration the {@link org.activiti.spring.components.registry.ActivitiStateHandlerRegistration} */ public void registerActivitiStateHandler( ActivitiStateHandlerRegistration registration) { String regKey = registrationKey(registration.getProcessName(), registration.getStateName()); this.registrations.put(regKey, registration); } /** * this is responsible for looking up components in the registry and returning the appropriate handler based * on specificity of the {@link org.activiti.spring.components.registry.ActivitiStateHandlerRegistration} * * @param processName the process name to look for (optional) * @param stateName the state name to look for (not optional) * @return all matching options */ public Collection<ActivitiStateHandlerRegistration> findRegistrationsForProcessAndState( String processName, String stateName) { Collection<ActivitiStateHandlerRegistration> registrationCollection = new ArrayList<ActivitiStateHandlerRegistration>(); String regKeyFull = registrationKey(processName, stateName); String regKeyWithJustState = registrationKey(null, stateName); for (String k : this.registrations.keySet()) if (k.contains(regKeyFull)) { registrationCollection.add(this.registrations.get(k)); } if (registrationCollection.size() == 0) { for (String k : this.registrations.keySet()) if (k.contains(regKeyWithJustState)) { registrationCollection.add(this.registrations.get(k)); } } return registrationCollection; } /** * this scours the registry looking for candidate registrations that match a given process name and/ or state nanme * * @param processName the name of the process * @param stateName the name of the state * @return an unambiguous {@link org.activiti.spring.components.registry.ActivitiStateHandlerRegistry} or null */ public ActivitiStateHandlerRegistration findRegistrationForProcessAndState(String processName, String stateName) { ActivitiStateHandlerRegistration r = null; String key = registrationKey(processName, stateName); Collection<ActivitiStateHandlerRegistration> rs = this.findRegistrationsForProcessAndState( processName, stateName); for (ActivitiStateHandlerRegistration sr : rs) { String kName = registrationKey(sr.getProcessName(), sr.getStateName()); if (key.equalsIgnoreCase(kName)) { r = sr; break; } } for (ActivitiStateHandlerRegistration sr : rs) { String kName = registrationKey(null, sr.getStateName()); if (key.equalsIgnoreCase(kName)) { r = sr; break; } } if ((r == null) && (rs.size() > 0)) { r = rs.iterator().next(); } return r; } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } public void setBeanName(String name) { this.beanName = name; } public void afterPropertiesSet() throws Exception { Assert.notNull(this.processEngine, "the 'processEngine' can't be null"); logger.info( "this bean contains a processEngine reference. "+ this.processEngine); logger.info("starting " + getClass().getName()); } }