@Override
  public void run() throws TaxomaticException {
    List<Taxon> taxaToSave = new ArrayList<Taxon>();
    for (Taxon mergedTaxon : taxaToMerge) {
      mergedTaxon.setStatus(TaxonStatus.STATUS_SYNONYM);
      {
        Synonym synonym = Taxon.synonymizeTaxon(mergedTaxon);
        synonym.setStatus(Synonym.MERGE);
        synonym.setTaxon(mergeTarget);

        mergeTarget.getSynonyms().add(synonym);
      }
      {
        Synonym synonym = Taxon.synonymizeTaxon(mergeTarget);
        synonym.setStatus(Synonym.MERGE);
        synonym.setTaxon(mergedTaxon);

        mergedTaxon.getSynonyms().add(synonym);
      }
      for (Taxon child : mergedTaxon.getChildren()) {
        child.setParent(mergeTarget);
        mergeTarget.getChildren().add(child);
        taxaToSave.add(child);
      }
      taxaToSave.add(mergedTaxon);
    }
    taxaToSave.add(mergeTarget);

    taxomaticIO.updateAndSave(taxaToSave, operation.getUser(), true);

    recordOperationHistory(taxaToSave, operation);
  }
  public void onClose() {
    String errorMessage = null;

    if (currentNode.getLevel() < TaxonLevel.SPECIES) {
      if (parentToChildList.size() < 1) {
        errorMessage =
            "You must create at least one new taxon to split "
                + currentNode.getFullName()
                + " into.";
      }
    } else {
      if (parentToChildList.size() < 2) {
        errorMessage =
            "You must create at least two new taxon to split "
                + currentNode.getFullName()
                + " into.";
      } else if (children.getItems().size() != 0) {
        errorMessage = "You must remove all children from " + currentNode.getFullName() + ".";
      }
    }

    if (errorMessage == null) {
      TaxomaticUtils.impl.performSplit(
          currentNode,
          parentToChildList,
          new GenericCallback<String>() {
            public void onFailure(Throwable arg0) {
              // Error message already displayed by default callback.
            }

            public void onSuccess(String arg0) {
              hide();
              if (currentNode.getLevel() < TaxonLevel.SPECIES) {
                WindowUtils.confirmAlert(
                    "Saved",
                    "The split was successful.  However, the status of "
                        + currentNode.getFullName()
                        + " was not modified.  Would you like to edit the status of "
                        + currentNode.getFullName()
                        + "?",
                    new WindowUtils.SimpleMessageBoxListener() {
                      @Override
                      public void onYes() {
                        TaxonBasicEditor editor = new TaxonBasicEditor();
                        editor.show();
                        editor.center();
                      }
                    },
                    "Yes, edit",
                    "No, all finished");
              } else {
                WindowUtils.infoAlert("Saved", "Changes saved.");
              }
            }
          });
    } else {
      WindowUtils.errorAlert("Error", errorMessage);
    }
  }
 /*
  * mergeTarget,toMerge,toMerge,toMerge
  */
 private String generateInstructions(Taxon mergeTarget, List<Taxon> taxaToMerge) {
   StringBuilder builder = new StringBuilder();
   builder.append(mergeTarget.getId());
   for (Taxon taxon : taxaToMerge) {
     builder.append(',');
     builder.append(taxon.getId());
   }
   return builder.toString();
 }
 private HTML getInstructions() {
   return new HTML(
       "<b>Instructions:</b> Click \"Create New Taxa\" to create one or more new taxa, "
           + "then move the children below, if any exist, to those new taxa."
           + "Use CTRL+Click to select multiple children at the same time. "
           + "You should move all the children to one of the new taxa as "
           + currentNode.getFullName()
           + " will become deprecated.");
 }
 private String generateDetails(Taxon mergeTarget, List<Taxon> taxaToMerge) {
   StringBuilder builder = new StringBuilder();
   builder.append("Merged the following taxa into " + mergeTarget.getFullName() + ": ");
   for (Iterator<Taxon> iter = taxaToMerge.iterator(); iter.hasNext(); ) {
     builder.append(iter.next().getFullName());
     if (iter.hasNext()) builder.append(", ");
   }
   return builder.toString();
 }
  private LayoutContainer getLeftSide() {
    // BorderLayout layout = new BorderLayout();
    RowLayout layout = new RowLayout(Orientation.VERTICAL);
    // layout.setMargin(0);
    // layout.setSpacing(0);

    LayoutContainer container = new LayoutContainer();
    container.setLayout(layout);
    container.setLayoutOnChange(true);
    container.setSize(PANEL_WIDTH / 2, PANEL_HEIGHT);

    children = new DataList();
    children.setSelectionMode(SelectionMode.MULTI);

    TaxonomyCache.impl.getTaxonChildren(
        currentNode.getId() + "",
        new GenericCallback<List<Taxon>>() {
          public void onFailure(Throwable caught) {
            WindowUtils.errorAlert("Error", "Could not fetch children, please try again later.");
          }

          public void onSuccess(List<Taxon> result) {
            for (Taxon taxon : result) {
              DataListItem li = new DataListItem(taxon.getFullName());
              li.setData("nodeID", "" + taxon.getId());
              li.setData("node", taxon);
              children.add(li);
            }
          }
        });

    container.add(
        new HTML("Children currently in " + currentNode.getFullName() + ":"), new RowData(1d, 25));
    container.add(children, new RowData(1d, 1d));

    return container;
  }