package foundation.state; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Set; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import foundation.action.ActionContext; import foundation.action.SingletonActionProvider; import foundation.action.StateContext; import foundation.action.WorkFlowRuntime; import foundation.action.WorkStepKey; import foundation.dao.DataPackage; import foundation.dao.DataReader; import foundation.dao.DataSource; import foundation.dao.DataWriter; import foundation.dao.Domain; import foundation.dao.PackageItem; import foundation.dao.bizlogic.DataStates; import foundation.dao.bizlogic.IStateProvider; import foundation.data.entity.Entity; import foundation.data.object.DataObject; import foundation.data.object.EntitySaver; import foundation.state.approve.ApprovalResult; import foundation.state.approve.ApproveOperate; import foundation.state.approve.ApproveRuntime; import foundation.state.approve.StepLocation; import foundation.state.approve.WorkingInstance; import foundation.token.IOnlineUser; import foundation.util.CaseInsensitiveSet; import foundation.util.Util; import foundation.variant.provider.DataEvent; public class StateCenter extends SingletonActionProvider implements IStateProvider { protected static Logger logger = LogManager.getLogger(StateCenter.class); protected static String StateName_Back = "审批退回"; protected static String StateName_Cancel = "申请人撤回"; private static StateCenter instance; private Set targetOperators; private StateCenter() { targetOperators = new CaseInsensitiveSet(); } public static synchronized StateCenter getInstance() { if (instance == null) { instance = new StateCenter(); } return instance; } public void exec(ActionContext context, String methodName) throws Exception { Method method = getMethod(methodName); if (method == null) { doExec(context, methodName); return; } try { method.invoke(this, context); } catch (InvocationTargetException e) { e.printStackTrace(); Throwable throwable = e.getTargetException(); if (throwable == null) { throw e; } else { throw (Exception) throwable; } } } @Override protected void publishMethod() { //1.1 【状态】-- 提交 状态进入到 To 位置 addMethod("commit"); //1.2 【状态】-- 状态回退到 From 位置 addMethod("stateBack"); //1.3 【状态】-- 状态进入到End位置 addMethod("stateEnd"); //2.1 【审批】-- 审批同意(下一步) addMethod("approve"); //2.2 【审批】-- 审批同意(跳过所有审批直接成功) addMethod("goEnd"); //2.3 【审批】-- 审批不同意,回退上一步 addMethod("goBack"); //2.4 【审批】-- 审批不同意(一票否决) addMethod("goHome"); //2.5 【审批】-- 申请人撤回 addMethod("pullBack"); //2.6 【审批】-- 变更 状态进入到 To 位置 addMethod("toChange"); //2.7 【审批】-- 关闭 状态进入到 To 位置 addMethod("toClose"); //3.1 获取状态机信息(页面审批-通过DataName) addMethod("getMachine"); //3.2 获取状态机信息(状态机设计器-通过状态机ID) addMethod("getOneMachine"); //3.3 保存状态机图数据 addMethod("saveOneMachine"); //3.4 获取审批步骤 addMethod("getApproveSteps"); //4. 获取状态机操作列表 addMethod("getPoints"); //5. 获取状态机操作列表(通过审批流ID) addMethod("getPointsByApprove"); } public void doExec(ActionContext context, String operator) throws Exception { runState(context, operator, null, null, null); } public void commit(ActionContext context) throws Exception { runState(context, "commit", null, DataEvent.Commit, null); } public void toChange(ActionContext context) throws Exception { runState(context, "toChange", null, DataEvent.toChange, null); } public void toClose(ActionContext context) throws Exception { runState(context, "toClose", null, DataEvent.toClose, null); } public void stateBack(ActionContext context) throws Exception { runState(context, "stateBack", null, DataEvent.StateBack, StateName_Back); } public void stateEnd(ActionContext context) throws Exception { runState(context, "stateEnd", null, DataEvent.StateEnd, StateName_Back); } public void approve(ActionContext context) throws Exception { runApprove(context, ApproveOperate.Approve); } public void goEnd(ActionContext context) throws Exception { runApprove(context, ApproveOperate.GoEnd); } public void goBack(ActionContext context) throws Exception { runApprove(context, ApproveOperate.GoBack); } public void goHome(ActionContext context) throws Exception { runApprove(context, ApproveOperate.GoHome); } public void pullBack(ActionContext context) throws Exception { runApprove(context, ApproveOperate.PullBack); } public void runState(ActionContext context, String operator, ReferObject referObject, DataEvent dataEvent, String stateName) throws Exception { StateOperate operate = StateOperate.parse(operator); State state = null; try { DataReader dataReader = context.getDataReader(); DataWriter dataWriter = context.getDataWriter(); //1. 获取直接状态对象的 State Point DataPackage dataPackage = dataReader.getDataPackage(); StatePoint statePoint = getStatePoint(dataPackage, operator, dataWriter); if (statePoint == null) { context.terminateTask(); return; } //2. 改变直接状态对象的状态 state = doRunState(SenderType.Original, dataPackage, statePoint, operate, dataEvent, stateName); context.setStateCode(dataPackage.getName(), state.getCode()); //3. 如果有Host,处理对象的状态 DataPackage host = dataPackage.getHost(); StatePoint hostPoint = null; if (host != null) { hostPoint = getStatePoint(host, operator, dataWriter); if (hostPoint == null) { context.terminateTask(); return; } state = doRunState(SenderType.Host, host, hostPoint, operate, dataEvent, null); context.setStateCode(host.getName(), state.getCode()); } //4. 处理Refer对象状态 StatePoint referPoint = null; if (referObject == null) { referObject = new ReferObject(dataReader); } if (!referObject.isEmpty()) { DataPackage refer = DataPackage.getInstance(referObject.getDataName()); refer.setMasterId(referObject.getId()); refer.loadMasterFromDB(); referPoint = getStatePoint(refer, operator, dataWriter); if (referPoint == null) { context.terminateTask(); return; } state = doRunState(SenderType.Refer, refer, referPoint, operate, dataEvent, null); context.setStateCode(refer.getName(), state.getCode()); } //5. 如果直接直接状态对象配置了审批,启动审批流 if ((StateOperate.Commit == operate || StateOperate.toChange == operate || StateOperate.toClose == operate) && statePoint.isFireAppproveFlow()) { String dataName = dataPackage.getName(); String masterId = dataPackage.getMasterId(); IOnlineUser user = dataReader.getUser(); DetailState detailState = WorkingInstance.start(dataName, masterId, statePoint, hostPoint, referPoint, referObject, user, context); doRunDetailState(dataPackage, detailState); } //6. 返回直接状态对象的状态 String result = state.getName(); dataWriter.reportOneMessage("runState", "执行成功,当前状态为[" + result + "]"); } catch (Exception e) { context.terminateTask(); e.printStackTrace(); } } public void runApprove(ActionContext context, ApproveOperate operator) throws Exception { try { DataReader dataReader = context.getDataReader(); DataWriter dataWriter = context.getDataWriter(); //1. 获取当前审批流程 DataPackage dataPackage = dataReader.getDataPackage(); String dataName = dataPackage.getName(); StateMachine machine = MachineBucket.getMachineByDataName(dataName); Domain domain = dataReader.getDomain(); String masterId = domain.getId(); Entity masterEntity = dataPackage.getMasterEntity(); WorkingInstance flowInstance = WorkingInstance.getInstance(machine, masterId); if (flowInstance.isEmpty()) { logger.error("approval not exists, document id is {}", masterId); StateMessage message = StateMessage.getInstance(dataName, "approveFinished", "审批已结束,无法完成当前操作"); dataWriter.reportOneError("approve", message.getContent(dataPackage)); return; } //2. 获取 State Point String masterPointId = flowInstance.getMasterPointId(); StatePoint statePoint = StateMachine.getGlobalPoint(masterPointId); if (statePoint == null) { context.terminateTask(); logger.error("approve error, state point not exists: {}", masterPointId); return; } //3. 检查当前用户是否合法 flowInstance.gotoActiveStep(); IOnlineUser onlineUser = dataReader.getUser(); String creatorId = masterEntity.getString("creator_id"); if (!flowInstance.validateCurrentUser(operator, onlineUser, creatorId)) { logger.error("approval user not valid, document:{} , user:{}", masterId, onlineUser.getName()); StateMessage message = StateMessage.getInstance(dataName, "IllegalUser", "用户没有权限审批当前节点,无法审批"); dataWriter.reportOneError("approve", message.getContent(dataPackage)); return; } StepLocation position = null; ApprovalResult approvalResult = new ApprovalResult(); ReferObject referObject = new ReferObject(flowInstance.getMaster()); String remark = dataReader.getString("remark"); //4.1 审批通过 if (ApproveOperate.Approve == operator) { approvalResult = flowInstance.runStep(statePoint, onlineUser, operator, remark); position = approvalResult.getStepLoscation(); if (StepLocation.AtSuccess == position) { flowInstance.close(); logger.info("审批动作", StateOperate.StateEnd); approveRunState(context, statePoint, flowInstance, StateOperate.StateEnd, referObject, null); } } //4.2 审批通过(进入到状态Final) else if (ApproveOperate.GoEnd == operator) { approvalResult = flowInstance.runStep(statePoint, onlineUser, operator, remark); flowInstance.close(); approveRunState(context, statePoint, flowInstance, StateOperate.StateEnd, referObject, null); } //4.3 审批不通过(回退一步) else if (ApproveOperate.GoBack == operator) { approvalResult = flowInstance.runStep(statePoint, onlineUser, operator, remark); position = approvalResult.getStepLoscation(); if (StepLocation.AtHome == position) { flowInstance.close(); approveRunState(context, statePoint, flowInstance, StateOperate.StateFrom, referObject, StateName_Back); } } //4.4 审批不通过(回退到状态Home) else if (ApproveOperate.GoHome == operator) { approvalResult = flowInstance.runStep(statePoint, onlineUser, operator, remark); flowInstance.close(); approveRunState(context, statePoint, flowInstance, StateOperate.StateFrom, referObject, StateName_Back); } //4.5 申请人主动撤销(回退到状态Home) else if (ApproveOperate.PullBack == operator) { approvalResult = flowInstance.runStep(statePoint, onlineUser, operator, remark); flowInstance.close(); approveRunState(context, statePoint, flowInstance, StateOperate.StateFrom, referObject, StateName_Cancel); } DetailState detailState = approvalResult.getDetailState(); doRunDetailState(dataPackage, detailState); } catch (Exception e) { context.terminateTask(); e.printStackTrace(); } } public void approveRunState(ActionContext context, StatePoint statePoint, WorkingInstance flowInstance, StateOperate operate, ReferObject referObject, String stateName) throws Exception { try { DataReader dataReader = context.getDataReader(); if (referObject == null) { referObject = new ReferObject(dataReader); } DataPackage dataPackage = dataReader.getDataPackage(); State state = doRunState(SenderType.Original, dataPackage, statePoint, operate, null, stateName); context.setStateCode(dataPackage.getName(), state.getCode()); context.setStateCode(dataPackage.getName(), operate.name()); //1. 如果有Host,处理对象的状态 DataPackage host = dataPackage.getHost(); if (host != null) { String hostPointId = flowInstance.getHostPointId(); statePoint = StateMachine.getGlobalPoint(hostPointId); if (statePoint == null) { context.terminateTask(); logger.error("approve error, state point not exists: {}", hostPointId); return; } state = doRunState(SenderType.Host, host, statePoint, operate, null, null); context.setStateCode(host.getName(), state.getCode()); } //2. 处理Refer对象状态 if (referObject != null && !referObject.isEmpty()) { String referPointId = flowInstance.getReferPointId(); statePoint = StateMachine.getGlobalPoint(referPointId); if (statePoint == null) { context.terminateTask(); logger.error("approve error, state point not exists: {}", referPointId); return; } DataPackage refer = DataPackage.getInstance(referObject.getDataName()); refer.setMasterId(referObject.getId()); refer.loadMasterFromDB(); state = doRunState(SenderType.Refer, refer, statePoint, operate, null, stateName); context.setStateCode(refer.getName(), state.getCode()); } } catch (Exception e) { context.terminateTask(); e.printStackTrace(); } } private StatePoint getStatePoint(DataPackage dataPackage, String operator, DataWriter dataWriter) { //1. 获取单据头 String dataName = dataPackage.getName(); Entity master = dataPackage.getMasterEntity(DataSource.DB, DataSource.Request, DataSource.File); if (master == null) { if (dataWriter != null) { StateMessage message = StateMessage.getInstance(dataName, "documentNotExists", "单据数据不存在,状态机无法工作"); dataWriter.reportOneError("runState", message.getContent(dataPackage)); } return null; } //2. 获取状态机 StateMachine machine = MachineBucket.getMachineByDataName(dataName); if (machine == null) { if (dataWriter != null) { StateMessage message = StateMessage.getInstance(dataName, "MachineNotExists", "状态机不存在(" + dataName + ")"); dataWriter.reportOneError("runState", message.getContent(dataPackage)); } return null; } //3. 通过状态操作获取Point StateField stateField = machine.getStateField(); String fromStateCode = master.getString(stateField.getCode()); String fromStateName = master.getString(stateField.getName()); String key = StatePoint.createKey(fromStateCode, operator); StatePoint point = machine.getPoint(key); if (point != null) { return point; } //4. 通过审批流操作获取Point ApproveOperate approveOperate = ApproveOperate.parse(operator); if (ApproveOperate.Unknown == approveOperate) { return null; } point = machine.getPointByToState(fromStateCode); if (point == null) { if (dataWriter != null) { logger.error("invalid operator {}.{} on state {}", operator, fromStateCode); StateMessage message = StateMessage.getInstance(dataName, "PointNotExists", "状态(" + fromStateName + ")不支持当前操作"); dataWriter.reportOneError("runState", message.getContent(dataPackage)); } return null; } return point; } private State doRunState(SenderType senderType, DataPackage dataPackage, StatePoint point, StateOperate operate, DataEvent dataEvent, String stateName) throws Exception { StateMachine machine = point.getMachine(); StateField stateField = machine.getStateField(); State result = null; //1. 如果是提交操作 if (StateOperate.Commit == operate || StateOperate.toChange == operate || StateOperate.toClose == operate) { result = point.getToState(); } //2. 如果是回退操作 else if (StateOperate.StateEnd == operate) { result = point.getEndState(); } //3. 如果是回退操作 else if (StateOperate.StateFrom == operate) { result = State.stateCopy(point.getFromState()); if (SenderType.Original == senderType && (!Util.isEmpty(stateName))) { result.setName(stateName); } } if (result != null) { updateDocumentState(stateField, result, dataPackage, dataEvent); } return result; } private void doRunDetailState(DataPackage dataPackage, DetailState step) throws Exception { if (step == null) { return ; } DataObject masterObject = dataPackage.getMasterDataObject(); EntitySaver saver; //1. 设置状态 if (dataPackage.getMasterEntity() == null) { saver = masterObject.createEntitySaver(dataPackage.getMasterId()); } else{ saver = masterObject.createEntitySaver(dataPackage.getMasterEntity()); } saver.set("state_step_code", step.getCode()); saver.set("state_step_name", step.getName()); //2. 更新数据库 saver.update(); } private void updateDocumentState(StateField stateField, State toState, DataPackage dataPackage, DataEvent dataEvent) throws Exception { DataObject masterObject = dataPackage.getMasterDataObject(); EntitySaver saver; //1. 设置状态 if (dataPackage.getMasterEntity() == null) { saver = masterObject.createEntitySaver(dataPackage.getMasterId()); } else{ saver = masterObject.createEntitySaver(dataPackage.getMasterEntity()); } saver.set(stateField.getCode(), toState.getCode()); saver.set(stateField.getName(), toState.getName()); //2. 更新数据库 saver.update(dataEvent); } public void getApproveSteps(ActionContext context) throws Exception { DataReader dataReader = context.getDataReader(); Domain domain = dataReader.getDomain(); DataPackage dataPackage = domain.getDataPackage(); DataWriter dataWriter = context.getDataWriter(); //1. String dataName = domain.getDataName(); StateMachine machine = MachineBucket.getMachineByDataName(dataName); if (machine == null) { StateMessage message = StateMessage.getInstance(dataName, "MachineNotExists", "状态机不存在(" + dataName + ")"); dataWriter.reportOneError("runState", message.getContent(dataPackage)); return; } //2. 获取Point String fromStateCode = dataReader.getString("from_state"); String operator = dataReader.getString("operator"); String key = StatePoint.createKey(fromStateCode, operator); StatePoint point = machine.getPoint(key); if (point == null) { StateMessage message = StateMessage.getInstance(dataName, "PointNotExists", "状态(" + fromStateCode + ")不支持当前操作"); dataWriter.reportOneError("runState", message.getContent(dataPackage)); return; } //3. 获取步骤 IOnlineUser user = dataReader.getUser(); ApproveRuntime steps = point.getSteps(user, context); //4. 返回 dataWriter.addValue(steps); } public void getMachine(ActionContext context) throws Exception { DataReader dataReader = context.getDataReader(); Domain domain = dataReader.getDomain(); DataWriter dataWriter = context.getDataWriter(); String dataName = domain.getDataName(); StateMachine machine = MachineBucket.getMachineByDataName(dataName); dataWriter.addValue("machine", machine); } public void getOneMachine(ActionContext context) throws Exception { DataReader dataReader = context.getDataReader(); Domain domain = dataReader.getDomain(); DataWriter dataWriter = context.getDataWriter(); String id = domain.getId(); StateMachine machine = MachineBucket.getMachineById(id); dataWriter.addValue("machine", machine); } public void getPoints(ActionContext context) throws Exception { DataWriter dataWriter = context.getDataWriter(); MachineBucket bucket = MachineBucket.getInstance(); StatePoints statePointList = new StatePoints(); for (StateMachine machine : bucket) { statePointList.addAll(machine.getStatePoints()); } dataWriter.addValue(statePointList); } public void getPointsByApprove(ActionContext context) throws Exception { DataReader dataReader = context.getDataReader(); DataWriter dataWriter = context.getDataWriter(); String approveId = dataReader.getString("approve_id"); StatePoints bucket = StateMachineLoader.loadPointsByApproveId(approveId); dataWriter.addValue(bucket); } @Override public DataStates queryToStates(WorkFlowRuntime workflow, DataPackage dataPackage, String operator, DataWriter dataWriter) { DataStates result = new DataStates(); Operate operate = new Operate(operator); //1. 获取直接状态对象的 State String dataName = dataPackage.getName(); StateContext stateContext = workflow.getStateContext(); stateContext.setState(dataName, operate.getStateOperate().name()); StatePoint statePoint = getStatePoint(dataPackage, operator, null); if (statePoint != null) { String stateCode = getTargetStateCode(statePoint, operate.getInitialOperator()); result.setState(dataName, stateCode); } //2. 获取 Host 对象状态 DataPackage host = dataPackage.getHost(); if (host == null) { return result; } statePoint = getStatePoint(host, operator, null); if (statePoint != null) { String stateCode = getTargetStateCode(statePoint, operator); result.setState(host.getName(), stateCode); } return result; } private String getTargetStateCode(StatePoint statePoint, String operator) { StateOperate stateOperate = StateOperate.parse(operator); if (StateOperate.Commit == stateOperate || StateOperate.toChange == stateOperate || StateOperate.toClose == stateOperate) { return statePoint.getToCode(); } else if (StateOperate.StateEnd == stateOperate) { return statePoint.getEndCode(); } else if (StateOperate.StateFrom == stateOperate) { return statePoint.getFromCode(); } ApproveOperate approveOperate = ApproveOperate.parse(operator); if (ApproveOperate.Approve == approveOperate) { return statePoint.getEndCode(); } else if (ApproveOperate.GoEnd == approveOperate) { return statePoint.getEndCode(); } else if (ApproveOperate.GoHome == approveOperate) { return statePoint.getFromCode(); } else if (ApproveOperate.PullBack == approveOperate) { return statePoint.getFromCode(); } else if (ApproveOperate.GoBack == approveOperate) { return statePoint.getFromCode(); } return null; } @Override public boolean isInFreedom(DataPackage dataPackage) throws Exception { dataPackage.loadMasterFromDB(); PackageItem master = dataPackage.getMaster(); Entity entity = dataPackage.getMasterEntity(DataSource.DB); if (entity == null) { return true; } //1. 得到当前状态 String dataName = master.getName(); StateField stateField = MachineBucket.getStateField(dataName); String stateCode = entity.getString(stateField.getCode()); //2. 检查是否处于自由态 boolean inFreedom = MachineBucket.isInFreedom(dataName, stateCode); return inFreedom; } public String getName() { return StateCenter.class.getSimpleName(); } public void loadOneTargetOperator(String target, String operator) { String key = WorkStepKey.getObjectKey(target, operator); targetOperators.add(key); } public Set getTargetOperators() { return targetOperators; } }