/**
   * This notifies the user that they are about to lose entered data (i.e. they've made changes and
   * are about to a) change classes or b) go to another entry), and allows them to save their data
   * if they so choose...
   */
  public void checkForUnsavedChanges() {
    if (dataSource == null || dataSource.isActive() == false)
      return; // no point prompting - nothing to save with!

    /*
     *    Only ever check the entry once (sometimes promptForSave can be called
     *    multiple time - remember that the 'save' function gets called by a
     *    separate thread).
     */

    if (tableData.changedByUser()) {
      String save = CBIntText.get("Save");
      String discard = CBIntText.get("Discard");

      int result =
          JOptionPane.showOptionDialog(
              owner,
              CBIntText.get("Submit changes to the Directory?"),
              CBIntText.get("Save Data"),
              JOptionPane.DEFAULT_OPTION,
              JOptionPane.QUESTION_MESSAGE,
              null,
              new Object[] {save, discard},
              save);
      if (result == 0) {
        writeTableData(); // nb - this queues a request to the directory
      }
    }
  }
  public void setVisible(boolean state) {
    super.setVisible(state);

    // has to be *after* previous call for SwingMagic reasons.
    if (state == false
        && tableData.changedByUser()) // user made changes - were they saved?  (i.e., are we
    {
      /*
       *    The setVisible() method may be called multiple time.  Only prompt
       *    the user the first time.
       */
      checkForUnsavedChanges();
    }
  }
  private void displayEntry(
      DXEntry entry, DataBrokerQueryInterface ds, boolean storeOriginalEntry) {
    myEditor.stopCellEditing();

    //        checkedDN = null; // hack - resets promptForSave.
    // Store original Entry for reset
    if (entry != null && storeOriginalEntry && entry.getStatus() == DXEntry.NORMAL)
      originalEntry = new DXEntry(entry);

    // Set the globals...
    currentEntry = entry;
    dataSource = ds;

    if (entry != null && entry.size() == 0) {
      // If there is an entry and its size is zero - it's probably a virtual entry.
      // We need to give the user the option of adding an object class to it i.e. so that
      // it can be added to the directory as a real entry.
      //
      // Disable all the buttons except the 'Change Class' button - but rename this button
      // to 'Add Class' so the user hopefully has a bit more of an idea about what is going on.

      // Sets editor to a blank screen...
      tableData.clear();

      // Disable all buttons except the 'Change Class' button - rename this one...
      submit.setEnabled(false);
      reset.setEnabled(false);
      changeClass.setText(CBIntText.get("Add Class"));
      changeClass.setEnabled(true);
      opAttrs.setEnabled(false);

      virtualEntry = true;

      return;
    }

    virtualEntry = false;

    // Isn't a virtual entry...
    if (entry != null) currentDN = entry.getDN();

    // May have been changed to 'Add Class'...
    changeClass.setText(CBIntText.get("Change Class"));

    // Some quick faffing around, to see if we're coming back from a
    // change classes operation.
    if (classChangedOriginalEntry != null) {
      // If they have the same name, then we're reviewing the same entry - otherwise we've moved on
      if (entry == null || entry.getDN().equals(classChangedOriginalEntry.getDN()) == false)
        classChangedOriginalEntry = null;
    }

    /*
     *    Check that we're not displaying a new entry, and leaving unsaved changes
     *    behind.
     *
     *    This turns out to be quite tricky, and involves a bunch 'o special cases.
     *
     *    First check whether the table data has changed (if not, do nothing)
     *    ->  if the new entry is null, prompt user to save
     *    ->  OR if the DN has changed, and it wasn't due to a rename, prompt user to save
     *
     */
    if (tableData.changedByUser()) // user made changes - were they saved?  (i.e., are we
    { // displaying the result of those changes?)
      boolean prompt = false;

      DXEntry oldEntry = tableData.getOldEntry();

      if (oldEntry != null) {
        /*
         *    The code below is simply checking to see if the name of the
         *    new entry is different from the old entry, and if it is,
         *    whether that's due to the old entry being renamed.
         */
        if (entry == null) {
          prompt = true;
        }
        // TE: added the isEmpty check see bug: 3194.
        else if (!oldEntry.getDN().isEmpty() && entry.getDN().equals(oldEntry.getDN()) == false) {
          DN oldParent = oldEntry.getDN().getParent();

          DN newParent = entry.getDN().getParent();

          if (oldParent.equals(newParent) == false) {
            prompt = true;
          } else {
            if (entry.getDN().getLowestRDN().equals(tableData.getRDN()) == false) {
              prompt = true;
            }
          }
        }

        if (prompt) // yes, there is a risk of data loss - prompt the user.
        {
          checkForUnsavedChanges(); // see if the user wants to save their data
        }
      }
    }

    myEditor.setDataSource(
        ds); // Sets the DataBrokerQueryInterface in AttributeValueCellEditor used to get the syntax
             // of attributes.

    // only enable buttons if DataBrokerQueryInterface
    // is valid *and* we can modify data...

    if (dataSource == null || entry == null || dataSource.isModifiable() == false) {
      setReadWrite(false, entry);
    } else {
      setReadWrite(true, entry);
    }

    //        myEditor.stopCellEditing();

    if (entry != null) {
      entry.expandAllAttributes();
      currentDN = entry.getDN();

      tableData.insertAttributes(entry);
      popupTableTool.setDN(currentDN); // Sets the DN in SmartPopupTableTool.
      myEditor.setDN(
          currentDN); // Sets the DN in the attributeValueCellEditor which can be used to identify
                      // the entry that is being modified/
    } else {
      tableData.clear(); // Sets editor to a blank screen.
    }

    tableScroller.getVerticalScrollBar().setValue(0); // Sets the scroll bar back to the top.
  }