/**
  * A helper method to save changes
  *
  * @param fileAdaptor
  * @param curatorFrame
  * @return true for saving the changes, while false for an unsuccessful saving. An unsuccessful
  *     saving might result from cancelling or throwing an exception.
  */
 private boolean saveChanges(XMLFileAdaptor fileAdaptor) {
   // Make sure everything is changed
   if (fileAdaptor.isDirty()) {
     int reply =
         JOptionPane.showConfirmDialog(
             this,
             "You have to save changes first before doing synchronization.\n"
                 + "Do you want to save changes and then do synchronization?",
             "Save Changes?",
             JOptionPane.OK_CANCEL_OPTION);
     if (reply == JOptionPane.CANCEL_OPTION) return false;
     try {
       fileAdaptor.save();
       return true;
     } catch (Exception e) {
       JOptionPane.showMessageDialog(
           this,
           "Cannot save changes:" + e.getMessage(),
           "Error in Saving",
           JOptionPane.ERROR_MESSAGE);
       System.err.println("SynchronizationDialog.saveChanges(): " + e);
       e.printStackTrace();
       return false;
     }
   }
   return true;
 }
 private void clearDeleteRecord() {
   if (deleteList != null) {
     java.util.List list = deleteList.getSelection();
     if (list.size() > 0) {
       try {
         java.util.List dbIDs = new ArrayList(list.size());
         for (Iterator it = list.iterator(); it.hasNext(); ) {
           GKInstance instance = (GKInstance) it.next();
           dbIDs.add(instance.getDBID());
         }
         fileAdaptor.clearDeleteRecord(dbIDs);
       } catch (IOException e) {
         System.err.println("SynchronizationDialog.clearDeleteRecord(): " + e);
         e.printStackTrace();
       }
       deleteList.deleteInstances(list);
       // Check if deleteList needs to be removed
       if (deleteList.getDisplayedInstances().size() == 0) {
         centerPane.remove(deleteList);
         centerPane.validate();
         centerPane.repaint();
       }
     }
   }
 }
 protected List getSynchronizingClassList(XMLFileAdaptor fileAdaptor) {
   GKSchemaClass topCls = selectedCls;
   if (topCls == null)
     topCls = (GKSchemaClass) ((GKSchema) fileAdaptor.getSchema()).getRootClass();
   List clsList = new ArrayList();
   InstanceUtilities.getDescendentClasses(clsList, topCls);
   return clsList;
 }
 private SchemaClass getDisplayedPESubclass(SchemaClass cls) {
   SchemaClass displayedCls = cls;
   // Only the first level of PE is displayed. Need to map it to one of
   // these subclasses
   XMLFileAdaptor fileAdaptor = PersistenceManager.getManager().getActiveFileAdaptor();
   GKSchemaClass pe =
       (GKSchemaClass)
           fileAdaptor.getSchema().getClassByName(ReactomeJavaConstants.PhysicalEntity);
   for (Iterator it = pe.getSubClasses().iterator(); it.hasNext(); ) {
     GKSchemaClass sub = (GKSchemaClass) it.next();
     if (cls.isa(sub)) {
       displayedCls = sub;
       break;
     }
   }
   return displayedCls;
 }
 @Override
 public void mapClass(
     OWLIndividual bpInstance,
     BioPAXFactory bpFactory,
     XMLFileAdaptor fileAdaptor,
     Map<OWLIndividual, GKInstance> bpToRInstancesMap)
     throws Exception {
   RDFSClass cls = bpInstance.getRDFType();
   if (cls != bpFactory.getpathwayClass()) return; // this method will work for pathway only
   GKInstance instance = fileAdaptor.createNewInstance(ReactomeJavaConstants.Pathway);
   bpToRInstancesMap.put(bpInstance, instance);
 }
 /**
  * Set the list of SchemaClasses to be displayed in this EntityInstanceListPane.
  *
  * @param classes
  * @throws Exception
  */
 public void setSchemaClasses(List<GKSchemaClass> classes, XMLFileAdaptor fileAdaptor)
     throws Exception {
   DefaultTreeModel model = (DefaultTreeModel) tree.getModel();
   DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
   root.removeAllChildren();
   for (GKSchemaClass cls : classes) {
     Collection instances = fileAdaptor.fetchInstancesByClass(cls.getName());
     // Don't add an empty class node to save space
     if (instances == null || instances.size() == 0) continue;
     DefaultMutableTreeNode clsNode = new DefaultMutableTreeNode(cls);
     root.add(clsNode);
     buildTree(instances, clsNode);
   }
   model.nodeStructureChanged(root);
 }
 private Map getLocalDeleteMap(XMLFileAdaptor fileAdaptor, List synClassList) {
   Map rtnMap = new HashMap();
   Map deleteMap = fileAdaptor.getDeleteMap();
   if (deleteMap != null && deleteMap.size() > 0) {
     List synClassName = new ArrayList(synClassList.size());
     for (Iterator it = synClassList.iterator(); it.hasNext(); ) {
       GKSchemaClass cls = (GKSchemaClass) it.next();
       synClassName.add(cls.getName());
     }
     for (Iterator it = deleteMap.keySet().iterator(); it.hasNext(); ) {
       Long dbID = (Long) it.next();
       String className = (String) deleteMap.get(dbID);
       if (synClassName.contains(className)) rtnMap.put(dbID, className);
     }
   }
   return rtnMap;
 }
 /**
  * Synchronize a local instance repository to the db repository. Calling this method may modify
  * deleteMap Map in the FileAdaptor object.
  *
  * @param fileAdaptor the PersistenceAdaptor for the local instance repository.
  * @param dbAdaptor the PersistenceAdaptor for the database instance repository.
  * @return Key: delete, deleteInDB, new and/or changed; Values: A list of instances
  *     <p>Sideeffect: changes typeMap.
  */
 private Map synchronize(final XMLFileAdaptor fileAdaptor, final MySQLAdaptor dbAdaptor) {
   // Need another thread to display the progress
   final ProgressDialog progDialog = new ProgressDialog((JFrame) getOwner());
   progDialog.setSize(300, 180);
   // GKApplicationUtilities.center(progDialog);
   progDialog.setLocationRelativeTo(progDialog.getOwner());
   progDialog.setModal(true);
   final List syncClassList = getSynchronizingClassList(fileAdaptor);
   // Get the total instance counter
   Schema schema = fileAdaptor.getSchema();
   SchemaClass cls = null;
   long total = 0;
   try {
     total = getTotalInstanceCount(fileAdaptor);
   } catch (Exception e) {
     System.err.println("SyncrhonizationEngine.synchronize(): " + e);
     e.printStackTrace();
   }
   progDialog.totalBar.setMaximum((int) total);
   progDialog.totalBar.setMinimum(0);
   // Let the synchronizing work in another thread.
   final Map map = new HashMap();
   Thread t =
       new Thread() {
         public void run() {
           java.util.List newInstances = new ArrayList();
           java.util.List changedInstances = new ArrayList();
           java.util.List deletedInDBInstances = new ArrayList();
           java.util.List localHasMoreIEInstances = new ArrayList();
           Schema schema = fileAdaptor.getSchema();
           SchemaClass schemaClass = null;
           Collection instances = null;
           GKInstance instance = null;
           GKInstance dbCopy = null;
           int index = 0;
           int total = 0;
           // For comparsing
           InstanceComparer comparer = new InstanceComparer();
           try {
             for (Iterator it = syncClassList.iterator(); it.hasNext(); ) {
               if (isCancelled) break;
               schemaClass = (SchemaClass) it.next();
               instances = fileAdaptor.fetchInstancesByClass(schemaClass, false);
               if (instances == null || instances.size() == 0) continue;
               progDialog.clsLabel.setText("Scan class " + schemaClass.getName() + "...");
               progDialog.clsBar.setMinimum(0);
               progDialog.clsBar.setMaximum(instances.size());
               List existedIDs = new ArrayList(instances.size());
               for (Iterator it1 = instances.iterator(); it1.hasNext(); ) {
                 instance = (GKInstance) it1.next();
                 if (instance.getDBID().longValue() < 0) {
                   newInstances.add(instance);
                   typeMap.put(instance, NEW_KEY);
                 } else // Shell instances should not be skipped since a shell instance can still
                   // be deleted locally so existence checking is needed.
                   existedIDs.add(instance.getDBID());
               }
               if (existedIDs.size() == 0) continue;
               Collection existences = dbAdaptor.fetchInstances(schemaClass.getName(), existedIDs);
               if (existences.size() > 0) {
                 // Load all modified attribute
                 SchemaAttribute att = schemaClass.getAttribute("modified");
                 // Load all atributes in a batch
                 dbAdaptor.loadInstanceAttributeValues(existences, att);
               }
               index = 0;
               for (Iterator it1 = instances.iterator(); it1.hasNext(); ) {
                 if (isCancelled) break;
                 instance = (GKInstance) it1.next();
                 if (instance.getDBID().longValue() < 0) { // Handled by the previous loop
                   continue;
                 }
                 // The schema class might be changed. Use the
                 // top-leve class to fetch instance
                 dbCopy = dbAdaptor.fetchInstance(instance.getDBID());
                 if (dbCopy == null) {
                   deletedInDBInstances.add(instance);
                   typeMap.put(instance, DELETE_IN_DB_KEY);
                 }
                 // Don't care a shell instance
                 else {
                   if (!instance.isShell()) {
                     int tmp = comparer.compare(instance, dbCopy);
                     String typeKey = mapCompareResultToString(tmp);
                     if (typeKey == LOCAL_HAS_MORE_IE_KEY) {
                       localHasMoreIEInstances.add(instance);
                       typeMap.put(instance, typeKey);
                     } else if (typeKey != IS_IDENTICAL_KEY) {
                       changedInstances.add(instance);
                       typeMap.put(instance, typeKey);
                     }
                   }
                 }
                 index++;
                 total++;
                 progDialog.clsBar.setValue(index);
                 progDialog.totalBar.setValue(total);
               }
             }
             if (deletedInDBInstances.size() > 0) map.put(DELETE_IN_DB_KEY, deletedInDBInstances);
             if (newInstances.size() > 0) map.put(NEW_KEY, newInstances);
             if (changedInstances.size() > 0) map.put(CHANGED_KEY, changedInstances);
             if (localHasMoreIEInstances.size() > 0)
               map.put(LOCAL_HAS_MORE_IE_KEY, localHasMoreIEInstances);
             // Check the delete instances
             Map deleteMap = getLocalDeleteMap(fileAdaptor, syncClassList);
             if (deleteMap != null && deleteMap.size() > 0) {
               java.util.List deleteInstances = new ArrayList();
               List clearingIDs = new ArrayList();
               for (Iterator it = deleteMap.keySet().iterator(); it.hasNext(); ) {
                 Long dbID = (Long) it.next();
                 String className = (String) deleteMap.get(dbID);
                 dbCopy = dbAdaptor.fetchInstance(className, dbID);
                 if (dbCopy != null) {
                   deleteInstances.add(dbCopy);
                   typeMap.put(dbCopy, DELETE_KEY);
                 } else clearingIDs.add(dbID);
               }
               if (deleteInstances.size() > 0) map.put(DELETE_KEY, deleteInstances);
               fileAdaptor.clearDeleteRecord(clearingIDs);
             }
             progDialog.dispose();
           } catch (Exception e) {
             System.err.println("SynchronizationEngine.synchronize() 1: " + e);
             e.printStackTrace();
             JOptionPane.showMessageDialog(
                 progDialog,
                 "Error in synchronizing: \n" + e,
                 "Error in Synchronizing",
                 JOptionPane.ERROR_MESSAGE);
             // Have to set this first to behavior correctly since thread issue.
             isCancelled = true;
             progDialog.dispose();
           }
         }
       };
   t.start();
   progDialog.setVisible(true);
   return map;
 }
  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);
    }
  }
 private void updateFromDB() {
   InstanceListPane touchedList = null;
   // Find out which instances have been selected in all relevant lists
   // Update the attribute values for changed list.
   try {
     if (changedList != null) {
       java.util.List list = new ArrayList(changedList.getSelection()); // To support it.remove()
       // Use a new ArrayList.
       if (list != null && list.size() > 0) {
         for (Iterator it = list.iterator(); it.hasNext(); ) {
           GKInstance instance = (GKInstance) it.next();
           // Fetch GKInstance based on its DB_ID since SchemaClass might be changed.
           GKInstance localCopy = fileAdaptor.fetchInstance(instance.getDBID());
           dbAdaptor.setUseCache(false);
           GKInstance dbCopy = dbAdaptor.fetchInstance(instance.getDBID());
           dbAdaptor.setUseCache(true);
           if (SynchronizationManager.getManager().updateFromDB(localCopy, dbCopy, this)) {
             AttributeEditManager.getManager().attributeEdit(localCopy);
             fileAdaptor.removeDirtyFlag(localCopy);
           } else it.remove(); // Remove from the list
         }
         // Remove all selected instances
         changedList.deleteInstances(list);
         touchedList = changedList;
       }
     }
     if (localHasMoreIEList != null && localHasMoreIEList.getSelection().size() > 0) {
       List list = new ArrayList(localHasMoreIEList.getSelection());
       for (Iterator it = list.iterator(); it.hasNext(); ) {
         GKInstance localCopy = (GKInstance) it.next();
         dbAdaptor.setUseCache(false);
         GKInstance dbCopy = dbAdaptor.fetchInstance(localCopy.getDBID());
         dbAdaptor.setUseCache(true);
         if (SynchronizationManager.getManager().updateFromDB(localCopy, dbCopy, this)) {
           AttributeEditManager.getManager().attributeEdit(localCopy);
           fileAdaptor.removeDirtyFlag(localCopy);
         } else it.remove(); // Remove from the list, if it it cancelled by the user.
       }
       localHasMoreIEList.deleteInstances(list);
       touchedList = localHasMoreIEList;
     }
     // Delete the local copy for deleteInDBList.
     if (deleteInDBList != null) {
       java.util.List list = deleteInDBList.getSelection();
       if (list != null && list.size() > 0) {
         for (Iterator it = list.iterator(); it.hasNext(); ) {
           GKInstance instance = (GKInstance) it.next();
           fileAdaptor.deleteInstance(instance);
         }
       }
       deleteInDBList.deleteInstances(list);
       touchedList = deleteInDBList;
     }
     // Get another copy for the local repository
     if (deleteList != null) {
       java.util.List<?> list = deleteList.getSelection();
       if (list != null && list.size() > 0) {
         Map<SchemaClass, Set<GKInstance>> checkOutMap =
             new HashMap<SchemaClass, Set<GKInstance>>(); // All checked out Instances
         for (Iterator<?> it = list.iterator(); it.hasNext(); ) {
           GKInstance instance = (GKInstance) it.next();
           Map<SchemaClass, List<GKInstance>> schemaMap =
               InstanceUtilities.listDownloadableInstances(instance);
           // Have to merge schemaMap to checkOutMap
           for (SchemaClass key : schemaMap.keySet()) {
             List<GKInstance> list1 = schemaMap.get(key);
             if (list1 != null && list1.size() > 0) {
               Set<GKInstance> list2 = checkOutMap.get(key);
               if (list2 == null) {
                 list2 = new HashSet<GKInstance>();
                 checkOutMap.put(key, list2);
               }
               // Remove first to avoid any duplication
               list2.addAll(list1);
             }
           }
         }
         fileAdaptor.store(checkOutMap);
         InstanceUtilities.clearShellFlags(checkOutMap);
         // There are maybe more than selected instances after checking out
         List<GKInstance> checkedOut = new ArrayList<GKInstance>();
         for (Set<GKInstance> set : checkOutMap.values()) {
           checkedOut.addAll(set);
         }
         deleteList.deleteInstances(checkedOut);
         // deleteList.deleteInstances(list);
         // Need to clear out these deletion records
         List<Long> dbIds = new ArrayList<Long>();
         for (GKInstance inst : checkedOut) dbIds.add(inst.getDBID());
         fileAdaptor.clearDeleteRecord(dbIds);
         touchedList = deleteList;
       }
     }
   } catch (Exception e) {
     System.err.println("SynchronizationDialog.updateFromDB(): " + e);
     e.printStackTrace();
   }
   updateInstanceList(touchedList);
 }
 protected long getTotalInstanceCount(XMLFileAdaptor fileAdaptor) throws Exception {
   GKSchemaClass topCls = selectedCls;
   if (topCls == null)
     topCls = (GKSchemaClass) ((GKSchema) fileAdaptor.getSchema()).getRootClass();
   return fileAdaptor.getClassInstanceCount(topCls);
 }