package com.blueland.bpm.engine.core.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipInputStream;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.ReadOnlyProcessDefinition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.blueland.bpm.common.page.Page;
import com.blueland.bpm.engine.config.model.ProcessInfoConfig;
import com.blueland.bpm.engine.config.service.ProcessInfoConfigManager;
import com.blueland.bpm.engine.core.cmd.RefreshProcessDefineCacheCmd;
import com.blueland.bpm.engine.core.cmd.UpdateDeploymentResourceCmd;
import com.blueland.bpm.engine.core.handler.BizProcessHandler;
import com.blueland.bpm.engine.core.model.ActivityDefinitionModel;
import com.blueland.bpm.engine.core.model.ActivityInstanceModel;
import com.blueland.bpm.engine.core.model.ActivityResourceModel;
import com.blueland.bpm.engine.core.model.ExceptionErrorCode;
import com.blueland.bpm.engine.core.model.ProcessDefinitionModel;
import com.blueland.bpm.engine.core.model.ProcessInstanceModel;
import com.blueland.bpm.engine.core.model.SearchProcessListDTO;
import com.blueland.bpm.engine.core.service.AbstractServiceHelper;
import com.blueland.bpm.engine.core.service.ProcessConfigService;
import com.blueland.bpm.engine.core.service.ProcessDefinitionService;
import com.blueland.bpm.engine.util.ProcessDefinitionUtils;
import com.blueland.bpm.engine.util.ProcessModelUtils;
import com.blueland.bpm.engine.util.WorkFlowException;
import com.blueland.bpm.identity.OrgService;
import com.blueland.bpm.identity.RoleService;
import com.blueland.bpm.identity.UserService;
import com.blueland.bpm.identity.model.User;

/**
 * 流程定义Service
 * @version:  1.0
 * @author lw 
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = false)
public class ProcessDefinitionServiceImpl  extends AbstractServiceHelper implements ProcessDefinitionService{

	protected Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private UserService userService;
	@Autowired
	private RoleService roleService;
	@Autowired
	private OrgService orgService;
	@Autowired
	private ProcessInfoConfigManager processInfoConfigManager;
	@Autowired
	private ProcessConfigService processConfigService;
	
	
	@Autowired
	private ProcessDefinitionResource processDefinitionResource;


	/**
	 * 根据流程实例ID查询流程定义对象{@link ProcessDefinition}
	 * 
	 * @param processInstanceId
	 *            流程实例ID
	 * @return 流程定义对象{@link ProcessDefinition}
	 */
	public ProcessDefinitionModel getProcessDefByPid(String processInstanceId) {
		HistoricProcessInstance historicProcessInstance = historyService
				.createHistoricProcessInstanceQuery()
				.processInstanceId(processInstanceId).singleResult();
		String processDefinitionId = historicProcessInstance
				.getProcessDefinitionId();
		return getProcessDef(processDefinitionId);
	}

	/**
	 * 根据流程定义ID查询流程定义对象{@link ProcessDefinition}
	 * 
	 * @param processDefinitionId
	 *            流程定义对象ID
	 * @return 流程定义对象{@link ProcessDefinition}
	 */
	public ProcessDefinitionModel getProcessDef(String processDefinitionId) {
		ProcessDefinition processDefinition = repositoryService
				.createProcessDefinitionQuery()
				.processDefinitionId(processDefinitionId).singleResult();
		if(processDefinition==null){
			return null;
		}
		return ProcessDefinitionModel.build(processDefinition);
	}

	public List<ActivityDefinitionModel> getProcessActivitys(String processDefinitionId) {
		ReadOnlyProcessDefinition rpd = this.getDeployedProcessDefinition(processDefinitionId);
		List<ActivityDefinitionModel> activityDefinitionModels=new ArrayList<ActivityDefinitionModel>();
		addTaskToModels((List<ActivityImpl>)rpd.getActivities(),activityDefinitionModels);
		return activityDefinitionModels;
	}
	
	public List<ActivityDefinitionModel> getProcessUserActivitys(String processDefinitionId) {
		ReadOnlyProcessDefinition rpd = this.getDeployedProcessDefinition(processDefinitionId);
		List<ActivityDefinitionModel> activityDefinitionModels=new ArrayList<ActivityDefinitionModel>();
		addUserTaskToModels((List<ActivityImpl>)rpd.getActivities(),activityDefinitionModels);
		return activityDefinitionModels;
	}
	
	public ActivityDefinitionModel getActivity(String processDefinitionId,
			String activityId) {
		ReadOnlyProcessDefinition rpd = this.getDeployedProcessDefinition(processDefinitionId);
		ActivityImpl destActivity = (ActivityImpl) rpd.findActivity(activityId);
		return ActivityDefinitionModel.build(destActivity);
	}

	/**
	 * 根据用户ID查询有权限起草的流程定义列表{@link ProcessDefinition}
	 * 
	 * @param userId
	 *            用户ID
	 * @return 流程定义对象{@link ProcessDefinition}
	 */
	public Page<List> findProcessDefList(SearchProcessListDTO searchProcessList) {
		List<ProcessDefinitionModel> procDefAndDeployList=findProcessDefs(searchProcessList);
		Page page = new Page(searchProcessList, procDefAndDeployList.size());
		page.setResult(procDefAndDeployList);
		return page;
	}
	
	/**
	 * 根据用户ID查询有权限起草的流程定义列表{@link ProcessDefinition}
	 * 
	 * @param userId
	 *            用户ID
	 * @return 流程定义对象{@link ProcessDefinition}
	 */
	public List<ProcessDefinitionModel> findProcessDefs(SearchProcessListDTO searchProcessList) {
		List<ProcessDefinitionModel> procDefAndDeployList = new ArrayList<ProcessDefinitionModel>();
		ProcessDefinitionQuery processDefinitionQuery = repositoryService
				.createProcessDefinitionQuery().latestVersion().active().orderByDeploymentId().desc();
		if(StringUtils.isNotEmpty(searchProcessList.getTenantId())){
			processDefinitionQuery.processDefinitionTenantId(searchProcessList.getTenantId());
		}
		if(StringUtils.isNotEmpty(searchProcessList.getFlowType())){
			processDefinitionQuery.processDefinitionKeyLike(searchProcessList.getFlowType());
		}
		/*
		 * 保存两个对象，一个是ProcessDefinition（流程定义），一个是Deployment（流程部署）
		 */
		List<ProcessDefinition> procDefList = processDefinitionQuery.list();
		for (ProcessDefinition processDefinition : procDefList) {
			String deploymentId = processDefinition.getDeploymentId();
			Deployment deployment = repositoryService.createDeploymentQuery()
					.deploymentId(deploymentId).singleResult();
			ProcessDefinitionModel processDefinitionModel=ProcessDefinitionModel.build(processDefinition,deployment);
			processDefinitionModel.setProcessInfoConfig(processConfigService.getProcessInfoConfig(processDefinitionModel.getProcDefId()));
			procDefAndDeployList.add(processDefinitionModel);
		}
		return procDefAndDeployList;
	}
	
	

	/**
	 * 根据用户ID查询有权限起草的流程定义列表{@link ProcessDefinition}
	 * 
	 * @param userId
	 *            用户ID
	 * @return 流程定义对象{@link ProcessDefinition}
	 */
	public List<ProcessDefinitionModel> findProcessDefsNotCascide(SearchProcessListDTO searchProcessList) {
		List<ProcessDefinitionModel> procDefAndDeployList = new ArrayList<ProcessDefinitionModel>();
		ProcessDefinitionQuery processDefinitionQuery = repositoryService
				.createProcessDefinitionQuery().latestVersion().active().orderByDeploymentId().desc();
		if(StringUtils.isNotEmpty(searchProcessList.getTenantId())){
			processDefinitionQuery.processDefinitionTenantId(searchProcessList.getTenantId());
		}
		if(StringUtils.isNotEmpty(searchProcessList.getProcessDefKey())){
			processDefinitionQuery.processDefinitionKeyLike(searchProcessList.getProcessDefKey());
		}
		/*
		 * 保存两个对象，一个是ProcessDefinition（流程定义），一个是Deployment（流程部署）
		 */
		List<ProcessDefinition> procDefList = processDefinitionQuery.list();
		for (ProcessDefinition processDefinition : procDefList) {
			String deploymentId = processDefinition.getDeploymentId();
			ProcessInfoConfig processConfig=processConfigService.getProcessInfoConfig(processDefinition.getId());
			/*if(!processConfig.isRelease()){
				continue;
			}*/
			Deployment deployment = repositoryService.createDeploymentQuery()
					.deploymentId(deploymentId).singleResult();
			ProcessDefinitionModel processDefinitionModel=ProcessDefinitionModel.build(processDefinition,deployment);
			processDefinitionModel.setProcessInfoConfig(processConfig);
			procDefAndDeployList.add(processDefinitionModel);
		}
		return procDefAndDeployList;
	}
	
	/**
	 * 根据定义key查询所有版本的流程定义数据
	 * 
	 * @param userId
	 *            用户ID
	 * @return 流程定义对象list
	 */
	public List<ProcessDefinitionModel> findAllVersionProcessDefs(String procDefKey) {
		List<ProcessDefinitionModel> result = new ArrayList<ProcessDefinitionModel>();
		if(!procDefKey.isEmpty()){
			ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).orderByProcessDefinitionVersion().desc();
			List<ProcessDefinition> processDefinitions = processDefinitionQuery.list();
			if(!processDefinitions.isEmpty()){
				for (ProcessDefinition processDefinition : processDefinitions) {
					ProcessDefinitionModel procDefModel =ProcessDefinitionModel.build(processDefinition);
					ProcessInfoConfig temp = processInfoConfigManager.getById(processDefinition.getId());
					if(temp!=null){
						procDefModel.setPdCreateTime(temp.getCreateTime());
					}
					result.add(procDefModel);
				}
			}
			return result.isEmpty()?null:result;
		}else{
			return null;
		}
	}


	/**
	 * 根据流程定义ID查询流程定义对象{@link ProcessDefinition}
	 * 
	 * @param processDefinitionId
	 *            流程定义对象ID
	 * @return 流程定义对象{@link ProcessDefinition}
	 */
	public ProcessDefinitionModel getProcessDefBykey(String processDefinitionKey) {
		ProcessDefinition processDefinition = repositoryService
				.createProcessDefinitionQuery()
				.processDefinitionKey(processDefinitionKey).latestVersion().singleResult();
		if(processDefinition==null){
			return null;
		}
		return ProcessDefinitionModel.build(processDefinition);
	}

	/**
	 * 根据用户ID查询有权限起草的流程定义列表{@link ProcessDefinition}
	 * 
	 * @param userId
	 *            用户ID
	 * @return 流程定义对象{@link ProcessDefinition}
	 */
	public Map<String,List<ProcessDefinitionModel>> findProcessDefStartByUser(String tenantId, String userId,String flowType) {
		List<ProcessDefinition> processDefinitions = repositoryService
				.createProcessDefinitionQuery().processDefinitionTenantId(tenantId).startableByUser(userId).latestVersion().list();
		//key=ProcessInfoConfig.processTypeId,value=List<ProcessDefinitionModel>
		Map<String,List<ProcessDefinitionModel>> result=new LinkedHashMap<String,List<ProcessDefinitionModel>>();
		if(processDefinitions==null||processDefinitions.isEmpty()){
			logger.error("未找到一条当前用户匹配的流程定义数据,无法查询出流程新建列表");
			return result;
		}
		logger.info("找到与当前用户匹配的流程定义数据列表[{}]",result);
		//key=processDefinitionId,value=ProcessDefinitionModel
		Map<String,ProcessDefinitionModel> processDefinitionModelMap=convertToProcessDefinitionModelMap(processDefinitions);
		//获取所有流程配置信息
		ProcessInfoConfig params=new ProcessInfoConfig();
		params.setTenantId(tenantId);
		if(!"null".equals(flowType)&&StringUtils.isNotEmpty(flowType)){
			params.setProcessTypeId(flowType);
		}
		List<ProcessInfoConfig> processInfoConfigs=processConfigService.findProcessInfoConfigs(params);
		if(processInfoConfigs==null||processInfoConfigs.isEmpty()){
			logger.error("未找到一条当前用户匹配的流程配置数据,无法查询出流程新建列表");
			return result;
		}
		logger.info("找到与当前用户匹配的流程配置数据列表[{}]",processInfoConfigs);
		for (ProcessInfoConfig processInfoConfig : processInfoConfigs) {
			/**
			 * 通过流程配置中的流程定义ID到processDefinitionModelMap中获取ProcessDefinitionModel
			 * 如果processDefinitionModelMap中不存在表明该流程没有在processInfoConfig中进行配置
			 */
			
			ProcessDefinitionModel processDefinitionModel= processDefinitionModelMap.get(processInfoConfig.getProcessDefId()) ;
			if(processDefinitionModel==null||!processInfoConfig.isRelease())
				continue;
			if(result.containsKey(processInfoConfig.getProcessTypeId())){
				List<ProcessDefinitionModel> processDefinitionModels=result.get(processInfoConfig.getProcessTypeId());
				processDefinitionModels.add(processDefinitionModel);
			}else{
				List<ProcessDefinitionModel> processDefinitionModels=new ArrayList<ProcessDefinitionModel>();
				processDefinitionModels.add(processDefinitionModel);
				result.put(processInfoConfig.getProcessTypeId(), processDefinitionModels);
			}
			//使用processInfoConfig.processDefName作为前台流程显示名称
			if(StringUtils.isNotEmpty(processInfoConfig.getProcessDefName())){
				processDefinitionModel.setProcDefName(processInfoConfig.getProcessDefName());
			}
			processDefinitionModel.setProcessInfoConfig(processInfoConfig);
		}
		return result;
	}
	
	public Map<String,List<ProcessDefinitionModel>> findProcessDefStartByUser(String tenantId, String userId){
		return findProcessDefStartByUser(tenantId,userId,"");
	}
	
	/**
	 * 根据用户ID查询有权限起草的流程定义列表{@link ProcessDefinition}
	 * 
	 * @param userId
	 *            用户ID
	 * @return 流程定义对象{@link ProcessDefinition}
	 */
	public ProcessDefinitionModel getProcessDefStartByUser(String userId,String processDefKey) {
		List<ProcessDefinition> processDefinitions = repositoryService
				.createProcessDefinitionQuery().startableByUser(userId).processDefinitionKey(processDefKey).orderByProcessDefinitionVersion().desc().list();
		if(processDefinitions!=null&&!processDefinitions.isEmpty()){
			return ProcessDefinitionModel.build(processDefinitions.get(0));
		}
		return null;
	}
	
	/**
	 * 是否有权限起草固定流程
	 * 
	 * @param userId
	 *            用户ID
	 * @return 流程定义对象{@link ProcessDefinition}
	 */
	public boolean isStartProcessPower(String userId,String processDefKey) {
		List<ProcessDefinition> processDefinitions = repositoryService
				.createProcessDefinitionQuery().startableByUser(userId).processDefinitionKey(processDefKey).latestVersion().list();
		if(processDefinitions!=null&&!processDefinitions.isEmpty()){
			return true;
		}
		return false;
	}



	/**
	 * 部署classpath下面的流程定义
	 * <p>
	 * 从属性配置文件中获取属性<b>com.blueland.bpm.engine.modules</b>扫描**deployments**
	 * </p>
	 * <p>
	 * 然后从每个**deployments/${module}**查找在属性配置文件中的属性**com.blueland.bpm.engine.module.keys.${
	 * submodule}**
	 * <p>
	 * 配置实例：
	 * 
	 * <pre>
	 * #com.blueland.bpm.engine for deploy
	 * com.blueland.bpm.engine.modules=budget,erp,oa
	 * com.blueland.bpm.engine.module.keys.budget=budget
	 * com.blueland.bpm.engine.module.keys.erp=acceptInsurance,billing,effectInsurance,endorsement,payment
	 * com.blueland.bpm.engine.module.keys.oa=caruse,leave,officalstamp,officesupply,out,overtime
	 * </pre>
	 * 
	 * </p>
	 * 
	 * @param processKey
	 *            流程定义KEY
	 * @throws Exception
	 */
	public void deployFromClasspath(String exportDir, String... processKey) {
		try{
		ResourceLoader resourceLoader = new DefaultResourceLoader();
		/*
		 * String[] processKeys = { "leave", "leave-dynamic-from",
		 * "leave-formkey", "dispatch" };
		 */
		for (String loopProcessKey : processKey) {

			/*
			 * 需要过滤指定流程
			 */
			if (ArrayUtils.isNotEmpty(processKey)) {
				if (ArrayUtils.contains(processKey, loopProcessKey)) {
					logger.debug("hit module of {}", processKey);
					deploySingleProcess(resourceLoader, loopProcessKey,
							exportDir);
				} else {
					logger.debug(
							"module: {} not equals process key: {}, ignore and continue find next.",
							loopProcessKey, processKey);
				}
			} else {
				/*
				 * 所有流程
				 */
				deploySingleProcess(resourceLoader, loopProcessKey, exportDir);
			}
		} }catch (Exception e) {
			logger.error("",e);
		}
	}


	/**
	 * 部署单个流程定义
	 * 
	 * @param resourceLoader
	 *            {@link ResourceLoader}
	 * @param processKey
	 *            模块名称
	 * @param subModule
	 *            流程定义名称
	 * @throws IOException
	 *             找不到zip文件时
	 */
	public ProcessDefinitionModel deploySingleProcess(String tenantId,
			InputStream inputStream, String fileName) {
		if (inputStream == null) {
			logger.error("inputStream is null!");
			return null;
		}
		if (fileName == null) {
			logger.error("fileName is null!");
			return null;
		}
		Deployment deployment = null;
		try {

			String extension = FilenameUtils.getExtension(fileName);
			if (extension.equals("zip") || extension.equals("bar")) {
				ZipInputStream zip = new ZipInputStream(inputStream);
				deployment = repositoryService.createDeployment()
						.addZipInputStream(zip).name(fileName).deploy();
			} else {
				deployment = repositoryService.createDeployment()
						.addInputStream(fileName, inputStream).name(fileName)
						.tenantId(tenantId).deploy();
			}
		} catch (Exception e) {
			logger.error("", e);
		}

		ProcessDefinitionModel processDefinitionModel = null;
		try {
			List<ProcessDefinition> list = repositoryService
					.createProcessDefinitionQuery()
					.deploymentId(deployment.getId()).list();
			processDefinitionModel = ProcessDefinitionModel.build(list.get(0));
			if (processDefinitionModel != null) {
				try {
					ProcessInfoConfig prevVersionProcessConfig = processInfoConfigManager
							.getPrevVersionProcessConfig(processDefinitionModel
									.getProcDefId());
					if (prevVersionProcessConfig != null) {
						prevVersionProcessConfig
								.setProcessMgrIsshow(ProcessInfoConfig.PROCESS_MGR_ISSHOW_N);
						processInfoConfigManager
								.update(prevVersionProcessConfig);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} catch (Exception e) {
			logger.error("", e);
		}
		return processDefinitionModel;

	}
	
	

	/**
	 * 重新部署单个流程定义
	 * 
	 * @param processKey
	 *            流程定义KEY
	 * @throws Exception
	 * @see #deployFromClasspath
	 */
	public void redeploy(String exportDir, String... processKey){
		this.deployFromClasspath(exportDir, processKey);
	}

	/**
	 * 重新部署所有流程定义，调用：{@link #deployFromClasspath()}完成功能
	 * 
	 * @throws Exception
	 * @see #deployFromClasspath
	 */
	public void deployAllFromClasspath(String exportDir) throws Exception {
		this.deployFromClasspath(exportDir);
	}

	/**
	 * 加载流程定义的bpmn.xml或图片资源
	 * 
	 * @param processDefinitionId
	 *            流程定义ID
	 * @param resourceType
	 *            image:图片资源,xml:bpmn.xml
	 * @return InputStream
	 */
	public InputStream loadProcessResource(String processDefinitionId,
			String resourceType) {
		InputStream resourceAsStream = null;
		try {
			ProcessDefinition processDefinition = repositoryService
					.createProcessDefinitionQuery()
					.processDefinitionId(processDefinitionId).singleResult();
			if (processDefinition == null)
				return resourceAsStream;
			String resourceName = "";
			if (resourceType.equals("image")) {
				resourceName = processDefinition.getDiagramResourceName();
			} else if (resourceType.equals("xml")) {
				resourceName = processDefinition.getResourceName();
			}
			resourceAsStream = repositoryService.getResourceAsStream(
					processDefinition.getDeploymentId(), resourceName);
		} catch (Exception e) {
			logger.error("获取流程定义的bpmn.xml或图片资源出现异常", e);
		}
		return resourceAsStream;
	}
	
	public void updateDeploymentResource(String deploymentId,String processDefinitionId,byte[] resourceByte,boolean isUpdateImage){
		Command<Void> tempSaveTaskCmd=new UpdateDeploymentResourceCmd(deploymentId,processDefinitionId, resourceByte,isUpdateImage);
		this.managementService.executeCommand(tempSaveTaskCmd);
	}
	
	public boolean updateDeploymentResourceAndCache(BpmnModel bpmnModel,ProcessDefinitionModel processDefinition,boolean isUpdateImage){
		boolean result=false;
		byte[] bpmnByte = ProcessModelUtils.convertBpmnModel(bpmnModel);
		if (bpmnByte != null && bpmnByte.length > 0) {
			Command<Void> tempSaveTaskCmd=new UpdateDeploymentResourceCmd(processDefinition.getDeploymentId(),processDefinition.getProcDefId(), bpmnByte,isUpdateImage);
			this.managementService.executeCommand(tempSaveTaskCmd);
			Command<Void> refreshProcessDefineCacheCmd=new RefreshProcessDefineCacheCmd(processDefinition.getProcDefId());
			this.managementService.executeCommand(refreshProcessDefineCacheCmd);
			result=true;
		}
		return result;
	}
	
	public void refreshProcessDefineCache(String processDefinitionId){
		Command<Void> refreshProcessDefineCacheCmd=new RefreshProcessDefineCacheCmd(processDefinitionId);
		this.managementService.executeCommand(refreshProcessDefineCacheCmd);
	}
	
	

	/**
	 * 部署单个流程定义
	 * 
	 * @param resourceLoader
	 *            {@link ResourceLoader}
	 * @param processKey
	 *            模块名称
	 * @param subModule
	 *            流程定义名称
	 * @throws IOException
	 *             找不到zip文件时
	 */
	private ProcessDefinition deploySingleProcess(ResourceLoader resourceLoader,
			String processKey, String exportDir) throws IOException {
		String classpathResourceUrl = "classpath:/deployments/" + processKey
				+ ".zip";
		logger.debug("read com.blueland.bpm.engine from: {}", classpathResourceUrl);
		Resource resource = resourceLoader.getResource(classpathResourceUrl);
		InputStream inputStream = resource.getInputStream();
		if (inputStream == null) {
			logger.warn("ignore deploy com.blueland.bpm.engine module: {}",
					classpathResourceUrl);
		} else {
			logger.debug("finded com.blueland.bpm.engine module: {}, deploy it!",
					classpathResourceUrl);
			ZipInputStream zis = new ZipInputStream(inputStream);
			Deployment deployment = repositoryService.createDeployment()
					.addZipInputStream(zis).name(processKey + ".bar").deploy();

			// export diagram
			List<ProcessDefinition> list = repositoryService
					.createProcessDefinitionQuery()
					.deploymentId(deployment.getId()).list();
			return list.get(0);
		}
		return null;
	}
	

	/**
	 * 转换ProcessDefinitionModel
	 * @param processDefinitions
	 * @return
	 */
	private Map<String,ProcessDefinitionModel> convertToProcessDefinitionModelMap(List<ProcessDefinition> processDefinitions){
		Map<String,ProcessDefinitionModel> processDefinitionModelMap=new HashMap<String,ProcessDefinitionModel>();
		for (ProcessDefinition processDefinition : processDefinitions) {
			processDefinitionModelMap.put(processDefinition.getId(),ProcessDefinitionModel.build(processDefinition));
		}
		return processDefinitionModelMap;
	}
	
	
	/**
	 * 获取流程起草任务环节
	 * @param processDefinitionId
	 * @return
	 */
	public ActivityDefinitionModel getStartActivity(String processDefinitionId) {
		ReadOnlyProcessDefinition rpd = this.getDeployedProcessDefinition(processDefinitionId);
		PvmActivity pvmActivity = rpd.getInitial();
		PvmTransition pvmTransition = pvmActivity.getOutgoingTransitions().get(
				0);
		PvmActivity pvmStartActivity = pvmTransition.getDestination();
		return ActivityDefinitionModel.build(pvmStartActivity);
	}
	


	

	
	
	public List<ActivityResourceModel> getActivityUserTree(String processInstId,String processDefinitionId,String curActInstId,
			String curActivityId, String destActivityId,String userId,String userOrgId,List<String> filterIds,Map conditionMap) {
		//by lw 20220119 User user=this.userService.getUserById(userId, userOrgId);
		User user=this.userService.getUserById(userId);
		if(user==null){
			throw new WorkFlowException(ExceptionErrorCode.B2058,String.format("user object not found,userId[%s],orgId[%s]",userId,userOrgId));
		}
		userId=user.getUserId();
		List<ActivityResourceModel> activityResources=processDefinitionResource.getNextActivityUser(processInstId,processDefinitionId,curActInstId,curActivityId,destActivityId,userId,filterIds,conditionMap);
		//暂时屏蔽客户端自定义环节下一步人员过滤
		//invokeFilterNextStepUserTree(activityResources, processInstId, processDefinitionId, curActInstId,curActivityId,  destActivityId, userId,filterIds) ;
		return activityResources;
	}

	public List<ActivityDefinitionModel> getNextActivity(String processInstId,
			String processDefinitionId, String activityId, Map conditionMap) {
		List<ActivityDefinitionModel> activityDefinitionModels = processDefinitionResource
				.getNextActivity(processDefinitionId, activityId,processInstId, conditionMap);
		//暂时屏蔽客户端自定义环节下一步过滤
		/*invokefilterNextStep(activityDefinitionModels, processInstId,
				processDefinitionId, activityId, conditionMap);*/
		return activityDefinitionModels;
	}

	public List<ActivityDefinitionModel> getPrevActivity(String processDefinitionId,
			String activityId, Map conditionMap){
		return processDefinitionResource.getPrevActivity(processDefinitionId,activityId,conditionMap);
	}
	
	public List<ActivityResourceModel> getResource(String procDefId,String actDefId) {
		return processDefinitionResource.getResource( procDefId, actDefId);
	}
	@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
	public boolean delete(String procDefId, String deploymentId,boolean cascode) {
		boolean result=false;
		try{
			getRepositoryService().deleteDeployment(deploymentId, cascode);
			processConfigService.deleteProcessInfoConfig(procDefId);
			result=true;
		}catch(Exception e){
			logger.error("",e);
		}
		try{
			if(result){
				processInfoConfigManager.recoverProcessInfoConfig(procDefId);
			}
		}catch(Exception e){
			logger.error("",e);
		}
		return result;
	}
	
	

	private void invokeFilterNextStepUserTree(List<ActivityResourceModel> activityResources,String processInstId,String processDefinitionId,String curActInstId,
			String curActivityId, String destActivityId,String userId,List<String> filterIds) {
		try {
			BizProcessHandler handler = getBussinessProcessHandler(processDefinitionId);
			if (handler != null) {
					if(StringUtils.isEmpty(processInstId)){
						return;
					}
					HistoricProcessInstance processInstance=this.historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstId).singleResult();
					ProcessDefinitionModel processDefinitionModel=this.getProcessDef(processDefinitionId);
					ProcessInstanceModel processInstanceModel=ProcessInstanceModel.buildAndProcDef(processInstance, processDefinitionModel);
					ActivityInstanceModel activityInstanceModel=new ActivityInstanceModel();
					activityInstanceModel.setActivityDefinition(this.getActivity(processDefinitionId, curActivityId));
					/*activityInstanceModel.setNextActivityDefId(destActivityId);
					processInstanceModel.setCurrentActivity(activityInstanceModel);*/
					
					handler.filterNextStepUserTree(activityResources,processInstanceModel, userId, null);
			}
		} catch (Exception e) {
			String errorMsg=String.format("标题为[%s]的流程执行前置业务处理接口filterNextStepUserTree失败,processInputModel对象数据为[%s]",null,null);
			logger.error(errorMsg, e);
		}
	}
	private void invokefilterNextStep(List<ActivityDefinitionModel>  activityDefinitionModels,String processInstId,String processDefinitionId,
			String activityId, Map conditionMap){
		try {
			BizProcessHandler handler = getBussinessProcessHandler(processDefinitionId);
			if (handler != null) {
				HistoricProcessInstance processInstance=this.historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstId).singleResult();
				ProcessDefinitionModel processDefinitionModel=this.getProcessDef(processDefinitionId);
				ProcessInstanceModel processInstanceModel=ProcessInstanceModel.buildAndProcDef(processInstance, processDefinitionModel);
				ActivityInstanceModel activityInstanceModel=new ActivityInstanceModel();
				activityInstanceModel.setActivityDefinition(this.getActivity(processDefinitionId, activityId));
				processInstanceModel.setCurrentActivity(activityInstanceModel);
				handler.filterNextStep(activityDefinitionModels,processInstanceModel, conditionMap);
			}
		} catch (Exception e) {
			String errorMsg=String.format("标题为[%s]的流程执行前置业务处理接口invokefilterNextStep失败,processInputModel对象数据为[%s]",null,null);
			logger.error(errorMsg, e);
		}
	}

	@Override
	public List<ActivityDefinitionModel> getMultiActivity(String processInstId,
			String processDefinitionId, String activityId, Map conditionMap) {
		List<ActivityDefinitionModel> activityDefinitionModels = processDefinitionResource
				.getNextActivity(processDefinitionId, activityId,processInstId, conditionMap);
		for (ActivityDefinitionModel activityDefinitionModel : activityDefinitionModels) {
			if(!activityDefinitionModel.isMulti()){
				activityDefinitionModels.remove(activityDefinitionModel);
			}
		}
		return activityDefinitionModels;
	}

	/**
	 * 查询指定资源的值在哪里流程定义中（资源类型包含角色、组织、人员）
	 * 可以按租户或者单个流程定义KEY来查询
	 * @param tenantId		租户ID
	 * @param procDefKey	流程定义
	 * @param type		资源类型
	 * @param resourceVal	资源值
	 * @return
	 */
	public List<Map<String,String>> findProcessDefsByResource(
			String tenantId, String procDefKey, String resourceType, String resourceVal) {
		List<Map<String,String>>  processDefs = new ArrayList<Map<String,String>>();
		if (StringUtils.isEmpty(resourceType) && StringUtils.isEmpty(resourceVal)) {
			return processDefs;
		}
		SearchProcessListDTO searchProcessListDTO = new SearchProcessListDTO();
		searchProcessListDTO.setTenantId(tenantId);
		searchProcessListDTO.setProcessDefKey(procDefKey);
		//查询符合条件的流程定义列表
		List<ProcessDefinitionModel> processDefinitions =findProcessDefsNotCascide(searchProcessListDTO);
		for (ProcessDefinitionModel processDefinitionModel : processDefinitions) {
			ReadOnlyProcessDefinition rpdf = this.getDeployedProcessDefinition(processDefinitionModel
					.getProcDefId());
			if(rpdf==null){
				continue;
			}
			//获取某流程定义所有环节
			List<PvmActivity> actis = (List<PvmActivity>) rpdf.getActivities();
			for (PvmActivity activity : actis) {
				Map<String,String> resources=new LinkedHashMap<String,String>();
				boolean isFind = false;
				//判断是否是用户任务
				if (ProcessDefinitionUtils.isUserTask((ActivityImpl) activity)) {
					TaskDefinition taskDefinition = (TaskDefinition) activity
							.getProperty("taskDefinition");
					if ("role".equals(resourceType)) {//角色查询逻辑
						Set<Expression> roles = taskDefinition
								.getCandidateGroupIdExpressions();
						for (Expression roleId : roles) {
							if (resourceVal.equals(roleId.getExpressionText())) {
								isFind = true;
								break;
							}
						}
					} else if ("user".equals(resourceType)) {//人员查询逻辑
						Set<Expression> users = taskDefinition
								.getCandidateUserIdExpressions();
						for (Expression userId : users) {
							if (resourceVal.equals(userId.getExpressionText())) {
								isFind = true;
								break;
							}
						}
						if(!isFind){
							Set<Expression> roles = taskDefinition
									.getCandidateGroupIdExpressions();
							for (Expression roleId : roles) {
								boolean isRoleFind=this.roleService.isUserInRole(roleId.getExpressionText(), resourceVal);
								if(isRoleFind){
									isFind = true;
									break;
								}
							}
						}
					} else if ("org".equals(resourceType)) {//组织查询逻辑
						Set<Expression> orgs = taskDefinition
								.getCandidateOrgIdExpressions();
						for (Expression orgId : orgs) {
							if (resourceVal.equals(orgId.getExpressionText())) {
								isFind = true;
								break;
							}
						}
					}
					if (isFind) {
						resources.put("tenantId", processDefinitionModel.getTenantId());
						resources.put("procDefId", processDefinitionModel.getProcDefId());
						resources.put("procDefName", processDefinitionModel.getProcDefName());
						resources.put("activityId", activity.getId());
						resources.put("activityName", (String)activity.getProperty("name"));
						processDefs.add(resources);
					}
				}
			}
		}
		return processDefs;
	}
	
	private void addUserTaskToModels(List<ActivityImpl>  activities,List<ActivityDefinitionModel> activityDefinitionModels){
		for (ActivityImpl activityImpl : activities) {
			 if(ProcessDefinitionUtils.isUserTask(activityImpl)||ProcessDefinitionUtils.isEndEvent(activityImpl)){
				 activityDefinitionModels.add(ActivityDefinitionModel.build(activityImpl));
			 }else if(ProcessDefinitionUtils.isSubProcessStartEvent(activityImpl)){
				 addUserTaskToModels(activityImpl.getActivities(),activityDefinitionModels);
			 }
		}
	}
	private void addTaskToModels(List<ActivityImpl>  activities,List<ActivityDefinitionModel> activityDefinitionModels){
		for (ActivityImpl activityImpl : activities) {
			 if(ProcessDefinitionUtils.isSubProcessStartEvent(activityImpl)){
				 addUserTaskToModels(activityImpl.getActivities(),activityDefinitionModels);
			 }else{
				 activityDefinitionModels.add(ActivityDefinitionModel.build(activityImpl));
			 }
		}
	}

}