private void doSave() {
    ObjectOutputStream objectStream = getObjectOutputStream();

    if (objectStream != null) {
      try {
        System.out.println("Saving " + selectedChildrenPaths.size() + " Selected Generations...");

        for (int i = 0; i < selectedChildrenPaths.size(); i++) {
          // Get the userObject at the supplied path
          Object selectedPath =
              ((TreePath) selectedChildrenPaths.elementAt(i)).getLastPathComponent();
          DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) selectedPath;

          objectStream.writeObject(selectedNode.getUserObject());
        }

        objectStream.close();
        System.out.println("Save completed successfully.");
      } catch (IOException e) {
        System.err.println(e);
      }
    } else {
      System.out.println("Save Selected Files has been aborted!");
    }
  }
  // Public Methods
  public void appendNextTreeGeneration(Vector generation) {
    DefaultMutableTreeNode nextGeneration = generationNodeBuilder(generation);

    generations.add(nextGeneration);

    // If Generations contains leaf nodes (generated objects)
    // Enabled Save All Menu Item
    if (generations.getLeafCount() > 0) miSaveAll.setEnabled(true);
    else miSaveAll.setEnabled(false);

    // Update JTree View

    // affected nodes needing updating
    int[] nodeRangeToUpdate = {generations.getIndex(nextGeneration)};
    ((DefaultTreeModel) tree.getModel()).nodesWereInserted(generations, nodeRangeToUpdate);

    // Expand Parent after first child node is displayed
    if (generationNumber == 1) tree.expandRow(0);

    ++generationNumber;
  }
  private void doSaveAll() {
    ObjectOutputStream objectStream = getObjectOutputStream();

    if (objectStream != null) {
      try {
        System.out.println("Saving All " + generations.getLeafCount() + " Generations...");

        for (Enumeration e = generations.depthFirstEnumeration(); e.hasMoreElements(); ) {
          DefaultMutableTreeNode tmpNode = (DefaultMutableTreeNode) e.nextElement();

          if (tmpNode.isLeaf()) objectStream.writeObject(tmpNode.getUserObject());
        }

        objectStream.close();
        System.out.println("Save completed successfully.");
      } catch (IOException e) {
        System.err.println(e);
      }
    } else {
      System.out.println("Save All Files has been aborted!");
    }
  }
    public void valueChanged(TreeSelectionEvent event) {
      // DefaultMutableTreeNode node = new DefaultMutableTreeNode();
      DefaultMutableTreeNode node;
      TreePath paths[] = event.getPaths();

      // Statistical variables
      Object bestNode;
      Object worstNode;
      double avgFitness = 0;
      double bestFitness = -1;
      double worstFitness = -1;

      // Update Selection Panel to reflect current selections
      for (int i = 0; i < paths.length; i++) {
        // If a parent node is selected, select all children nodes
        DefaultMutableTreeNode tmpNode = (DefaultMutableTreeNode) paths[i].getLastPathComponent();

        // If Root is selected, clear all selections
        if (tmpNode.isRoot()) {
          tree.clearSelection();
          selectedChildrenPaths.removeAllElements();
          break;
        }

        if (tmpNode.getAllowsChildren()) {
          ArrayList tmpNodeChildren = new ArrayList();

          for (Enumeration e = tmpNode.children(); e.hasMoreElements(); ) {
            DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) e.nextElement();
            TreePath treePath = new TreePath(childNode.getPath());

            if (event.isAddedPath(paths[i])) {
              if (!selectedChildrenPaths.contains(treePath))
                selectedChildrenPaths.addElement(treePath);
            } else selectedChildrenPaths.removeElement(treePath);
          }

          // TreePath [] treePaths = new TreePath[tmpNodeChildren.size()];

          // if ( event.isAddedPath(paths[i]) )
          //    tree.addSelectionPaths( (TreePath []) tmpNodeChildren.toArray(treePaths) );
          // else
          //    tree.removeSelectionPaths( (TreePath[]) tmpNodeChildren.toArray(treePaths) );

          // Collapse parent view -- commented for future use, DO NOT IMPLEMENT AS SHOWN
          // tree.collapsePath( paths[i] );
        } else // only a single node is being examined
        {
          if (event.isAddedPath(paths[i])) {
            if (!selectedChildrenPaths.contains(paths[i]))
              selectedChildrenPaths.addElement(paths[i]);
          } else selectedChildrenPaths.removeElement(paths[i]);
        }
      }

      // If selections exist, enabled "Save Selected" menu item
      if (selectedChildrenPaths.size() > 0) miSave.setEnabled(true);
      else miSave.setEnabled(false);

      // Calculate selection information statistics
      for (int j = 0; j < selectedChildrenPaths.size(); j++) {
        double fitness = 0;

        node =
            (DefaultMutableTreeNode)
                ((TreePath) selectedChildrenPaths.elementAt(j)).getLastPathComponent();

        fitness = gaMonitor.getFitness(node.getUserObject());

        avgFitness += fitness;

        if (fitness > bestFitness || bestFitness == -1) {
          bestFitness = fitness;
          bestNode = node;
        }

        if (fitness < worstFitness || worstFitness == -1) {
          worstFitness = fitness;
          worstNode = node;
        }
      }

      // Finialize Statistics
      if (bestFitness != -1) avgFitness = avgFitness / (double) selectedChildrenPaths.size();

      // Panel may not exist!  If null, ignore
      if (selectionStatsPanel != null) {
        if (bestFitness != -1)
          selectionStatsPanel.setSelectionStats(
              selectedChildrenPaths.size(), avgFitness, bestFitness, worstFitness);
        else selectionStatsPanel.setEmptySelection();
      }
    }