private void handleMergeResult(
     GKInstance localCopy, GKInstance dbCopy, InstanceComparisonPane comparisonPane) {
   if (comparisonPane.getSaveMergeOption() == InstanceComparisonPane.OVERWRITE_FIRST) {
     // Need to refresh the selected instance
     InstanceComparer comparer = new InstanceComparer();
     try {
       int result = comparer.compare(localCopy, dbCopy);
       if (result != InstanceComparer.IS_IDENTICAL) {
         typeMap.put(localCopy, mapCompareResultToString(result));
       } else {
         typeMap.remove(localCopy);
         changedList.deleteInstance(localCopy);
       }
       changedList.repaint();
     } catch (Exception e1) {
       System.err.println("SynchronizationDialog.handleMergeResult(): " + e1);
       e1.printStackTrace();
     }
   } else if (comparisonPane.getSaveMergeOption() == InstanceComparisonPane.SAVE_AS_NEW) {
     // Need to add a new instance to the local new instance
     GKInstance newInstance = comparisonPane.getMerged();
     List newInstances = (List) syncMap.get(NEW_KEY);
     if (newInstances == null) {
       newInstances = new ArrayList();
       syncMap.put(NEW_KEY, newInstances);
     }
     newInstances.add(newInstance);
     typeMap.put(newInstance, NEW_KEY);
     if (newList == null) {
       // Get some information from changed
       newList =
           initInstanceListPane(newInstances, "Instances created locally: " + newInstances.size());
       centerPane.validate();
     } else {
       // Cannot call this method because it is used for one schema class only
       // newList.addInstance(newInstance);
       newList.setTitle("Instances created locally: " + newInstances.size());
       newList.setDisplayedInstances(newInstances);
       newList.repaint();
     }
   }
 }
  private void showComparison() {
    // Find the instance that can be used for comparision. This instance
    // should be chosen from changedList or localHasUnexpInstance
    GKInstance instance = null;
    if (changedList != null) { // Check changedList first
      List selection = changedList.getSelection();
      if (selection.size() > 0) instance = (GKInstance) selection.get(0);
    }
    if (instance == null && localHasMoreIEList != null) {
      List selection = localHasMoreIEList.getSelection();
      if (selection.size() > 0) instance = (GKInstance) selection.get(0);
    }
    if (instance == null) return;
    final InstanceComparisonPane comparisonPane = new InstanceComparisonPane();
    // Fine tune comparison pane for making comparisons with
    // database
    comparisonPane.setSaveDialogHideUnusedButtons(true);
    comparisonPane.setSaveDialogSaveAsNewBtnFirst(false);
    comparisonPane.setSaveDialogSaveAsNewBtnTitle(
        "Create new local instance and put merge into that");
    comparisonPane.setSaveDialogReplaceFirstBtnTitle(
        "Overwrite existing instance with merge (recommended)");
    comparisonPane.setCloseAfterSaving(true);
    try {
      String clsName = instance.getSchemClass().getName();
      Long instanceId = instance.getDBID();
      final GKInstance localCopy = fileAdaptor.fetchInstance(clsName, instanceId);
      dbAdaptor.setUseCache(false);
      // final GKInstance dbCopy = dbAdaptor.fetchInstance(clsName, instanceId);
      // The class type might be changed locally or remotely. So not clsName should be used
      // to fetch database instance. Otherwise, null exception will be thrown. The same thing
      // is done also in creating synchronization result.
      final GKInstance dbCopy = dbAdaptor.fetchInstance(instanceId);
      dbAdaptor.setUseCache(true);
      comparisonPane.setInstances(localCopy, dbCopy);
      String title =
          "Comparing Instances \""
              + instance.getDisplayName()
              + "\" in the local and DB repositories";
      JDialog parentDialog = (JDialog) SwingUtilities.getAncestorOfClass(JDialog.class, centerPane);
      final JDialog dialog = new JDialog(parentDialog, title);
      // Try to update the list automatically
      dialog.addWindowListener(
          new WindowAdapter() {
            public void windowClosed(WindowEvent e) {
              handleMergeResult(localCopy, dbCopy, comparisonPane);
              // To prevent double calling. It is called again when parentDialog is closed.
              dialog.removeWindowListener(this);
            }
          });
      dialog.getContentPane().add(comparisonPane, BorderLayout.CENTER);
      dialog.setModal(true);
      dialog.setSize(800, 600);
      GKApplicationUtilities.center(dialog);
      dialog.setVisible(true);

      // Update synchronization dialog panels depending on user
      // choice.
      if (comparisonPane.getSaveMergeOption() == InstanceComparisonPane.SAVE_AS_NEW) {
        GKInstance merged = comparisonPane.getMerged();

        if (newList == null) {
          List list = new ArrayList();
          list.add(merged);
          newList = initInstanceListPane(list, "Instances created locally: " + list.size());
        } else newList.addInstance(merged);
      } else if (comparisonPane.getSaveMergeOption() == InstanceComparisonPane.OVERWRITE_FIRST) {
        dbAdaptor.setUseCache(false);
        GKInstance remoteCopy = dbAdaptor.fetchInstance(instance.getDBID());
        dbAdaptor.setUseCache(true);
        if (remoteCopy != null) {
          InstanceComparer comparer = new InstanceComparer();
          int reply = comparer.compare(instance, remoteCopy);
          if (reply == InstanceComparer.LOCAL_HAS_MORE_IE) {
            if (localHasMoreIEList == null) {
              List list = new ArrayList();
              list.add(instance);
              localHasMoreIEList =
                  initInstanceListPane(
                      list, "Local instances having unexpected InstanceEdits: " + list.size());
            } else localHasMoreIEList.addInstance(instance);
          } else if (reply == InstanceComparer.IS_IDENTICAL) {
            // Merge has made local and database copies
            // identical - don't need to check in anymore
            changedList.deleteInstance(instance);
          } else if (reply != InstanceComparer.NEW_CHANGE_IN_LOCAL) {
            // Merge has produced a conflict
            typeMap.put(mapCompareResultToString(reply), instance);
          } else
            // The user should now be allowed to commit this
            // instance, because it will now have changed.
            commitToDBAction.setEnabled(true);

          JOptionPane.showMessageDialog(
              parentDialog,
              "Merge successful, you will need to check the merged instance into the database.\n\n",
              "Merge OK",
              JOptionPane.INFORMATION_MESSAGE);
        }
      }

    } catch (Exception e1) {
      System.err.println("Synchronization.createDisplayMapPane(): " + e1);
      e1.printStackTrace();
      JOptionPane.showMessageDialog(
          this,
          "Error in comparing: " + instance.toString(),
          "Error in Comparing",
          JOptionPane.ERROR_MESSAGE);
    }
  }