/*
   * Determine whether the operation in question is still valid.
   */
  private IStatus proceedWithOperation(
      final IUndoableOperation operation,
      final IOperationHistory history,
      final IAdaptable uiInfo,
      final int doing) {

    // return immediately if the operation is not relevant
    if (!operation.hasContext(context)) {
      return Status.OK_STATUS;
    }

    // if the operation does not support advanced validation,
    // then we assume it is valid.
    if (doing == EXECUTING) {
      if (!(operation instanceof IAdvancedUndoableOperation2)) {
        return Status.OK_STATUS;
      }
    } else {
      if (!(operation instanceof IAdvancedUndoableOperation)) {
        return Status.OK_STATUS;
      }
    }

    // The next two methods make a number of UI calls, so we wrap the
    // whole thing up in a syncExec.
    final IStatus[] status = new IStatus[1];
    Workbench.getInstance()
        .getDisplay()
        .syncExec(
            new Runnable() {
              public void run() {
                // Compute the undoable or redoable status
                status[0] = computeOperationStatus(operation, history, uiInfo, doing);

                // Report non-OK statuses to the user. In some cases, the user
                // may choose to proceed, and the returned status will be
                // different than what is reported.
                if (!status[0].isOK()) {
                  status[0] = reportAndInterpretStatus(status[0], uiInfo, operation, doing);
                }
              }
            });

    // If the operation is still not OK, inform the history that the
    // operation has changed, since it was previously believed to be valid.
    // We rely here on the ability of an IAdvancedUndoableOperation to
    // correctly report canUndo() and canRedo() once the undoable and
    // redoable status have been computed.
    if (!status[0].isOK()) {
      history.operationChanged(operation);
    }
    return status[0];
  }