org.eclipse.wst.command.internal.env.ui.widgets.SimpleCommandEngineManager.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.wst.command.internal.env.ui.widgets.SimpleCommandEngineManager.java

Source

/*******************************************************************************
 * Copyright (c) 2004, 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * IBM Corporation - initial API and implementation
 * yyyymmdd bug      Email and other contact information
 * -------- -------- -----------------------------------------------------------
 * 20060223   129232 pmoogk@ca.ibm.com - Peter Moogk
 * 20070314   176886 pmoogk@ca.ibm.com - Peter Moogk
 * 20070730   197144 pmoogk@ca.ibm.com - Peter Moogk, Pass progress monitor to undo commands.
 *******************************************************************************/
package org.eclipse.wst.command.internal.env.ui.widgets;

import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.wst.command.internal.env.core.data.DataFlowManager;
import org.eclipse.wst.command.internal.env.core.fragment.CommandFragment;
import org.eclipse.wst.command.internal.env.core.fragment.CommandFragmentEngine;
import org.eclipse.wst.command.internal.env.core.fragment.FragmentListener;
import org.eclipse.wst.command.internal.env.eclipse.BaseStatusHandler;
import org.eclipse.wst.command.internal.env.eclipse.EclipseEnvironment;
import org.eclipse.wst.common.environment.ILog;

/**
 * This class manages the execution of Commands in a flow of CommandFragments.
 * The bulk of this work is done by the CommandFragmentEngine.  The main job of
 * this class is run the fragments in a particular transactional environment.
 * A fragment has a method called doNotRunInTransaction which is used to determine
 * if its commands should be run in a transaction or not.  If this method returns
 * true(ie. not in a transaction) the Commands are wrapped in a IRunnableWithProgress.
 * If false( ie. in a transaction ) the Commands are wrapped in a WorkspaceModifyOperation. 
 *
 */
public class SimpleCommandEngineManager {
    protected CommandFragmentEngine engine_;
    protected DataFlowManager dataManager_;
    protected EclipseEnvironment environment_;

    private boolean foundStop_;
    private boolean doNotRunInTransaction_;

    public SimpleCommandEngineManager(EclipseEnvironment environment, DataFlowManager dataManager) {
        environment_ = environment;
        dataManager_ = dataManager;
    }

    /**
     * Sets the root fragment.  The execution engine will start executing commands
     * at the beginning of this root fragment.
     * 
     * @param root the root fragment.
     */
    public void setRootFragment(CommandFragment root) {
        engine_ = new CommandFragmentEngine(root, dataManager_, environment_);

        environment_.setCommandManager(engine_);

        engine_.setPeekFragmentListener(new FragmentListener() {
            public boolean notify(CommandFragment fragment) {
                return peekFragment(fragment);
            }
        });

        engine_.setNextFragmentListener(new FragmentListener() {
            public boolean notify(CommandFragment fragment) {
                return nextFragment(fragment);
            }
        });

        engine_.setAfterExecuteFragmentListener(new FragmentListener() {
            public boolean notify(CommandFragment fragment) {
                return afterExecuteNextFragment(fragment);
            }
        });

        engine_.setUndoFragmentListener(new FragmentListener() {
            public boolean notify(CommandFragment fragment) {
                return undoFragment(fragment);
            }
        });
    }

    protected boolean afterExecuteNextFragment(CommandFragment fragment) {
        boolean continueExecute = true;
        BaseStatusHandler statusHandler = (BaseStatusHandler) environment_.getStatusHandler();
        IStatus commandStatus = engine_.getLastStatus();
        IStatus handlerStatus = statusHandler.getStatus();

        if (commandStatus.getSeverity() == IStatus.ERROR && handlerStatus.getSeverity() != IStatus.ERROR) {
            // The command returned an error status for the engine to stop,
            // but the status handler did not have report and error.
            // Therefore, we will report this status returned by the command
            // if there is a message to display.  
            String errorMessage = commandStatus.getMessage();

            if (errorMessage != null && errorMessage.length() > 0) {
                statusHandler.reportError(commandStatus);
            }
        } else if (commandStatus.getSeverity() != IStatus.ERROR && handlerStatus.getSeverity() == IStatus.ERROR) {
            // The last command didn't return an error, but the status handler
            // did report and error.  Therefore, we should stop.
            continueExecute = false;
        }

        return continueExecute;
    }

    /**
     * The CommandFragmentEngine calls this method when it is peeking forward
     * in the fragments.  When peeking forward the command stack state in the
     * engine is not changes.
     * 
     * 
     * @param fragment the fragment that it is peeking at.
     * @return Indicates whether peeking should stop or not.
     */
    protected boolean peekFragment(CommandFragment fragment) {
        return true;
    }

    /**
     * The CommandFragmentEngine calls this method when it is moving forward
     * in the fragments.   When moving forward the command stack state is saved
     * at each fragment is traversed.
     * 
     * @param fragment the fragment that is being traversed.
     * @return indicates if the forward traversal should continue.  
     */
    protected boolean nextFragment(CommandFragment fragment) {
        if (fragment.doNotRunInTransaction() != doNotRunInTransaction_) {
            // The fragment is requesting a different transaction environment than
            // the one that we are in so we must stop and change environments.
            doNotRunInTransaction_ = fragment.doNotRunInTransaction();
            foundStop_ = false;
        }

        return foundStop_;
    }

    /**
     * This method is called for each fragment when the command engine is unwinding
     * its stack during an undo operation.
     * 
     * @param fragment  the fragment being undone.
     * @return returns true if the undo process should continue.
     */
    protected boolean undoFragment(CommandFragment fragment) {
        return true;
    }

    /**
     * This method undoes the commands that were executed in the runForwardToNextStop
     * method.
     * @param context the runnable context.
     * @return returns if all commands have been undone or not.
     */
    public boolean runUndoToNextStop(IRunnableContext context) {
        final boolean result[] = new boolean[] { true };

        IRunnableWithProgress undoOperation = new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor) {
                result[0] = engine_.undoToLastStop(monitor);
            }
        };

        try {
            if (context == null) {
                // We don't have a container yet so just run the operation.
                undoOperation.run(null);
            } else {
                // We have a container where this operation can run and have
                // its progress displayed.
                context.run(false, false, undoOperation);
            }
        } catch (Exception exc) {
            // For now we will ignore all exceptions.
        }

        return result[0];
    }

    /**
     * The method executes the CommandFragment commands in the context provided.
     * 
     * @param context the context
     * @return returns the status of executing the commands.
     */
    public IStatus runForwardToNextStop(IRunnableContext context) {
        IRunnableWithProgress operation = null;

        doNotRunInTransaction_ = false;

        do {
            // We will stop unless we are changing transaction modes.
            foundStop_ = true;

            if (doNotRunInTransaction_) {
                operation = getNoTransactionOperation();
            } else {
                operation = getTransactionOperation();
            }

            try {
                if (context == null) {
                    // We don't have a container yet so just run the operation.
                    operation.run(null);
                } else {
                    // We have a container where this operation can run and have
                    // its progress displayed.
                    context.run(false, false, operation);
                }
            } catch (InterruptedException exc) {
                //TODO should log these exceptions.
                exc.printStackTrace();
            } catch (InvocationTargetException exc) {
                //TODO should log these exceptions.
                exc.printStackTrace();
            }
        } while (!foundStop_);

        return engine_.getLastStatus();
    }

    private IRunnableWithProgress getTransactionOperation() {
        IRunnableWithProgress operation = new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor) {
                environment_.getLog().log(ILog.INFO, "command", 5002, this, "getTransactionOperation",
                        "Start of transaction");

                BaseStatusHandler statusHandler = (BaseStatusHandler) environment_.getStatusHandler();

                statusHandler.resetStatus();
                engine_.moveForwardToNextStop(monitor);

                environment_.getLog().log(ILog.INFO, "command", 5003, this, "getTransactionOperation",
                        "End of transaction");
            }
        };

        return operation;
    }

    private IRunnableWithProgress getNoTransactionOperation() {
        IRunnableWithProgress operation = new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor) {
                environment_.getLog().log(ILog.INFO, "command", 5085, this, "getNoTransactionOperation",
                        "Start of NON transaction");

                BaseStatusHandler statusHandler = (BaseStatusHandler) environment_.getStatusHandler();

                statusHandler.resetStatus();
                engine_.moveForwardToNextStop(monitor);
                environment_.getLog().log(ILog.INFO, "command", 5086, this, "getNoTransactionOperation",
                        "End of NON transaction");
            }
        };

        return operation;
    }
}