All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xworker.app.userflow.UserFlowActions Maven / Gradle / Ivy

The newest version!
package xworker.app.userflow;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;

import org.xmeta.ActionContext;
import org.xmeta.ActionException;
import org.xmeta.Thing;
import org.xmeta.World;
import org.xmeta.util.UtilData;
import org.xmeta.util.UtilMap;

import xworker.dataObject.DataObject;
import xworker.dataObject.utils.DataObjectUtil;
import xworker.dataObject.utils.DbUtil;
import xworker.lang.util.UtilDate;

public class UserFlowActions {
	public static int start(ActionContext actionContext) throws SQLException{
		Thing self = (Thing) actionContext.get("self");
		int count = 0;
		for(Thing task : self.getChilds()){
			if(task.getBoolean("autoStart")){
				if(startTask(task, false, actionContext)){
					count ++;
				}
			}
		}

		return count;
	}
	
	public static void finish(ActionContext actionContext) throws SQLException{
		Thing self = (Thing) actionContext.get("self");
		finish(self, actionContext);
	}

	public static void finish(Thing taskThing, ActionContext actionContext) throws SQLException {
		DataObject task = getTask(taskThing, actionContext);
		if(task != null){
			task.put("finishedCount", task.getInt("finishedCount") + 1);
			task.put("lastFinishedTime", new Date());
			task.put("status", 2);
			task.update(actionContext);

			UserFlowManager.fireTaskFinished(taskThing, task);

			//启动后续子节点
			List nextTaskThings = taskThing.doAction("getNextTaskThings", actionContext);
			for(Thing nextTaskThing : nextTaskThings){
				startTask(nextTaskThing, false, actionContext);
			}
		}
	}
	
	public static DataObject getTask(Thing thing, ActionContext actionContext){
		List datas = DataObjectUtil.query("xworker.app.userflow.dataobjects.UserFlow", UtilMap.toMap("thingPath", thing.getMetadata().getPath()), actionContext);
		if(datas != null && datas.size() > 0){
			return datas.get(0);
		}else{
			return null;
		}
	}
	
	public static boolean startTask(ActionContext actionContext) throws SQLException{
		Thing self = actionContext.getObject("self");
		return startTask(self, false, actionContext);
	}

	public static boolean forceStartTask(ActionContext actionContext) throws SQLException{
		Thing self = actionContext.getObject("self");
		return startTask(self, true, actionContext);
	}

	/**
	 * 启动一个任务。即把任务保存到数据库中,并检测是否可以自动启动。
	 * 1.检查是否在数据库中存在,如果不存在则插入一条。
	 * 2.检测是否可以自动启动。
	 *
	 * @param taskThing 任务模型
	 * @param actionContext 上下文
	 * @param forceStart 是否强制启动
	 * @throws SQLException 异常
	 */
	public static synchronized boolean startTask(Thing taskThing , boolean forceStart, ActionContext actionContext) throws SQLException{
		//判断是否是被引用的任务
		if(taskThing.getStringBlankAsNull("referenceTask") != null){
			Thing refTask = World.getInstance().getThing(taskThing.getString("referenceTask"));
			if(refTask != null){
				taskThing = refTask;
			}
		}
		
		//排除非用户任务节点,比如启动子节点时也会把actions节点启动,需要排除这样的非任务子节点		
		Boolean isTask = taskThing.doAction("isUserFlowTask", actionContext);
		if(isTask == null || !isTask){
			return false;
		}
		
		//判断任务是否存在
		DataObject task = getTask(taskThing, actionContext);
		if(task == null){
			//不存在,新建一条记录
			task = new DataObject("xworker.app.userflow.dataobjects.UserFlow");
			task.put("thingPath", taskThing.getMetadata().getPath());
			task.put("status", 0);
			task.put("label", taskThing.getMetadata().getLabel());
			task.put("finishedCount", 0);
			task.put("periodic", taskThing.getBoolean("periodic") ? 1 : 0);
			task.put("autoStart", taskThing.getBoolean("autoStart") ? 1 : 0);
			task = task.create(actionContext);
		}
		
		if(task == null){
			throw new ActionException("UserFlowTask not exists, path=" + taskThing.getMetadata().getPath());
		}
		
		//正在执行
		if(task.getInt("status") == UserTask.RUNNING){
			return false;
		}
		
		//剩下的状态未启动或已结束,现在重新启动
		return checkPreAndStart(taskThing, task,  forceStart, actionContext);
	}
	
	/**
	 * 检测任何是否可以自动启动。如符合条件的未启动的任务,以及日常未启动的任务等。
	 * 在什么地方被调用的呢?定时器或者任务结束时吧。
	 * 
	 * @param actionContext 上下文
	 * @throws SQLException  SQL异常
	 */
	public static void autoCheckTasks(ActionContext actionContext) throws SQLException{
		//检查任务状态为0的任务,如果任务过多且有很多未执行的任务,应该通过某种方式清理掉
		List unstartTasks = DataObjectUtil.query("xworker.app.userflow.dataobjects.UserFlow", 
				UtilMap.toMap("status", 0, "autoStart", 1), actionContext);
		
		for(DataObject task : unstartTasks){
			Thing flow = World.getInstance().getThing(task.getString("thingPath"));
			if(flow == null){
				task.delete(actionContext);
			}else{
				checkPreAndStart(flow, task, false, actionContext);
			}
		}
		
		//启动每日任务
		List dailyTasks = DataObjectUtil.query("xworker.app.userflow.dataobjects.UserFlow", 
				UtilMap.toMap("status", 2, "periodic", "1"), actionContext);
		
		for(DataObject task : dailyTasks){
			Thing flow = World.getInstance().getThing(task.getString("thingPath"));
			if(flow == null){
				task.delete(actionContext);
			}else{
				checkPreAndStart(flow, task, false, actionContext);
				//检查是否是今天
				//if(task.getDate("lastFinishedTime") != null && !UtilDate.isToday(task.getDate("lastFinishedTime"))){
				//	checkPreAndStart(flow, task, actionContext);
				//}
			}
		}
	}
	
	/**
	 * 检查前置任务, 如果满足那么就启动。
	 * @throws SQLException SQL异常
	 */
	private static boolean checkPreAndStart(Thing flow, DataObject task, boolean forceStart, ActionContext actionContext) throws SQLException{
		if(!forceStart) {
			//检查前置条件
			String preTasks = flow.getStringBlankAsNull("preTasks");
			if (preTasks != null) {
				Thing dbFlow = World.getInstance().getThing("xworker.app.userflow.dataobjects.UserFlow");
				Thing dataSource = World.getInstance().getThing(dbFlow.getString("dataSource"));

				//获取数据库连接
				Connection con = dataSource.doAction("getConnection", actionContext);
				PreparedStatement pst = null;
				try {
					for (String pre : preTasks.split("[\n]")) {
						pre = pre.trim();
						if ("".equals(pre)) {
							continue;
						}

						ResultSet rs = null;
						try {
							pst = con.prepareStatement("select finishedCount from tblAppUserFlow where thingPath=?");
							pst.setString(1, pre);
							rs = pst.executeQuery();

							if (rs.next()) {
								int finishedCount = rs.getInt("finishedCount");
								if (finishedCount == 0) {
									return false;
								}
							} else {
								//没有记录,前置条件未完成
								return false;
							}
						} finally {
							DbUtil.close(rs);
							DbUtil.close(pst);
						}
					}

				} finally {
					DbUtil.close(con);
				}
			}

			//判断前置条件,如果没有符合条件的返回false
			for (Thing preCondition : flow.getChilds("UserTaskCondition")) {
				if (!UtilData.isTrue(preCondition.doAction("isTrue", actionContext, "flow", flow, "task", task))) {
					return false;
				}
			}
		}
		
		//任务可以执行
		task.put("status", 1);
		task.put("lastStartTime", new Date());
		task.update(actionContext);
		
		UserFlowManager.fireTaskStarted(flow, task);
		
		//检查是否是自动执行
		Boolean auto = flow.doAction("isAutoRun", actionContext);
		if(auto != null && auto){
			flow.doAction("run", actionContext);
		}

		return true;
	}
	
	public static void taskRun(ActionContext actionContext){
		Thing self = actionContext.getObject("self");
		
		//执行任务
		self.doAction("doTask", actionContext);
		
		//如果自动结束,则结束
		if(UtilData.isTrue(self.doAction("isAutoFinish", actionContext))){
			self.doAction("finish", actionContext);
		}
	}
	
	public static Boolean isAutoRun(ActionContext actionContext){
		return true;
	}
	
	public static Boolean unAutoRun(ActionContext actionContext){
		return false;
	}
	
	public static Boolean isUserFlowTask(ActionContext actionContext){
		return true;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy