content: package com.alibaba.smart.framework.engine.configuration.impl;
  
  import java.util.Map;
  
  import com.alibaba.smart.framework.engine.annotation.Retryable;
  import com.alibaba.smart.framework.engine.common.util.MapUtil;
  import com.alibaba.smart.framework.engine.configuration.DelegationExecutor;
  import com.alibaba.smart.framework.engine.configuration.ExceptionProcessor;
  import com.alibaba.smart.framework.engine.configuration.InstanceAccessor;
  import com.alibaba.smart.framework.engine.configuration.ProcessEngineConfiguration;
  import com.alibaba.smart.framework.engine.context.ExecutionContext;
  import com.alibaba.smart.framework.engine.delegation.ContextBoundedJavaDelegation;
  import com.alibaba.smart.framework.engine.delegation.JavaDelegation;
  import com.alibaba.smart.framework.engine.delegation.TccDelegation;
  import com.alibaba.smart.framework.engine.exception.EngineException;
  import com.alibaba.smart.framework.engine.model.assembly.Activity;
  
  import com.alibaba.smart.framework.engine.util.ThreadPoolUtil;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  /**
   * Created by 高海军 帝奇 74394 on  2019-08-30 16:08.
   */
  public class DefaultDelegationExecutor implements DelegationExecutor {
  
      private static final Logger LOGGER = LoggerFactory.getLogger(DefaultDelegationExecutor.class);
  
      @Override
      public void execute(ExecutionContext context, Activity activity) {
  
          Map<String, String> properties = activity.getProperties();
          if(MapUtil.isNotEmpty(properties)){
              String className  =  properties.get("class");
              if(null != className){
                  execute(context, className,activity);
              }else {
                  LOGGER.debug("No behavior found:"+activity.getId());
              }
          }
      }
  
      protected   void execute(ExecutionContext context, String className, Activity activity) {
          ProcessEngineConfiguration processEngineConfiguration = context.getProcessEngineConfiguration();
          ExceptionProcessor exceptionProcessor = processEngineConfiguration.getExceptionProcessor();
  
          InstanceAccessor instanceAccessor = processEngineConfiguration
              .getInstanceAccessor();
          Object delegation = instanceAccessor.access(className);
  
          boolean present =  delegation.getClass().isAnnotationPresent(Retryable.class);
  
  
              if (delegation instanceof ContextBoundedJavaDelegation) {
                  ContextBoundedJavaDelegation contextBoundedJavaDelegation = (ContextBoundedJavaDelegation)delegation;
                  contextBoundedJavaDelegation.setClassName(className);
                  contextBoundedJavaDelegation.setActivity(activity);
  
                  execute(context, contextBoundedJavaDelegation,  exceptionProcessor , present);
  
              } else if (delegation instanceof JavaDelegation) {
                  JavaDelegation javaDelegation = (JavaDelegation)delegation;
                  execute(context, javaDelegation,  exceptionProcessor ,present);
  
              } else if (delegation instanceof TccDelegation) {
  
                  TccDelegation tccDelegation = (TccDelegation)delegation;
  
                  tccDelegation.tryExecute(context);
  
              } else {
                  throw new EngineException("The delegation is not support : " + delegation.getClass());
              }
  
  
  
      }
  
      protected void execute(ExecutionContext context, JavaDelegation delegation,ExceptionProcessor exceptionProcessor ,boolean present) {
  
  
          if(!present){
              delegation.execute(context);
          }else {
              Retryable annotation = delegation.getClass().getAnnotation(Retryable.class);
              long delay = annotation.delay();
              int maxAttempts = annotation.maxAttempts();
  
              int attemptCount = 0;
              for (;  attemptCount < maxAttempts; attemptCount++) {
  
                  boolean success = false;
                  try {
                      delegation.execute(context);
                      success = true;
                  }catch (Exception e){
                      dealException(exceptionProcessor, e,context);
                      ThreadPoolUtil.sleepSilently(delay);
                  }
  
                  if(success){
                      break;
                  }
  
  
              }
  
              if(attemptCount == maxAttempts -1){
                  // means all retry failed
                  // record log ,trigger alert, persist params if needed
              }
          }
      }
  
  
      protected   void dealException(ExceptionProcessor exceptionProcessor, Exception exception,ExecutionContext context) {
  
          if (null != exceptionProcessor) {
              exceptionProcessor.process(exception,context);
          } else if (exception instanceof RuntimeException) {
              throw (RuntimeException)exception;
          } else {
              throw new EngineException(exception);
          }
      }
  
  
  }