/* * CategoryManager.java */ package gnt; import palm.conduit.*; import java.io.*; import java.util.*; /* Copyright (c) 1997-2001 Palm Inc. or its subsidiaries. All rights reserved. */ /** * Performs all actions related to synchronizing Categories between the PC and hand-held device. */ public class CategoryManager { private int db; SyncProperties props; byte[] bytes; //the array of bytes from the hand-held device which contains the AppInfoBlock /** Constructor * @param props The SyncProperties object created while running the conduit. * @param db The handle of the open database. */ // public CategoryManager(SyncProperties props, int db) { // this.props = props; // this.db = db; // } // // /** Accesses the AppInfoBlock from the hand-held device and parses it into a Vector // * of category objects. // * @return A Vector of category objects // */ // public Vector getHHCategories() throws IOException { // //use the javasync api to read the AppInfoBlock from the AddressDB // bytes = SyncManager.readDBAppInfoBlock(db, props.remoteNames[0]); // return Category.parseCategories(bytes); // } // // /* // * Performs mirror synchronization of the hand-held and PC categories. This method // * automatically reads categories from the hand-held device and writes the // * synchronized categories back to the device.
// * First, the algorithm loops through all the Categories found on the device and // * deletes those that have been deleted on the PC. Next the PC Categories // * are compared to the device categories one at a time. Categories that are not found // * in the device categories are deleted, categories with name modifications are // * synchronized, etc. The synchronization logic assumes that each PC and device category // * has a status field (isModified) to indicate that the Category has been modified. // * The synchronization algorithm can be summarized by the following table: // *

// * // * // * // * // * // * // * // * // * // * // * // * // *
Palm Rec State PC Rec State Action
Add No category The category is added on the PC.
No category Add The category is added on the handheld.
Delete No modify The category is deleted on the PC.
No modify Delete The category is deleted on the handheld.
Modify Delete The device modifications are reflected on the PC. The PC category is not deleted.
Delete Modify The PC modifications are reflected on the device. The device category is not deleted.
Modify No modify The device modifications are reflected on the PC.
No modify Modify The PC modifications are reflected on the device.
Modify Modify If the modifications are identical, no action is taken.
Modify Modify If the modifications are different, both categories are placed on both the PC and device.

// * @param pcCategories A Vector of category objects that exist on the PC // * @param pcRecords A vector of record objects that exist on the PC // * @return A Vector of synchronized category objects // * @exception java.io.IOException thrown if cannot read the categories // */ // public Vector synchronize(Vector pcCategories, Vector pcRecords) throws IOException{ // // Vector hhCategories; // Category hhCat, pcCat; // boolean deleteCat; // // //parse out the category information from the device // hhCategories = getHHCategories(); // // if (props.syncType == props.SYNC_DO_NOTHING) { // // // Do nothing to the pcCategories // return pcCategories; // // } else if (props.syncType == props.SYNC_HH_TO_PC) { // // // Copy HH categories to PC // return hhCategories; // // } else if (pcCategories.size() == 0) { // // // This will initialize a test file of categories if the pc categories are empty // // Copy HH categories to PC // for (int i = 0; i < hhCategories.size(); i ++){ // hhCat = (Category)hhCategories.elementAt(i); // hhCat.setIsModified(false); // } // writeHHCategories(hhCategories); // return hhCategories; // // } else if (props.syncType == props.SYNC_PC_TO_HH) { // // // Copy the PC categories to the HH, done below. // // } else { // FastSync or SlowSync // // // If the PC has not yet be synced with, then set all the HH category flags so // // those HH categories get added and not deleted // if (props.firstDevice == props.SYNC_PC_FIRST_SYNC) { // setDirtyCategoryFlags(hhCategories); // // // If the HH has not yet be synced with, then set all the PC category flags so // // those PC categories get added and not deleted // } else if (props.firstDevice == props.SYNC_HH_FIRST_SYNC) { // setDirtyCategoryFlags(pcCategories); // // // If this is a slow sync that means that the last sync was with // // a different PC, so set the category dirty flags on the HH // // because they were cleared in the last sync. // } else if (props.syncType == props.SYNC_SLOW) { // setDirtyCategoryFlags(hhCategories); // } // // // First search through the HH categories and delete the categories that // // were deleted from the PC and need to be deleted from the HH. // // A category needs to be deleted when the category exists on one side // // and not the other and the dirty flag is off. // // for (int i = 0; i < hhCategories.size(); i ++){ // // hhCat = (Category)hhCategories.elementAt(i); // // deleteCat = true; // // if (!hhCat.getName().equals("") && !hhCat.isModified() && // matchName(hhCat.getName(), pcCategories) == null && // matchId(hhCat.getId(), pcCategories) == null) { // // // The category has been deleted on the PC, so needs // // to be deleted on the HH. Also, change all the // // records under that category to be Unfiled. // // Move records to unfiled - Report to Log // try { // SyncManager.changeCategory(db, hhCat.getIndex(), 0); // } catch(SyncException e){ // // Log.err("MemoCond Error: Error Changing Categories"); // e.printStackTrace(); // deleteCat = false; // } // // if (deleteCat){ // Log.out("Handheld Category Deleted: " + hhCat.getName()); // hhCat.delete(); // } // } // else hhCat.setIsModified(false); // } // // // Merge the PC categories into the HH categories // for (int i = 0; i < pcCategories.size(); i++){ // // pcCat = (Category)pcCategories.elementAt(i); // // if (!pcCat.getName().equals("")){ // // hhCat = matchName(pcCat.getName(), hhCategories); // // if(hhCat != null){ // // // PC catName exists on HH // // catIndexes are different and HH index must be chosen // if (pcCat.getIndex() != hhCat.getIndex()) { // // Change the PC catIndex // int oldCatIndex = pcCat.getIndex(); // pcCat.setIndex(hhCat.getIndex()); // // Update PC records belonging to that PC category // // to it's new category index assigned from handheld // updateRecordsCategory(pcRecords, oldCatIndex, pcCat.getIndex()); // } // } // else { // PC catName does not exist on HH // // // if PC catID exists on HH // hhCat = matchId(pcCat.getId(), hhCategories); // if (hhCat != null) { // // If PC category was renamed, then replace the HH // // catName with the PC catName // if (pcCat.isModified()) { // // hhCat.setName(pcCat.getName()); // // // If the indexes are different, change the PC catIndex // } else if (pcCat.getIndex() != hhCat.getIndex()) { // int oldCatIndex = pcCat.getIndex(); // pcCat.setIndex(hhCat.getIndex()); // // Update PC records belonging to that PC category // // to it's new category index assigned from handheld // updateRecordsCategory(pcRecords, oldCatIndex, pcCat.getIndex()); // } // } // else { // // // If the category exists on the PC but not on the HH and // // the dirty flag is not on, the category must have been // // deleted on the HH, therefore needs to be deleted on PC. // if (!pcCat.isModified()) { // // Report to Log // Log.out("Desktop Category Deleted: " + pcCat.getName()); // pcCat.delete(); // // } else { // New category from PC // // hhCat = (Category)hhCategories.elementAt(pcCat.getIndex()); // // // PC catIndex does not exist on HH, so add PC category // // as is to the HH Category Manager // if (hhCat.getName().equals("")) { // hhCat.setName(pcCat.getName()); // hhCat.setId(pcCat.getId()); // // } else { // PC catIndex already exists // // // Find the next available catIndex on the HH // int nextIndex = getNextIndex(hhCategories); // // if (nextIndex == -1) { // Category Manager is Full // // // Too many categories - Report to Log // Log.out("MemoCond Error: Too Many Categories. Category not added to handheld device: " + pcCat.getName()); // } else { // // // Change PC catIndex to next available HH catIndex // int oldCatIndex = pcCat.getIndex(); // pcCat.setIndex(nextIndex); // // // Add the PC Category // hhCat = (Category)hhCategories.elementAt(nextIndex); // hhCat.setName(pcCat.getName()); // hhCat.setId(pcCat.getId()); // // // Update PC records belonging to that PC category // // to it's new category index assigned from handheld // updateRecordsCategory(pcRecords, oldCatIndex, pcCat.getIndex()); // } // } // } // } // } // } // } // } // // //point the input categories at the synchronized hhCategories // pcCategories = hhCategories; // // //write the categories back out to the AppInfoBlock on the device // writeHHCategories(hhCategories); // return hhCategories; // } // // /** Writes a Vector of category objects back to the device. // * @param hhCategories A Vector of category objects to be written to the device // */ // public void writeHHCategories(Vector hhCategories) throws IOException{ // byte []tmp = Category.toBytes(hhCategories); // System.arraycopy(tmp, 0, bytes, 0, tmp.length); // // //write the synchronized categories to the device // SyncManager.writeDBAppInfoBlock(db, props.remoteNames[0], bytes); // } // // private void setDirtyCategoryFlags(Vector hhCategories){ // // for (int i = 0; i < hhCategories.size(); i++) { // Category tempCategory = (Category)hhCategories.elementAt(i); // tempCategory.setIsModified(true); // } // } // // //this method searches for a particular category name within a vector of categories // private Category matchName(String name, Vector categories){ // // Category category; // String categoryName; // // for (int i = 0; i < categories.size(); i++) { // // category = (Category)categories.elementAt(i); // // categoryName = category.getName(); // // if (categoryName != "" && name.equals(categoryName)) { // return category; // } // } // return null; // } // //this method searches for a particular category id within a vector of categories // private Category matchId(int id, Vector categories){ // // Category category; // // for (int i = 0; i < categories.size(); i++) { // // category = (Category)categories.elementAt(i); // // if (id == category.getId() && id != 0) { // return category; // } // } // return null; // } // // private int getNextIndex(Vector categories) { // // int nextIndex = -1; // Category tempCategory; // // for (int i = 0; i < categories.size(); i++) { // // tempCategory = (Category)categories.elementAt(i); // // if (tempCategory.getName().equals("")){ // nextIndex = tempCategory.getIndex(); // return nextIndex; // } // } // return nextIndex; // } // // private void updateRecordsCategory(Vector pcRecords, int oldCatIndex, int newCatIndex) { // // // Cycle throught the pcRecords vector and replace // // the old cat index with the new cat index // if (pcRecords != null) { // // Record pcRecord; // pcRecords.trimToSize(); // // for (int i = 0; i < pcRecords.size(); i++){ // // pcRecord = (Record)pcRecords.elementAt(i); // if (pcRecord.getCategoryIndex() == oldCatIndex) // pcRecord.setCategoryIndex(newCatIndex); // } // } // } }