content: /**
   * Alipay.com Inc.
   * Copyright (c) 2004-2017 All Rights Reserved.
   */
  package com.alibaba.smart.framework.engine.persister.custom.session;
  
  import java.util.Map;
  import java.util.Stack;
  import java.util.concurrent.ConcurrentHashMap;
  
  import com.alibaba.smart.framework.engine.model.instance.ProcessInstance;
  
  /**
   * @author xuantian 2017-02-08 5:50 xuantian
   */
  public class PersisterSession {
  
  
      /**
       * The Session Thread Local.
       */
      private static InheritableThreadLocal<Stack<PersisterSession>> sessionThreadLocal = new InheritableThreadLocal<Stack<PersisterSession>>();
  
      private Map<String, ProcessInstance> processInstances = new ConcurrentHashMap<String, ProcessInstance>(8);
  
      public static PersisterSession create() {
          PersisterSession session = new PersisterSession();
          getOrBuildStack(sessionThreadLocal).push(session);
          return session;
  
      }
  
      /**
       * @return the BizSession got from the thread local.
       */
      public static PersisterSession currentSession() {
          Stack<PersisterSession> sessions = getOrBuildStack(sessionThreadLocal);
          if (sessions.isEmpty()) {
              return null;
          }
          return sessions.peek();
      }
  
      /**
       * the static method for destroy session for easy using.
       */
      public static void destroySession() {
          Stack<PersisterSession> stack = getOrBuildStack(sessionThreadLocal);
          stack.pop();
  
          // 当线程被复用时，导致stack被多个子线程共享，进而导致push/pop 不被成对调用了，最终导致数据错乱。
          if(stack.isEmpty()){
              sessionThreadLocal.remove();
          }
      }
  
  
      private static <T> Stack<T> getOrBuildStack(ThreadLocal<Stack<T>> threadLocal) {
          Stack<T> stack = threadLocal.get();
          if (stack==null) {
              stack = new Stack<T>();
              threadLocal.set(stack);
          }
          return stack;
      }
  
      /**
       * default constructor.
       */
      private PersisterSession() {
  
      }
  
  
  
      public Map<String, ProcessInstance> getProcessInstances() {
          return processInstances;
      }
  
  
      public void putProcessInstance(ProcessInstance processInstance) {
          this.processInstances.put(processInstance.getInstanceId(), processInstance);
      }
  
      public ProcessInstance getProcessInstance(String instanceId) {
          return this.processInstances.get(instanceId);
      }
  }