Java tutorial
/** * Copyright 2007-2010 ? * All rights reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses. * */ package org.fireflow.pdl.fpdl.behavior; import java.util.Date; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.fireflow.client.WorkflowSession; import org.fireflow.client.impl.WorkflowSessionLocalImpl; import org.fireflow.engine.context.RuntimeContext; import org.fireflow.engine.entity.runtime.ActivityInstance; import org.fireflow.engine.entity.runtime.ProcessInstance; import org.fireflow.engine.entity.runtime.ScheduleJob; import org.fireflow.engine.entity.runtime.ScheduleJobState; import org.fireflow.engine.entity.runtime.impl.ScheduleJobImpl; import org.fireflow.engine.exception.EngineException; import org.fireflow.engine.invocation.TimerOperationName; import org.fireflow.engine.modules.beanfactory.BeanFactory; import org.fireflow.engine.modules.calendar.CalendarService; import org.fireflow.engine.modules.persistence.ActivityInstancePersister; import org.fireflow.engine.modules.persistence.PersistenceService; import org.fireflow.engine.modules.persistence.ProcessInstancePersister; import org.fireflow.engine.modules.persistence.ScheduleJobPersister; import org.fireflow.engine.modules.schedule.Scheduler; import org.fireflow.engine.modules.script.ScriptEngineHelper; import org.fireflow.model.ModelElement; import org.fireflow.model.data.Expression; import org.fireflow.pdl.fpdl.behavior.router.SplitEvaluator; import org.fireflow.pdl.fpdl.behavior.router.impl.OrSplitEvaluator; import org.fireflow.pdl.fpdl.misc.FpdlConstants; import org.fireflow.pdl.fpdl.process.Node; import org.fireflow.pdl.fpdl.process.StartNode; import org.fireflow.pdl.fpdl.process.SubProcess; import org.fireflow.pdl.fpdl.process.Synchronizer; import org.fireflow.pdl.fpdl.process.features.Feature; import org.fireflow.pdl.fpdl.process.features.startnode.CatchCompensationFeature; import org.fireflow.pdl.fpdl.process.features.startnode.CatchFaultFeature; import org.fireflow.pdl.fpdl.process.features.startnode.NormalStartFeature; import org.fireflow.pdl.fpdl.process.features.startnode.TimerStartFeature; import org.fireflow.pvm.kernel.PObjectKey; import org.fireflow.pvm.kernel.Token; import org.fireflow.pvm.kernel.TokenState; import org.fireflow.pvm.pdllogic.BusinessStatus; import org.fireflow.pvm.pdllogic.ContinueDirection; import org.fireflow.pvm.pdllogic.ExecuteResult; import org.fireflow.pvm.pdllogic.WorkflowBehavior; /** * @author ? * @version 2.0 */ public class StartNodeBehavior extends AbsSynchronizerBehavior implements WorkflowBehavior { private static Log log = LogFactory.getLog(StartNodeBehavior.class); protected List<String> determineNextTransitions(WorkflowSession session, Token token4Node, Node node) { RuntimeContext runtimeContext = ((WorkflowSessionLocalImpl) session).getRuntimeContext(); BeanFactory beanFactory = runtimeContext.getEngineModule(BeanFactory.class, FpdlConstants.PROCESS_TYPE_FPDL20); String className = OrSplitEvaluator.class.getName(); SplitEvaluator splitEvaluator = this.splitEvaluatorRegistry.get(className); if (splitEvaluator == null) { splitEvaluator = (SplitEvaluator) beanFactory.createBean(className); splitEvaluatorRegistry.put(className, splitEvaluator); } return splitEvaluator.determineNextTransitions(session, token4Node, node); } public int canBeFired(WorkflowSession session, Token token, List<Token> liblings, Synchronizer synchronizer) { return token.getStepNumber(); } protected boolean hasAlivePreviousNode(WorkflowSession session, Token token, Node thisNode) { return false; } @Override public ExecuteResult execute(WorkflowSession session, Token token, Object workflowElement) { WorkflowSessionLocalImpl sessionLocalImpl = (WorkflowSessionLocalImpl) session; ActivityInstance activityInstance = sessionLocalImpl.getCurrentActivityInstance(); StartNode startNode = (StartNode) workflowElement; Feature dec = startNode.getFeature(); // ??? // ??TimerStartFeatureJmsMessageStartFeature // WebserviceStartFeature???Startnode.execute(...)? SubProcess process = (SubProcess) startNode.getParent(); Node entry = process.getEntry(); if (entry != null && entry.getId().equals(startNode.getId())) { ExecuteResult result = new ExecuteResult(); result.setStatus(BusinessStatus.COMPLETED); return result; } // NormalStartFeature CatchFaultFeatureCatchCompensationFeature // ???? else if (dec == null || dec instanceof NormalStartFeature || dec instanceof CatchFaultFeature || dec instanceof CatchCompensationFeature) { ExecuteResult result = new ExecuteResult(); result.setStatus(BusinessStatus.COMPLETED); return result; } // ??ActivityTimerStartFeature else if (dec != null && dec instanceof TimerStartFeature) { // 1?currentActivityInstancecurrentProcessInstance ProcessInstance oldProcInst = sessionLocalImpl.getCurrentProcessInstance(); ActivityInstance oldActInst = sessionLocalImpl.getCurrentActivityInstance(); RuntimeContext ctx = ((WorkflowSessionLocalImpl) session).getRuntimeContext(); PersistenceService persistenceService = ctx.getEngineModule(PersistenceService.class, FpdlConstants.PROCESS_TYPE_FPDL20); ActivityInstancePersister actInstPersistenceService = persistenceService.getActivityInstancePersister(); ProcessInstancePersister processInstancePersister = persistenceService.getProcessInstancePersister(); if (oldProcInst == null || !oldProcInst.getId().equals(token.getProcessInstanceId())) { ProcessInstance procInst = processInstancePersister.fetch(ProcessInstance.class, token.getProcessInstanceId()); ((WorkflowSessionLocalImpl) session).setCurrentProcessInstance(procInst); } if (oldActInst == null || !oldActInst.getId().equals(token.getElementInstanceId())) { ActivityInstance actInst = actInstPersistenceService.fetch(ActivityInstance.class, token.getElementInstanceId()); ((WorkflowSessionLocalImpl) session).setCurrentActivityInstance(actInst); } try { // 2? TimerStartFeature timerDecorator = (TimerStartFeature) dec; createScheduleJob(session, activityInstance, timerDecorator); ExecuteResult result = new ExecuteResult(); result.setStatus(BusinessStatus.RUNNING); return result; } finally { ((WorkflowSessionLocalImpl) session).setCurrentProcessInstance(oldProcInst); ((WorkflowSessionLocalImpl) session).setCurrentActivityInstance(oldActInst); } } else { // ??? ExecuteResult result = new ExecuteResult(); result.setStatus(BusinessStatus.COMPLETED); return result; } } private void createScheduleJob(WorkflowSession session, ActivityInstance activityInstance, TimerStartFeature timerDecorator) { RuntimeContext runtimeContext = ((WorkflowSessionLocalImpl) session).getRuntimeContext(); CalendarService calendarService = runtimeContext.getEngineModule(CalendarService.class, activityInstance.getProcessType()); WorkflowSessionLocalImpl sessionLocalImpl = (WorkflowSessionLocalImpl) session; ProcessInstance processInstance = sessionLocalImpl.getCurrentProcessInstance(); String operationName = timerDecorator.getTimerOperationName().name(); String triggerType = null; String triggerExpression = null; // TODO ScheduleJob if (TimerOperationName.TRIGGERED_ONLY_ONCE.name().equalsIgnoreCase(operationName.trim())) { triggerType = ScheduleJob.STARTTIME_REPEATCOUNT_INTERVAL; triggerExpression = triggeredOnlyOnce(session, activityInstance, timerDecorator); } else if (TimerOperationName.TRIGGERED_BY_REPEAT_COUNT.name().equalsIgnoreCase(operationName.trim())) { triggerType = ScheduleJob.STARTTIME_REPEATCOUNT_INTERVAL; triggerExpression = triggeredByRepeatCount(session, activityInstance, timerDecorator); } else if (TimerOperationName.TRIGGERED_BY_STARTTIME_ENDTIME.name() .equalsIgnoreCase(operationName.trim())) { triggerType = ScheduleJob.STARTTIME_ENDTIME_INTERVAL; triggerExpression = triggerdByStarttimeEndtime(session, activityInstance, timerDecorator); } else if (TimerOperationName.TRIGGERED_BY_CRON.name().equalsIgnoreCase(operationName.trim())) { triggerType = ScheduleJob.CRON; triggerExpression = triggeredByCron(session, activityInstance, timerDecorator); } else { log.error("Unsupported timer operation '" + operationName + "'."); throw new EngineException(activityInstance, "Unsupported timer operation '" + operationName + "'."); } ScheduleJobImpl scheduleJob = new ScheduleJobImpl(); scheduleJob.setName(activityInstance.getName()); scheduleJob.setDisplayName(activityInstance.getDisplayName()); scheduleJob.setState(ScheduleJobState.RUNNING); scheduleJob.setActivityInstanceId(activityInstance.getId()); if (timerDecorator.getAttachedToActivity() == null) {// ??Activity?StartNode scheduleJob.setCreateNewProcessInstance(true); } else { scheduleJob.setCreateNewProcessInstance(false); } scheduleJob.setCancelAttachedToActivity(timerDecorator.getCancelAttachedToActivity()); scheduleJob.setProcessId(activityInstance.getProcessId()); scheduleJob.setProcessType(activityInstance.getProcessType()); scheduleJob.setVersion(activityInstance.getVersion()); scheduleJob.setTriggerType(triggerType); scheduleJob.setTriggerExpression(triggerExpression); scheduleJob.setCreatedTime(calendarService.getSysDate()); // ? PersistenceService persistenceService = runtimeContext.getEngineModule(PersistenceService.class, activityInstance.getProcessType()); ScheduleJobPersister persister = persistenceService.getScheduleJobPersister(); persister.saveOrUpdate(scheduleJob); // Scheduler scheduler = runtimeContext.getEngineModule(Scheduler.class, activityInstance.getProcessType()); scheduler.schedule(scheduleJob, runtimeContext); } private String triggeredOnlyOnce(WorkflowSession session, ActivityInstance activityInstance, TimerStartFeature timerDecorator) throws EngineException { RuntimeContext runtimeContext = ((WorkflowSessionLocalImpl) session).getRuntimeContext(); WorkflowSessionLocalImpl sessionLocalImpl = (WorkflowSessionLocalImpl) session; ProcessInstance processInstance = sessionLocalImpl.getCurrentProcessInstance(); Expression theStartTimeExpression = timerDecorator.getStartTimeExpression(); Expression theRepeatCountExpression = null; Expression theRepeatIntervalExpression = null; if (theStartTimeExpression == null || theStartTimeExpression.getBody() == null || theStartTimeExpression.getBody().trim().equals("")) { log.error("The start time expression is null"); throw new EngineException(activityInstance, "The start time expression is null"); } Map<String, Object> varContext = ScriptEngineHelper.fulfillScriptContext(session, runtimeContext, processInstance, activityInstance); Date startTime = null; Integer repeatCount = 0; Integer repeatInterval = 0; startTime = (Date) ScriptEngineHelper.evaluateExpression(runtimeContext, theStartTimeExpression, varContext); StringBuffer buf = new StringBuffer(); buf.append(startTime.getTime()).append("|").append(repeatCount.toString()).append("|") .append(repeatInterval); return buf.toString(); } private String triggeredByRepeatCount(WorkflowSession session, ActivityInstance activityInstance, TimerStartFeature timerDecorator) throws EngineException { RuntimeContext runtimeContext = ((WorkflowSessionLocalImpl) session).getRuntimeContext(); WorkflowSessionLocalImpl sessionLocalImpl = (WorkflowSessionLocalImpl) session; ProcessInstance processInstance = sessionLocalImpl.getCurrentProcessInstance(); Expression theStartTimeExpression = timerDecorator.getStartTimeExpression(); Expression theRepeatCountExpression = timerDecorator.getRepeatCountExpression(); Expression theRepeatIntervalExpression = timerDecorator.getRepeatIntervalExpression(); if (theStartTimeExpression == null || theStartTimeExpression.getBody() == null || theStartTimeExpression.getBody().trim().equals("")) { log.error("The start time expression is null"); throw new EngineException(activityInstance, "The start time expression is null"); } Map<String, Object> varContext = ScriptEngineHelper.fulfillScriptContext(session, runtimeContext, processInstance, activityInstance); Date startTime = null; Integer repeatCount = 0; Integer repeatInterval = 0; startTime = (Date) ScriptEngineHelper.evaluateExpression(runtimeContext, theStartTimeExpression, varContext); if (theRepeatCountExpression != null && theRepeatCountExpression.getBody() != null && !theRepeatCountExpression.getBody().trim().equals("")) { repeatCount = (Integer) ScriptEngineHelper.evaluateExpression(runtimeContext, theRepeatCountExpression, varContext); } if (theRepeatIntervalExpression != null && theRepeatIntervalExpression.getBody() != null && !theRepeatIntervalExpression.getBody().trim().equals("")) { repeatInterval = (Integer) ScriptEngineHelper.evaluateExpression(runtimeContext, theRepeatIntervalExpression, varContext); } StringBuffer buf = new StringBuffer(); buf.append(startTime.getTime()).append("|").append(repeatCount.toString()).append("|") .append(repeatInterval); return buf.toString(); } public String triggerdByStarttimeEndtime(WorkflowSession session, ActivityInstance activityInstance, TimerStartFeature timerDecorator) throws EngineException { RuntimeContext runtimeContext = ((WorkflowSessionLocalImpl) session).getRuntimeContext(); WorkflowSessionLocalImpl sessionLocalImpl = (WorkflowSessionLocalImpl) session; ProcessInstance processInstance = sessionLocalImpl.getCurrentProcessInstance(); Expression theStartTimeExpression = timerDecorator.getStartTimeExpression(); Expression theEndTimeExpression = timerDecorator.getEndTimeExpression(); Expression theRepeatIntervalExpression = timerDecorator.getRepeatCountExpression(); if (theStartTimeExpression == null || theStartTimeExpression.getBody() == null || theStartTimeExpression.getBody().trim().equals("")) { log.error("The start time expression is null"); throw new EngineException(activityInstance, "The start time expression is null"); } Map<String, Object> varContext = ScriptEngineHelper.fulfillScriptContext(session, runtimeContext, processInstance, activityInstance); Date startTime = null; Date endTime = null; Integer repeatInterval = 0; startTime = (Date) ScriptEngineHelper.evaluateExpression(runtimeContext, theStartTimeExpression, varContext); if (theEndTimeExpression != null && theEndTimeExpression.getBody() != null && !theEndTimeExpression.getBody().trim().equals("")) { endTime = (Date) ScriptEngineHelper.evaluateExpression(runtimeContext, theEndTimeExpression, varContext); } if (theRepeatIntervalExpression != null && theRepeatIntervalExpression.getBody() != null && !theRepeatIntervalExpression.getBody().trim().equals("")) { repeatInterval = (Integer) ScriptEngineHelper.evaluateExpression(runtimeContext, theRepeatIntervalExpression, varContext); } StringBuffer buf = new StringBuffer(); buf.append(startTime.getTime()).append("|").append(endTime == null ? "null" : endTime.getTime()).append("|") .append(repeatInterval); return buf.toString(); } private String triggeredByCron(WorkflowSession session, ActivityInstance activityInstance, TimerStartFeature timerDecorator) throws EngineException { RuntimeContext runtimeContext = ((WorkflowSessionLocalImpl) session).getRuntimeContext(); WorkflowSessionLocalImpl sessionLocalImpl = (WorkflowSessionLocalImpl) session; ProcessInstance processInstance = sessionLocalImpl.getCurrentProcessInstance(); Expression theCronExpression = timerDecorator.getCronExpression(); if (theCronExpression == null) { log.error("The cron expression is null!"); throw new EngineException(activityInstance, "The cron expression is null"); } Map<String, Object> varContext = ScriptEngineHelper.fulfillScriptContext(session, runtimeContext, processInstance, activityInstance); try { Object obj = ScriptEngineHelper.evaluateExpression(runtimeContext, theCronExpression, varContext); return (String) obj; } catch (ClassCastException e) { log.error("The result of the cron expression is not a java String object.", e); throw new EngineException(activityInstance, "The result of the cron expression is not a java String object." + e.getMessage()); } } public ContinueDirection continueOn(WorkflowSession session, Token token, Object workflowElement) { // ??? if (token.getState().getValue() != TokenState.RUNNING.getValue()) { return ContinueDirection.closeMe(); } List<PObjectKey> nextPObjectKeys = determineNextPObjectKeys(session, token, workflowElement); ContinueDirection direction = null; // start StartNode startNode = (StartNode) workflowElement; Feature dec = startNode.getFeature(); // ??TimerStartDecorator if (dec == null || !(dec instanceof TimerStartFeature)) { direction = ContinueDirection.closeMe(); direction.setNextProcessObjectKeys(nextPObjectKeys); return direction; } else { // ??Activitytimer?ContinueDirection.startNextAndWaitingForClose(); SubProcess subflow = (SubProcess) ((ModelElement) startNode).getParent(); Node entry = subflow.getEntry(); if (entry != null && entry.getId().equals(startNode.getId())) { direction = ContinueDirection.closeMe(); direction.setNextProcessObjectKeys(nextPObjectKeys); return direction; } else { direction = ContinueDirection.startNextAndWaitingForClose(); direction.setNextProcessObjectKeys(nextPObjectKeys); } } return direction; } }