= Algorithms for category syncing. =

== Geneneral notes ==
All the things for handling full sync, hotsync and so on are in the base conduit
allready. The only thing we have to look at are how to handle copy category to
PC and copy category to handheld. Because the handheld only supports one
category per record for each application (as far as I know), the conduit keeps
only one category in sync. The last category that is kept in sync is stored in
some place to be aible to check next sync if the category has changed. The best
approach in my opinion to set a category to a record is to handle this through
the data store. In this way the base conduit doesn't have to know in detail how
categories are handled by a datastore.

To keep the framework general we work with Record.getCategories() which returns
all the categories set for a record. However because we know that a HHRecord
always has only one category and a pcrecord might for some conduits also have
always one category we add for convenience the Record.category() method which
returns Record.categories().first().


== Copy category to PC ==
In this case we have to handle two cases I think. First case is when the
record on the pc has either no or one category. In that case we replace the
category on the pc record with the category from the handheld. This strategy
also solves the problem when the database on the pc side only supports one
category which is the case for the keyring conduit. The only problem that might
arise in that case is that the category on the handheld is not available on the
pc and there's no room left. This seems a bit a hypothetical issue for me and I
suggest that we leave that for what it is. The only conduit we have at the
moment for which this problem might arise is the keyring conduit. If the record
on the pc has more than one category the algorithm looks if the category is
already there. When found, this category is stored somewhere (e.g. mapping)
otherwise the category is added to the pc record.

This results in the following algorithm:

copyHHCategoryToPc( HHRecord, PCRecord )
  if( PCRecord.categoryCount() <= 1 )
    // Removes all categories and set this only category and gives the datastore
    // the change to do some administrative things if necessary.
    PCDataStore.setCategory( PCRecord, HHRecord.category() )
  else
    if( !PCRecord.containsCategory( HHRecord.category() ) )
      // Keeps categories and adds another one
      PCDataStore.addCategory( PCRecord, HHRecord.category() )

  store( mapping, HHRecord.category() ) // Store the last synced category.

== Copy category to HH ==
This is a bit more difficult as we know that the handheld database only supports
16 categories at most. First we have to identify which cases we can encounter
here:

1. PCRecord has changed to no category => Set HHRecord to unfiled (default
   category).
2. PCRecord has changed to a category which is already available in the handheld
   datastore => set HHRecord to this category.
3. PCRecord has changed to a category which is not available in the handheld
   datastore but there's still place left => Add category to datastore and set
   HHRecord to this category.
4. PCRecord has changed to a category which is not available in the handheld
   datastore and there's no place left 
   => Present user categories available on handheld and ask what to do:
      1. Use for the HHRecord one of the categories available from the handheld
      2. Set the HHRecord to unfiled.
5. PCRecord was modified and contains more than one category => If the previous
   category was unfiled try to use one of the new categories. If the previous
   category is still set on the PCRecord, do nothing. If the previous synced
   record is not set to the PCRecord anymore, find a category that's already in
   the HHDatabase, otherwise case 3 or 4 is applicable.

This results in the following algorithm:

copyPCCategoryToHH( PCRecord, HHRecord )
  category = PCRecord.category()

  if( !PCRecord.hasCategory() )
    // Case 1
    HHDataStore.clearCategory( HHRecord )
  if( PCRecord.categoryCount == 1 )
    // Case 2, 3, 4
    if( HHDataStore.containsCategory( PCRecord.category() ) )
      // Case 2
      HHDataStore.setCategory( HHRecord, PCRecord.category() )
    else
      bool success = HHDataStore.setCategory( HHRecord, PCRecord.category() )
      if( succes )
        // Case 3, do nothing.
      else
        // Case 4, Ask the use which category to use
        category = askUser( HHDataStore.categories() )
        HHDataStore.setCategory( HHRecord, category )
  else
    // Case 5
    if( !PCRecord.containsCategory( HHRecord.category() ) )
      // The previous category has been removed
      bool synced = false
      iterator i( PCRecord.categories() )

      while( !synced && i.hasNext() )
        // Try each category
        category = i.next()

        if( HHDataStore.containsCategory( PCRecord.category() ) )
          // Case 2
          HHDataStore.setCategory( HHRecord, PCRecord.category() )
          synced = true
       
      if( !synced )
        // None of the categories set to the pc record are in the datastore
        // already. So we just try to set the first one and ask the user what to
        // do if the datastore cannont contain more categories.
        bool success = HHDataStore.setCategory( HHRecord, PCRecord.category() )
        if( succes )
          // Case 3, do nothing.
        else
          // Case 4, Ask the use which category to use
          category = askUser( HHDataStore.categories() )
          HHDataStore.setCategory( HHRecord, category )

  store( mapping, category ) // Store the last synced category.
