originalWorkflow.addConstraint(constraint); } }  logger.debug("re-publishing original workflow for restarting task: " + originalWorkflow); NewExpansion expansion = (NewExpansion) factory.createExpansion(task.getPlan(), task, originalWorkflow, null);
copiedWorkflow.addConstraint(constraint); } }  logger.debug("re-publishing original workflow for restarting task: " + copiedWorkflow); NewExpansion expansion = (NewExpansion) factory.createExpansion(task.getPlan(), task, copiedWorkflow, null);
    public void execute() {        stepsTable = (LittleJILStepsTable) stepsTableSubscription.first();        for (Enumeration exceptions = exceptionsSubscription.getAddedList();exceptions.hasMoreElements();) {            LittleJILException exception = (LittleJILException) exceptions.nextElement();            Task task = exception.getTask();            logger.debug("got exception for task " + task.getVerb());            Task failedTask = null;            if (exception.getNestedException() != null) {                failedTask = exception.getNestedException().getTask();            }            // look for any handlers defined for this task            // in general, tasks that have pre or post-reqs will have the handlers at the task level,            // and not in the parent task (ie the stepsTable.get(parent task) will be null)            // however, there is a 'corner case' with RESTART handlers, where we have to handler it at the            // "parent task" level so that the pre-req will be executed.            Step step = stepsTable.get(task);            Enumeration handlers = (step == null ? null : step.handlers());            if (handlers != null && handlers.hasMoreElements()) {                // TODO: look at multiple handlers (for now, just looking at first one)                // TODO: match exception types                HandlerBinding handlerBinding = (HandlerBinding) handlers.nextElement();                logger.debug("found handler of type " + handlerBinding.getControlFlow());                Task handlerTask = null;                if (handlerBinding.getTarget() != null && handlerBinding.getTarget() instanceof Step) {                    handlerTask = stepsTable.get((Step)handlerBinding.getTarget());                    logger.debug("found handler task: " + handlerTask.getVerb());                }                if (handlerBinding.getControlFlow() == HandlerBinding.CONTINUE) {                    if (failedTask == null) {                        // trying to continue a leaf task -- not valid                        logger.info("cannot continue a leaf task -- rethrowing exception");                        if (task.getWorkflow() != null) {                            blackboard.publishAdd(new LittleJILException(exception));                        }                        logger.info(">>> task " + task.getVerb() + " FAILED <<<");                        continue;   // with for (Enumeration exceptions...)                    }                    // get a workflow for the remaining tasks                    NewWorkflow remainingWorkflow = factory.newWorkflow();                    remainingWorkflow.setParentTask(task);                    extractDependentTasks(failedTask, failedTask.getWorkflow(), remainingWorkflow);                    // now remove the original workflow for this task, since we'll post a new one                    if (task.getPlanElement() != null) {                        logger.debug("removing expansion for task " + task.getVerb());                        blackboard.publishRemove(task.getPlanElement());                    }                    if (handlerTask != null) {                        remainingWorkflow.addTask(handlerTask);                        ((NewTask)handlerTask).setWorkflow(remainingWorkflow);                        // TODO: assuming that the first task returned by workflow.getTasks() is indeed the first one in order                        if (remainingWorkflow.getTasks().hasMoreElements()) {                            Task firstTask = (Task) remainingWorkflow.getTasks().nextElement();                            // add constraint so that the handler task gets done before this task                            NewConstraint constraint = factory.newConstraint();                            constraint.setConstrainingTask(handlerTask);                            constraint.setConstrainingAspect(AspectType.END_TIME);                            constraint.setConstrainedTask(firstTask);                            constraint.setConstrainedAspect(AspectType.START_TIME);                            constraint.setConstraintOrder(Constraint.BEFORE);                            remainingWorkflow.addConstraint(constraint);                        }                    }                    logger.debug("re-publishing expansion for continuing task");                    NewExpansion expansion = (NewExpansion) factory.createExpansion(task.getPlan(), task, remainingWorkflow, null);                    blackboard.publishAdd(expansion);                }                else if (handlerBinding.getControlFlow() == HandlerBinding.COMPLETE) {                    // first remove the existing expansion for this task, since we won't run any more tasks                    if (task.getPlanElement() != null) {                        logger.debug("removing expansion for task " + task.getVerb());                        blackboard.publishRemove(task.getPlanElement());                    }                    // now just add the handler task (if any)                    NewWorkflow workflow = factory.newWorkflow();                    workflow.setParentTask(task);                    if (handlerTask != null) {                        workflow.addTask(handlerTask);                        ((NewTask)handlerTask).setWorkflow(workflow);                        ((NewTask)handlerTask).setParentTask(task);                    }                    else {                        // TODO: need to add a dummy task?? otherwise there's nothing to do for this task and it never completes                    }                    NewExpansion expansion = (NewExpansion) factory.createExpansion(task.getPlan(), task, workflow, null);                    blackboard.publishAdd(task);                    blackboard.publishAdd(expansion);                }                else if (handlerBinding.getControlFlow() == HandlerBinding.RESTART) {                    // first check that this came from a failed task below us                    if (failedTask == null) {                        // trying to restart a leaf task -- not valid                        logger.info("cannot restart on a leaf task -- rethrowing exception");                        if (task.getWorkflow() != null) {                            blackboard.publishAdd(new LittleJILException(exception));                        }                        logger.info(">>> task " + task.getVerb() + " FAILED <<<");                        continue;   // with for (Enumeration exceptions...)                    }                    // make a copy of this workflow, which we will post to restart the task                    Expansion originalExpansion = (Expansion) task.getPlanElement();                    NewWorkflow originalWorkflow = copyWorkflow(originalExpansion.getWorkflow());                    originalWorkflow.setParentTask(task);                    // now remove the existing expansion                    if (task.getPlanElement() != null) {                        logger.debug("removing expansion for task " + task.getVerb());                        blackboard.publishRemove(task.getPlanElement());                    }                    // following the "corner case" described above, if this task has pre-reqs, and                    // it has a RESTART handler, and it's not a "parent" task, then we throw it up.                    if (step.getPrerequisite() != null && !task.getVerb().toString().endsWith("Parent")) {                        // throw it up to the parent                        logger.debug("deferring restart handler to parent");                        // we also need to remove this task's start_time pref, otherwise the new posted expansion                        // will start right away                        if (task.getPreference(AspectType.START_TIME) != null && task.getPreference(AspectType.END_TIME) != null) {                            logger.debug("resetting preferences of task " + task.getVerb());                            Vector v = new Vector();                            v.add(task.getPreference(AspectType.END_TIME));                            ((NewTask)task).setPreferences(v.elements());                        }                        // re-publish the task's workflow                        blackboard.publishChange(task);                        blackboard.publishAdd(factory.createExpansion(task.getPlan(), task, originalWorkflow, null));                        blackboard.publishAdd(new LittleJILException(exception));                        continue;   // with the for (Enumeration exceptions...)                    }                    // if there is a handler task, and it's not already in the workflow, we want to insert that first....                    // (it could be already if this is the second time we are restarting the task)                    if (handlerTask != null && !containsTask(originalWorkflow,handlerTask)) {                        originalWorkflow.addTask(handlerTask);                        ((NewTask)handlerTask).setWorkflow(originalWorkflow);                        // TODO: I'm assuming that the first task returned by workflow.getTasks() is indeed the first one in order                        if (originalWorkflow.getTasks().hasMoreElements()) {                            Task firstTask = (Task) originalWorkflow.getTasks().nextElement();                            logger.debug("adding constraint so that " + handlerTask.getVerb() + " goes before " +                                    firstTask.getVerb());                            // add constraint so that the handler task gets done before this task                            NewConstraint constraint = factory.newConstraint();                            constraint.setConstrainingTask(handlerTask);                            constraint.setConstrainingAspect(AspectType.END_TIME);                            constraint.setConstrainedTask(firstTask);                            constraint.setConstrainedAspect(AspectType.START_TIME);                            constraint.setConstraintOrder(Constraint.BEFORE);                            originalWorkflow.addConstraint(constraint);                        }                    }                    logger.debug("re-publishing original workflow for restarting task: " + originalWorkflow);                    NewExpansion expansion = (NewExpansion) factory.createExpansion(task.getPlan(), task, originalWorkflow, null);                    blackboard.publishChange(task);                    blackboard.publishAdd(expansion);                    logger.debug("published expansion " + expansion);                }                else /*if (handlerBinding.getControlFlow() == HandlerBinding.RETHROW)*/ {                    // default action is to RETHROW the exception                    // remove the current expansion, if any                    if (task.getPlanElement() != null) {                        logger.debug("removing expansion for task " + task.getVerb());                        blackboard.publishRemove(task.getPlanElement());                    }                    NewWorkflow workflow = factory.newWorkflow();                    workflow.setParentTask(task);                    if (handlerTask != null) {                        workflow.addTask(handlerTask);                        ((NewTask)handlerTask).setWorkflow(workflow);                        ((NewTask)handlerTask).setParentTask(task);                        NewExpansion expansion = (NewExpansion) factory.createExpansion(task.getPlan(), task, workflow, null);                        blackboard.publishAdd(task);                        blackboard.publishAdd(expansion);                    }                    logger.info("rethrowing exception");                    // and re-throw the exception, too                    if (task.getWorkflow() != null) {                        blackboard.publishAdd(new LittleJILException(exception));                    }                    logger.info(">>> task " + task.getVerb() + " FAILED <<<");                }            }            else {                // remove the current expansion, if any                if (task.getPlanElement() != null) {                    logger.debug("removing expansion for task " + task.getVerb());                    blackboard.publishRemove(task.getPlanElement());                }                // exception is not handled, re-throw to the parent (if the task has a parent (ie, if task has workflow))                if (task.getWorkflow() != null) {                    blackboard.publishAdd(new LittleJILException(exception));                }                logger.info(">>> task " + task.getVerb() + " FAILED <<<");            }        }    }