/** Event handler for this dialog. */
  public void actionPerformed(ActionEvent e) {
    // Force table to accept any partial edits.
    if (metadataTable.isEditing()) {
      metadataTable.getCellEditor().stopCellEditing();
    }

    // Apply new/modified attributes to the object.
    Map currentObjectMetadata = currentObject.getModifiableMetadata();
    Set obsoleteMetadataItems = currentObjectMetadata.keySet();
    for (int row = 0; row < metadataTable.getRowCount(); row++) {
      String name = (String) objectMetadataTableModel.getValueAt(row, 0);
      String value = (String) objectMetadataTableModel.getValueAt(row, 1);
      currentObject.addMetadata(name, value);
      obsoleteMetadataItems.remove(name);
    }
    // Remove obsolete attributes.
    Iterator obsoleteNamesIter = obsoleteMetadataItems.iterator();
    while (obsoleteNamesIter.hasNext()) {
      currentObject.removeMetadata((String) obsoleteNamesIter.next());
    }

    if (e.getSource().equals(nextObjectButton)) {
      currentObjectIndex++;
      displayObjectProperties();
    } else if (e.getSource().equals(previousObjectButton)) {
      currentObjectIndex--;
      displayObjectProperties();
    } else if ("OK".equals(e.getActionCommand())) {
      modifyActionApproved = isModifyMode();
      this.setVisible(false);
    } else if ("Cancel".equals(e.getActionCommand())) {
      modifyActionApproved = false;
      this.setVisible(false);
    } else if ("addMetadataItem".equals(e.getActionCommand())) {
      int newRowNumber = metadataTable.getRowCount() + 1;
      objectMetadataTableModel.addRow(
          new String[] {"name-" + newRowNumber, "value-" + newRowNumber});
    } else if ("removeMetadataItem".equals(e.getActionCommand())) {
      int[] rows = metadataTable.getSelectedRows();
      for (int i = rows.length - 1; i >= 0; i--) {
        int modelIndex = metadataTableSorter.modelIndex(rows[i]);
        objectMetadataTableModel.removeRow(modelIndex);
      }
    }
  }
  /**
   * Update the dialog to display the attributes of a single object. The user may choose which
   * object to display by iterating forward and back through the set of objects.
   */
  private void displayObjectProperties() {
    currentObject = destinationObjects[currentObjectIndex];

    // Manage previous/next buttons.
    if (destinationObjects.length > 1) {
      currentObjectLabel.setText((currentObjectIndex + 1) + " of " + destinationObjects.length);
      previousObjectButton.setEnabled(currentObjectIndex > 0);
      nextObjectButton.setEnabled(currentObjectIndex < (destinationObjects.length - 1));
    }

    // Unmodifiable fields.
    objectKeyTextField.setText(currentObject.getKey());
    objectContentLengthTextField.setText(String.valueOf(currentObject.getContentLength()));
    objectLastModifiedTextField.setText(String.valueOf(currentObject.getLastModifiedDate()));
    objectETagTextField.setText(currentObject.getETag());
    bucketLocationTextField.setText(currentObject.getBucketName());

    if (currentObject.getOwner() != null) {
      ownerNameLabel.setVisible(true);
      ownerNameTextField.setVisible(true);
      ownerIdLabel.setVisible(true);
      ownerIdTextField.setVisible(true);
      ownerNameTextField.setText(currentObject.getOwner().getDisplayName());
      ownerIdTextField.setText(currentObject.getOwner().getId());
    } else {
      ownerNameLabel.setVisible(false);
      ownerNameTextField.setVisible(false);
      ownerIdLabel.setVisible(false);
      ownerIdTextField.setVisible(false);
    }

    // Clear old table contents
    while (objectMetadataTableModel.getRowCount() > 0) {
      objectMetadataTableModel.removeRow(0);
    }

    // Display remaining metadata items in the table.
    Iterator mdIter = currentObject.getModifiableMetadata().entrySet().iterator();
    while (mdIter.hasNext()) {
      Map.Entry entry = (Map.Entry) mdIter.next();
      Object name = entry.getKey();
      Object value = entry.getValue();
      objectMetadataTableModel.addRow(new Object[] {name, value});
    }
  }