/**
   * Returns the (non-<code>null</code>) name of the left or right side if they are identical.
   * Otherwise both names are concatenated (separated with a slash ('/')).
   *
   * <p>Subclasses may re-implement to provide a different name for this node.
   *
   * @return the name of this node.
   */
  public String getName() {
    String right = null;
    if (fRight != null) right = fRight.getName();

    String left = null;
    if (fLeft != null) left = fLeft.getName();

    if (right == null && left == null) {
      if (fAncestor != null) return fAncestor.getName();
      return Utilities.getString("DiffNode.noName"); // $NON-NLS-1$
    }

    if (right == null) return left;
    if (left == null) return right;

    if (right.equals(left)) return right;

    String s1;
    String s2;

    if (fSwapSides) {
      s1 = left;
      s2 = right;
    } else {
      s1 = right;
      s2 = left;
    }

    String fmt = Utilities.getString("DiffNode.nameFormat"); // $NON-NLS-1$
    return MessageFormat.format(fmt, new String[] {s1, s2});
  }
  /**
   * This method is called from the <code>Viewer</code> method <code>inputChanged</code> to save any
   * unsaved changes of the old input.
   *
   * <p>The <code>ContentMergeViewer</code> implementation of this method calls <code>
   * saveContent(...)</code>. If confirmation has been turned on with <code>setConfirmSave(true)
   * </code>, a confirmation alert is posted before saving. Clients can override this method and are
   * free to decide whether they want to call the inherited method.
   *
   * @param newInput the new input of this viewer, or <code>null</code> if there is no new input
   * @param oldInput the old input element, or <code>null</code> if there was previously no input
   * @return <code>true</code> if saving was successful, or if the user didn't want to save (by
   *     pressing 'NO' in the confirmation dialog).
   * @since 2.0
   */
  protected boolean doSave(Object newInput, Object oldInput) {

    // before setting the new input we have to save the old
    if (isLeftDirty() || isRightDirty()) {

      if (Utilities.RUNNING_TESTS) {
        if (Utilities.TESTING_FLUSH_ON_COMPARE_INPUT_CHANGE) {
          flushContent(oldInput, null);
        }
      } else if (fConfirmSave) {
        // post alert
        Shell shell = fComposite.getShell();

        MessageDialog dialog =
            new MessageDialog(
                shell,
                Utilities.getString(getResourceBundle(), "saveDialog.title"), // $NON-NLS-1$
                null, // accept the default window icon
                Utilities.getString(getResourceBundle(), "saveDialog.message"), // $NON-NLS-1$
                MessageDialog.QUESTION,
                new String[] {
                  IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL,
                },
                0); // default
        // button
        // index

        switch (dialog.open()) { // open returns index of pressed button
          case 0:
            flushContent(oldInput, null);
            break;
          case 1:
            setLeftDirty(false);
            setRightDirty(false);
            break;
          case 2:
            throw new ViewerSwitchingCancelled();
        }
      } else flushContent(oldInput, null);
      return true;
    }
    return false;
  }
 /**
  * Returns the viewer's name.
  *
  * @return the viewer's name
  */
 public String getTitle() {
   return Utilities.getString(getResourceBundle(), "title"); // $NON-NLS-1$
 }