Package org.camunda.bpm.engine.spring.components.aop

Source Code of org.camunda.bpm.engine.spring.components.aop.ProcessStartingMethodInterceptor

/*
* 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.camunda.bpm.engine.spring.components.aop;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.logging.Logger;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.spring.annotations.BusinessKey;
import org.camunda.bpm.engine.spring.annotations.ProcessVariable;
import org.camunda.bpm.engine.spring.annotations.StartProcess;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
* {@link org.aopalliance.intercept.MethodInterceptor} that starts a business process
* as a result of a successful method invocation.
*
* @author Josh Long
*/
public class ProcessStartingMethodInterceptor implements MethodInterceptor {

  private Logger log = Logger.getLogger(getClass().getName());

  /**
   * injected reference - can be obtained via a {@link org.camunda.bpm.engine.spring.ProcessEngineFactoryBean}
   */
  protected ProcessEngine processEngine;

  /**
   * @param processEngine takes a reference to a {@link org.camunda.bpm.engine.ProcessEngine}
   */
  public ProcessStartingMethodInterceptor(ProcessEngine processEngine) {
    this.processEngine = processEngine;
  }

  boolean shouldReturnProcessInstance(StartProcess startProcess, MethodInvocation methodInvocation, Object result) {
    return (result instanceof ProcessInstance || methodInvocation.getMethod().getReturnType().isAssignableFrom(ProcessInstance.class));
  }

  boolean shouldReturnProcessInstanceId(StartProcess startProcess, MethodInvocation methodInvocation, Object result) {
    return startProcess.returnProcessInstanceId() && (result instanceof String || methodInvocation.getMethod().getReturnType().isAssignableFrom(String.class));
  }

  @SuppressWarnings("unused")
  boolean shouldReturnAsyncResultWithProcessInstance(StartProcess startProcess, MethodInvocation methodInvocation, Object result) {
    return (result instanceof Future || methodInvocation.getMethod().getReturnType().isAssignableFrom(Future.class));
  }

  public Object invoke(MethodInvocation invocation) throws Throwable {

    Method method = invocation.getMethod();

    StartProcess startProcess = AnnotationUtils.getAnnotation(method, StartProcess.class);

    String processKey = startProcess.processKey();

    Assert.hasText(processKey, "you must provide the name of process to start");

    Object result;
    try {
      result = invocation.proceed();
      Map<String, Object> vars = this.processVariablesFromAnnotations(invocation);

      String businessKey = this.processBusinessKey(invocation);

      log.info("variables for the started process: " + vars.toString());

      RuntimeService runtimeService = this.processEngine.getRuntimeService();
      ProcessInstance pi ;
      if (null != businessKey && StringUtils.hasText(businessKey)) {
        pi = runtimeService.startProcessInstanceByKey(processKey, businessKey, vars);
        log.info("the business key for the started process is '" + businessKey + "' ");
      } else {
        pi = runtimeService.startProcessInstanceByKey(processKey, vars);
      }

      String pId = pi.getId();

      if (invocation.getMethod().getReturnType().equals(void.class))
        return null;

      if (shouldReturnProcessInstance(startProcess, invocation, result))
        return pi;

      if (shouldReturnProcessInstanceId(startProcess, invocation, result))
        return pId;

      if (shouldReturnAsyncResultWithProcessInstance(startProcess, invocation, result)) {
        return new AsyncResult<ProcessInstance>(pi);
      }

    } catch (Throwable th) {
      throw new RuntimeException(th);
    }
    return result;
  }

  protected String processBusinessKey(MethodInvocation invocation) throws Throwable {
    Map<BusinessKey, String> businessKeyAnnotations = this.mapOfAnnotationValues( BusinessKey.class ,invocation);
    if (businessKeyAnnotations.size() == 1) {
      BusinessKey processId = businessKeyAnnotations.keySet().iterator().next();
      return businessKeyAnnotations.get(processId);
    }
    return null;
  }

  @SuppressWarnings("unchecked")
  private <K extends Annotation, V> Map<K, V> mapOfAnnotationValues(Class<K> annotationType, MethodInvocation invocation) {
    Method method = invocation.getMethod();
    Annotation[][] annotations = method.getParameterAnnotations();
    Map<K, V> vars = new HashMap<K, V>();
    int paramIndx = 0;
    for (Annotation[] annPerParam : annotations) {
      for (Annotation annotation : annPerParam) {
        if (!annotationType.isAssignableFrom(annotation.getClass())) {
          continue;
        }
        K pv = (K) annotation;
        V v = (V) invocation.getArguments()[paramIndx];
        vars.put(pv, v);

      }
      paramIndx += 1;
    }
    return vars;
  }


  /**
   * if there any arguments with the {@link org.camunda.bpm.engine.annotations.ProcessVariable} annotation,
   * then we feed those parameters into the business process
   *
   * @param invocation the invocation of the method as passed to the {@link org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)} method
   * @return returns the map of process variables extracted from the parameters
   * @throws Throwable thrown anything goes wrong
   */
  protected Map<String, Object> processVariablesFromAnnotations(MethodInvocation invocation) throws Throwable {

    Map<ProcessVariable, Object> vars = this.mapOfAnnotationValues(ProcessVariable.class, invocation);

    Map<String, Object> varNameToValueMap = new HashMap<String, Object>();
    for (ProcessVariable processVariable : vars.keySet()) {
      varNameToValueMap.put(processVariable.value(), vars.get(processVariable));
    }
    return varNameToValueMap;

  }
}
TOP

Related Classes of org.camunda.bpm.engine.spring.components.aop.ProcessStartingMethodInterceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.