public void unloadPlates() throws ChippingManagerException {
   seedChipperGUIController.getSeedChipperController().validateChangePriorToSave();
   //        List<Plate> platesToUnload = getFailedChiplates();
   DefaultListModel destinationsListModel = (DefaultListModel) destinationsList.getModel();
   int[] destinationsLoadCount = new int[destinationsListModel.getSize()];
   // Assign destinations to the seed plates
   int destinationsListIndex = 0;
   updateSeedPlateStatus();
   updateChipPlateStatus();
   // Set the respective locations in the seed plates
   for (int i = 0; i < seedPlates.length; i++) {
     // todo: unload criteria to be refactored to plate object....
     if (SCANNED.equals(seedPlates[i].getStatus()) && seedPlates[i].getPrescanStatus() != null) {
       destinationsListIndex =
           findDestinationListIndex(
               destinationsListModel, destinationsLoadCount, destinationsListIndex, i);
       // Decide the destination
       String seedPlateDestination =
           destinationsListModel.getElementAt(destinationsListIndex).toString();
       logger.info(
           "assigning seed  plates to plate "
               + seedPlates[i].getDeckNest()
               + " ->> "
               + seedPlateDestination);
       seedPlates[i].setStorageLocation(seedPlateDestination);
       destinationsLoadCount[destinationsListIndex]++;
       destinationsListIndex++;
       seedPlates[i].setPrescanStatus(CHIPPED);
     }
   }
   seedChipperGUIController
       .getSeedChipperController()
       .unloadChipperRun(userIDComboBox.getSelectedItem().toString());
   //
   // seedChipperGUIController.getSeedChipperController().syncPrescannedPlatesList(platesToUnload,
   // seedPlates, chipPlates);
   seedChipperGUIController.drawDeck();
   seedChipperGUIController.drawRunsOnDeck();
   logger.info("Plates unloaded to seed store");
   this.dispose();
 }
/**
 * Filename: $RCSfile: MultipleDestinationsUnloadPlatesDialog.java,v $ Label: $Name: $ Last Change:
 * $Author: rkkall $ On: $Date: 2009/03/16 21:47:54 $
 *
 * @author ynadkar
 * @version $Revision: 1.32 $
 */
public class MultipleDestinationsUnloadPlatesDialog extends BaseUnloadDialog {
  static Logger logger = Logger.getLogger(MultipleDestinationsUnloadPlatesDialog.class);

  private JScrollPane jScrollPane1;
  private JScrollPane jScrollPane2;
  private JPanel locationPanel;
  private JButton removeSelectedButton;
  private JLabel scanLabel;
  private JList destinationsList;
  private JButton locationRemoveAllButton;
  private JButton locationRemoveSelectedButton;
  private JButton removeAllButton;

  public MultipleDestinationsUnloadPlatesDialog(
      SeedChippingGUIController seedChipperGUIController,
      JFrame parent,
      boolean modal,
      Plate[] seedPlates,
      Plate[] chipPlates) {
    super(parent, modal, seedPlates, chipPlates, seedChipperGUIController);
    initComponents();
  }

  private void initComponents() {
    chipPlatesPanel = new javax.swing.JPanel();
    scannerInput = new javax.swing.JTextField();
    jScrollPane1 = new javax.swing.JScrollPane();
    failedPlatesList = new javax.swing.JList(new DefaultListModel());
    removeSelectedButton = new javax.swing.JButton();
    locationPanel = new javax.swing.JPanel();
    userIdLabel = new javax.swing.JLabel();
    userIDComboBox = new javax.swing.JComboBox();
    userIDComboBox.setName("userIDComboBox");
    scanLabel = new javax.swing.JLabel();
    scanDestination = new javax.swing.JTextField();
    jScrollPane2 = new javax.swing.JScrollPane();
    destinationsList = new javax.swing.JList(new DefaultListModel());
    completeUnloadingButton = new javax.swing.JButton();
    locationRemoveAllButton = new javax.swing.JButton();
    locationRemoveSelectedButton = new javax.swing.JButton();
    removeAllButton = new javax.swing.JButton();

    jScrollPane2 = new javax.swing.JScrollPane(destinationsList);

    setTitle(UNLOAD_DECK);
    setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

    chipPlatesPanel.setBorder(
        javax.swing.BorderFactory.createTitledBorder(SCAN_UNFILLED_CHIP_PLATES));
    scannerInput.setName("inputScanner");
    scannerInput.setText(BLANK);
    scannerInput.addActionListener(new DialogScannerAction());
    jScrollPane1.setViewportView(failedPlatesList);

    removeSelectedButton.setText(REMOVE_SELECTED);
    removeSelectedButton.setName(REMOVE_SELECTED);
    removeSelectedButton.addActionListener(new RemoveSelectedItemAction());
    removeAllButton.setText(REMOVE_ALL);
    removeAllButton.setName(REMOVE_ALL);
    removeAllButton.addActionListener(new RemoveAllAction());
    populateUserList(userIDComboBox);

    org.jdesktop.layout.GroupLayout scanUnfilledSeedPlatesPanelLayout =
        new org.jdesktop.layout.GroupLayout(chipPlatesPanel);
    chipPlatesPanel.setLayout(scanUnfilledSeedPlatesPanelLayout);
    scanUnfilledSeedPlatesPanelLayout.setHorizontalGroup(
        scanUnfilledSeedPlatesPanelLayout
            .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(
                scanUnfilledSeedPlatesPanelLayout
                    .createSequentialGroup()
                    .addContainerGap()
                    .add(
                        scanUnfilledSeedPlatesPanelLayout
                            .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(
                                jScrollPane1,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                246,
                                Short.MAX_VALUE)
                            .add(
                                scannerInput,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                246,
                                Short.MAX_VALUE)
                            .add(
                                org.jdesktop.layout.GroupLayout.TRAILING,
                                scanUnfilledSeedPlatesPanelLayout
                                    .createSequentialGroup()
                                    .add(
                                        removeAllButton,
                                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                        123,
                                        Short.MAX_VALUE)
                                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                    .add(
                                        removeSelectedButton,
                                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                                        117,
                                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                    .addContainerGap()));
    scanUnfilledSeedPlatesPanelLayout.setVerticalGroup(
        scanUnfilledSeedPlatesPanelLayout
            .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(
                scanUnfilledSeedPlatesPanelLayout
                    .createSequentialGroup()
                    .add(
                        scannerInput,
                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                    .add(
                        jScrollPane1,
                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                    .add(
                        scanUnfilledSeedPlatesPanelLayout
                            .createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(removeSelectedButton)
                            .add(removeAllButton))
                    .addContainerGap(
                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));

    locationPanel.setBorder(
        javax.swing.BorderFactory.createTitledBorder(SET_LOCATION_FOR_SEED_PLATES));
    userIdLabel.setText(USER_ID);
    scanLabel.setText(SCAN_DESTINATION);
    scanDestination.setText(BLANK);
    scanDestination.setName("scanDestination");
    scanDestination.addActionListener(new DestinationScanAction());
    locationRemoveAllButton.setText(REMOVE_ALL);
    locationRemoveAllButton.setName("Location_" + REMOVE_ALL);
    locationRemoveAllButton.addActionListener(new RemoveAllAction());
    locationRemoveSelectedButton.setText(REMOVE_SELECTED);
    locationRemoveSelectedButton.setName("Location_" + REMOVE_SELECTED);
    locationRemoveSelectedButton.addActionListener(new RemoveSelectedItemAction());

    org.jdesktop.layout.GroupLayout locationPanelLayout =
        new org.jdesktop.layout.GroupLayout(locationPanel);
    locationPanel.setLayout(locationPanelLayout);
    locationPanelLayout.setHorizontalGroup(
        locationPanelLayout
            .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(
                locationPanelLayout
                    .createSequentialGroup()
                    .addContainerGap()
                    .add(
                        locationPanelLayout
                            .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(
                                jScrollPane2,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                246,
                                Short.MAX_VALUE)
                            .add(
                                locationPanelLayout
                                    .createSequentialGroup()
                                    .add(
                                        locationPanelLayout
                                            .createParallelGroup(
                                                org.jdesktop.layout.GroupLayout.LEADING)
                                            .add(scanLabel)
                                            .add(userIdLabel))
                                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                    .add(
                                        locationPanelLayout
                                            .createParallelGroup(
                                                org.jdesktop.layout.GroupLayout.LEADING)
                                            .add(userIDComboBox, 0, 157, Short.MAX_VALUE)
                                            .add(
                                                scanDestination,
                                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                                157,
                                                Short.MAX_VALUE)))
                            .add(
                                org.jdesktop.layout.GroupLayout.TRAILING,
                                locationPanelLayout
                                    .createSequentialGroup()
                                    .add(
                                        locationRemoveAllButton,
                                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                        123,
                                        Short.MAX_VALUE)
                                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                    .add(locationRemoveSelectedButton)))
                    .addContainerGap()));
    locationPanelLayout.setVerticalGroup(
        locationPanelLayout
            .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(
                locationPanelLayout
                    .createSequentialGroup()
                    .add(
                        locationPanelLayout
                            .createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(userIdLabel)
                            .add(
                                userIDComboBox,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                    .add(
                        locationPanelLayout
                            .createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(scanLabel)
                            .add(
                                scanDestination,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                    .add(
                        jScrollPane2,
                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                        111,
                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                    .add(
                        locationPanelLayout
                            .createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(locationRemoveSelectedButton)
                            .add(locationRemoveAllButton))
                    .addContainerGap(
                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));

    completeUnloadingButton.setText(COMPLETE_UNLOADING);
    completeUnloadingButton.setName("completeUnloadingButton");
    completeUnloadingButton.addActionListener(new CompleteUnloadAction());

    org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout
            .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(
                layout
                    .createSequentialGroup()
                    .addContainerGap()
                    .add(
                        layout
                            .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(
                                locationPanel,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.TRAILING, completeUnloadingButton)
                            .add(
                                chipPlatesPanel,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                                Short.MAX_VALUE))
                    .addContainerGap()));
    layout.setVerticalGroup(
        layout
            .createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(
                layout
                    .createSequentialGroup()
                    .addContainerGap()
                    .add(
                        chipPlatesPanel,
                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
                        217,
                        org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                    .add(
                        locationPanel,
                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                        org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
                        Short.MAX_VALUE)
                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                    .add(completeUnloadingButton)
                    .addContainerGap()));
    pack();
  }

  public void updateSeedPlateDestination() {}

  public void addToUnloadPlatesList(String scannerInput) {
    DefaultListModel listModel = (DefaultListModel) failedPlatesList.getModel();
    int lastPosition = listModel.getSize();
    listModel.add(lastPosition, scannerInput);
  }

  class DestinationScanAction extends AbstractAction {
    public void actionPerformed(ActionEvent e) {
      try {
        String scannedDestination = ((JTextField) e.getSource()).getText().toUpperCase();
        validateDestinationScan(scannedDestination);
        DefaultListModel listModel = (DefaultListModel) destinationsList.getModel();
        int lastPosition = listModel.getSize();
        int seedsCount = 0;
        // todo: do we have to worry about more trays than required..?
        for (int i = 0; i < seedPlates.length; i++) {
          if (seedPlates[i].getSeedPlateBarcode() != null
              && SCANNED.equals(seedPlates[i].getStatus())
              && !isContainedInList(seedPlates[i].getSeedPlateBarcode(), failedPlatesList)) {
            seedsCount++;
          }
        }
        if (lastPosition >= seedsCount) {
          throw new ChippingManagerException(DESTINATIONS_LIMIT_EXCEEDED);
        }
        addDestination(scannedDestination);
      } catch (Throwable cmException) {
        logger.error("Unable to scan destination ", cmException);
        JOptionPane.showMessageDialog(
            new JFrame(),
            cmException.getMessage(),
            TITLE_CHIPPING_MANAGER,
            JOptionPane.WARNING_MESSAGE);
      }
      scanDestination.setText(BLANK);
    }
  }

  public void addDestination(String scannedDestination) {
    DefaultListModel listModel = (DefaultListModel) destinationsList.getModel();
    int lastPosition = listModel.getSize();
    listModel.add(lastPosition, scannedDestination);
  }

  public void validateDestinationScan(String scannedDestination) {
    if (StringUtils.isNullOrEmpty(scannedDestination)) {
      throw new ChippingManagerException(SEED_PLATE_DESTINATION);
    }
    // IS THIS A TRAY ?
    if (scannedDestination.length() != 4 || !StringUtils.isNumeric(scannedDestination)) {
      throw new ChippingManagerException(scannedDestination + " is not a valid Tray barcode");
    }
    if (isContainedInList(scannedDestination, destinationsList)) {
      throw new ChippingManagerException(DUPLICATE_DESTINATION_SCANNED);
    }
    // CHECK WITH DB THAT TRAY DOES NOT HAVE OTHER NON SORTED PROJECT ASSOCIATIONS
    if (seedChipperGUIController
        .getSeedChipperController()
        .isTrayUsedInOtherProjects(scannedDestination)) {
      throw new ChippingManagerException(TRAY_IN_MULTIPLE_PROJECTS);
    }
  }

  class CompleteUnloadAction extends AbstractAction {
    public void actionPerformed(ActionEvent e) {
      try {
        validateUnloadPlatesDialog();
        unloadPlates();
      } catch (Throwable cmException) {
        logger.error("error to unload to multiple destinations", cmException);
        JOptionPane.showMessageDialog(
            new JFrame(),
            cmException.getMessage(),
            TITLE_CHIPPING_MANAGER,
            JOptionPane.WARNING_MESSAGE);
      }
    }
  }

  public void unloadPlates() throws ChippingManagerException {
    seedChipperGUIController.getSeedChipperController().validateChangePriorToSave();
    //        List<Plate> platesToUnload = getFailedChiplates();
    DefaultListModel destinationsListModel = (DefaultListModel) destinationsList.getModel();
    int[] destinationsLoadCount = new int[destinationsListModel.getSize()];
    // Assign destinations to the seed plates
    int destinationsListIndex = 0;
    updateSeedPlateStatus();
    updateChipPlateStatus();
    // Set the respective locations in the seed plates
    for (int i = 0; i < seedPlates.length; i++) {
      // todo: unload criteria to be refactored to plate object....
      if (SCANNED.equals(seedPlates[i].getStatus()) && seedPlates[i].getPrescanStatus() != null) {
        destinationsListIndex =
            findDestinationListIndex(
                destinationsListModel, destinationsLoadCount, destinationsListIndex, i);
        // Decide the destination
        String seedPlateDestination =
            destinationsListModel.getElementAt(destinationsListIndex).toString();
        logger.info(
            "assigning seed  plates to plate "
                + seedPlates[i].getDeckNest()
                + " ->> "
                + seedPlateDestination);
        seedPlates[i].setStorageLocation(seedPlateDestination);
        destinationsLoadCount[destinationsListIndex]++;
        destinationsListIndex++;
        seedPlates[i].setPrescanStatus(CHIPPED);
      }
    }
    seedChipperGUIController
        .getSeedChipperController()
        .unloadChipperRun(userIDComboBox.getSelectedItem().toString());
    //
    // seedChipperGUIController.getSeedChipperController().syncPrescannedPlatesList(platesToUnload,
    // seedPlates, chipPlates);
    seedChipperGUIController.drawDeck();
    seedChipperGUIController.drawRunsOnDeck();
    logger.info("Plates unloaded to seed store");
    this.dispose();
  }

  private int findDestinationListIndex(
      DefaultListModel destinationsListModel,
      int[] destinationsLoadCount,
      int destinationsListIndex,
      int i) {
    if (seedPlates[i].getSeedPlateBarcode() != null) {
      if (destinationsListIndex == destinationsListModel.getSize()) {
        for (int k = 0; k < destinationsListModel.getSize(); k++) {
          if (destinationsLoadCount[k] < MAX_NUMBER_IN_SEED_DESTINATION) {
            destinationsListIndex = k;
            break;
          }
        }
      }
    }
    return destinationsListIndex;
  }

  public Plate getSeedPlateByNumber(String number, Plate[] plates) {
    Plate temp = null;
    if (plates != null) {
      for (int i = 0; i < plates.length; i++) {
        if (plates[i].getSeedPlateBarcode() != null
            && plates[i].getSeedPlateBarcode().toUpperCase().equals(number.toUpperCase())) {
          temp = plates[i];
        }
      }
    }
    return temp;
  }

  public void validateUnloadPlatesDialog() throws ChippingManagerException {
    StringBuffer stBuff = new StringBuffer(CORRECT_ERRORS_TO_CONTINUE);
    DefaultListModel destinationListModel = (DefaultListModel) destinationsList.getModel();
    int numberOfDestinations = destinationListModel.getSize();
    // Get the number of seed plates
    int seedPlatesCount = numberOfValidSeedPlates();
    String destinationsMessage =
        seedChipperGUIController
            .getSeedChipperController()
            .validateDestinations(numberOfDestinations, seedPlatesCount);
    if (destinationsMessage != null) {
      stBuff.append("\n- " + destinationsMessage);
    }
    if (userIDComboBox.getSelectedIndex() == 0) {
      stBuff.append("\n- " + USER_NAME_NOT_SELECTED + "\n");
    }
    if (!stBuff.toString().equals(CORRECT_ERRORS_TO_CONTINUE)) {
      throw new ChippingManagerException(stBuff.toString());
    }
  }

  private int numberOfValidSeedPlates() {
    int seedPlatesCount = 0;
    for (int i = 0; i < seedPlates.length; i++) {
      if (seedPlates[i].getSeedPlateBarcode() != null
          && seedPlates[i].getStatus() != null
          && seedPlates[i].getStatus().equals(SCANNED)
          && !isContainedInList(seedPlates[i].getSeedPlateBarcode(), failedPlatesList)) {
        seedPlatesCount++;
      }
    }
    return seedPlatesCount;
  }

  class RemoveSelectedItemAction extends AbstractAction {
    public void actionPerformed(ActionEvent e) {
      DefaultListModel listModel = null;
      JList list = null;
      if (((JButton) e.getSource()).getName().equals(REMOVE_SELECTED)) {
        list = failedPlatesList;
        listModel = (DefaultListModel) failedPlatesList.getModel();
      } else {
        list = destinationsList;
        listModel = (DefaultListModel) destinationsList.getModel();
      }
      if (list.getSelectedIndices().length > 0) {
        int[] temp = list.getSelectedIndices();
        int[] selectedIndices = list.getSelectedIndices();
        for (int i = temp.length - 1; i >= 0; i--) {
          selectedIndices = list.getSelectedIndices();
          listModel.removeElementAt(selectedIndices[i]);
        }
      }
    }
  }

  class RemoveAllAction extends AbstractAction {
    public void actionPerformed(ActionEvent e) {
      DefaultListModel listModel = null;
      if (((JButton) e.getSource()).getName().equals(REMOVE_ALL)) {
        listModel = (DefaultListModel) failedPlatesList.getModel();
      } else {
        listModel = (DefaultListModel) destinationsList.getModel();
      }
      listModel.removeAllElements();
    }
  }

  /**
   * Determines if a given String is present in the list
   *
   * @param scan the String to look for in the list
   * @param list the list of values to examine
   * @return true if the list contains the String, false otherwise
   */
  public boolean isContainedInList(String scan, JList list) {
    DefaultListModel listModel = (DefaultListModel) list.getModel();
    return listModel.contains(scan);
  }
}