MailNews:Address Book Interface Redesign

From MozillaWiki
Revision as of 17:04, 2 February 2008 by Standard8 (talk | contribs) (→‎Revised nsIAbManager Interface: Split new into create and register)
Jump to navigation Jump to search

With the interest of someone working on a sql backend for Address Book, various discussions have been held on irc regarding redesign of some of the interfaces (and hence classes in the address book).

The aim of the redesign would be to:

  • make it easier to add new address book types
  • support all the existing functionality we have already where possible
  • separate out the mailing list implementation from nsIAbCard and nsIAbDirectory
  • support as much functionality at implementation independent levels where possible
  • make it easier for groups/mailing lists/etc to be defined and controlled
  • could we make the structure to support recursive groups/mailing lists/etc?

This page is still WIP for even the initial design thoughts. Please use the Talk Page for comments

Current Structure

On Trunk as at 15th January 2008:

  • nsIAbManager
    • just about handles creation of new mork based address books. Sort-of handles LDAP books
    • Some utility functions
    • won't handle enable/removal of OSX or Outlook books.
  • nsIAbCard
    • Lots of attributes for each of the items on a card, can also represent mailing lists, but doesn't contain the list contains.
  • nsIAbDirectory
    • Represents an address book, is mostly implementation-independent but not quite.
    • Can also represent a mailing list, in which case most of the other properties are useless.

Thoughts that need clarification/decisions

  • Do we allow different Address Book types at different levels in a recursive structure?
    • Could be complicated with outlook books (one backend-book = multiple outlook books)

Revised nsIAbManager Interface

  • Handles addition/deletion of new address books (modifications of properties handled directly on nsIAbDirectory).
interface nsIAbManager : nsISupports
{
  /**
   * Returns a list of all the directories currently registered.
   *
   * @param  aCount        The number of directories registered.
   * @param  aDirectories  The array of directories.
   */
  void getDirectories(out PRUint32 aCount,
                      [array, size_is(aCount), retval] out nsIAbDirectory aDirectories);

  /**
   * Creates a new directory of the specified type but does not register it
   * with the manager.
   *
   * @param  aType         The type of the directory, e.g. "sql", "ldap", etc.
   * @return               An object of the specific directory type whose
   *                       attributes can then be modified/set.
   */
  nsIAbDirectory createDirectory(in AUTF8String aType);

  /**
   * Registers a directory with the manager.
   *
   * @param  aDirectory    The directory to register.
   */
  void registerDirectory(in nsIAbDirectory aDirectory);

  /**
   * Deletes a directory and unregisters it.
   *
   * @param  aDirectory    The directory to delete.
   */
  void deleteDirectory(in nsIAbDirectory aDirectory);
...
}

Notes/Thoughts:

  • Why does createCalendar have URI, why do they feel its necessary to set the URI in calCalendarManager?
  • Will the delete directory work - check what nsIAbDirectory implements.
  • Should we provide a nsISimpleEnumerator version of getDirectories, or is that overkill?
  • nsIAbDirFactory and its implementations won't be required.

Proposed Structure For the Main Interfaces

  • Proposed Interface Inheritance Structure:
            nsIAbItem
                |
    |-------------------------|
nsIAbCard               nsIAbCollection
                              |
                    |--------------------|
                nsIAbGroup         nsIAbDirectory

nsIAbItem

  • Base address book item.
  • Contains functions/attributes generic to all items.
  • All items are derived from this one.
interface nsIAbItem : nsISupports
{
  /**
   * Unique identifier for this item.
   *
   * @ exception NS_ERROR_ILLEGAL_VALUE  The supplied uuid is invalid.
   */
  attribute AUTF8String uuid;
...
}

Notes/Thoughts:

  • Need a format (or at least examples) for the uuid.
  • Do we need a type attribute (e.g. LDAP/SQL etc) or is this better on nsIAbCollection?

nsIAbCard

  • Represents a card.
  • No link to database. Modified card must be presented to directory in order for the database to be updated (this means we can easily enforce reducing the amount of database operations).
  • Generic attribute get/set.
interface nsIAbCard : nsIAbItem
{
  /**
   * A list of all the properties that this card has as an enumerator, whose
   * members are all nsIProperty objects.
   */
  readonly attribute nsISimpleEnumerator properties;
 
  /**
   * @{
   * Returns a property for the given name.
   *
   * @exception NS_ERROR_FAILURE if the named property does not exist.
   */
  nsIVariant getProperty(in AString name);
  AString getPropertyAsAString(in AString name);
  AUTF8String getPropertyAsAUTF8String(in AString name);
  PRUint32 getPropertyAsUint32(in AString name);
  boolean getPropertyAsBool(in AString name);
  /** @} */

  /**
   * @{
   * Assigns the given to value to the property of the given name.
   *
   * Should the property exist, its value will be overwritten. An
   * implementation may impose additional semantic constraints for certain
   * properties.
   *
   * @exception NS_ERROR_ILLEGAL_VAlUE if the value violates a constraint.
   * @exception NS_ERROR_FAILURE if the value is required.
   */
  void setProperty(in AString name, in nsIVariant value);
  void setPropertyAsAString(in AString name, in AString value);
  void setPropertyAsAUTF8String(in AString name, in AUTF8String value);
  void setPropertyAsUint32(in AString name, in PRUint32 value);
  void setPropertyAsBool(in AString name, in boolean value);
  /** @} */

  /**
   * Deletes the property with the given name.
   *
   * Some properties may not be deleted.
   *
   * @exception NS_ERROR_FAILURE if the value is required by an implementation.
   */
  void deleteProperty(in AString name);

  
  /**
   * Generates an XML format encoded in Base 64 string from the data in this
   * card.
   *
   * @return                A string containing the Base-64 encoded XML.
   */
  ACString generateBase64EncodedXML();

  /**
   * Generates an XML string, in a format suitable for printing, from the data
   * in this card.
   *
   * @return                A string containing the XML data.
   */
  AString generateXMLPrintData();

  /**
   * Generates an escaped vcard from the data in this card.
   *
   * @return                A string containing the escaped vcard.
   */
  ACString generateEscapedVCard();

  /** 
   * Generate a name from the card for display purposes. Using the firstName,
   * lastName and the displayName. We allow the caller to cache the pref value,
   * so we don't have to go to prefs every time.
   *
   * The format follows the "mail.addr_book.lastnamefirst" pref values:
   *
   * 0 = generated name is displayName
   * 1 = lastFirst, formatted following lastFirstFormat
   * 2 = firstLast, formatted following firstLastFormat
   *
   * lastFirstFormat and firstLastFormat are defined in addressBook.properties.
   *
   * @param  aGenerateFormat The format to generate as per the above definition.
   * @param  aBundle         An optional parameter that is a pointer to a string
   *                         bundle that holds:
   *           chrome://messenger/locale/addressbook/addressBook.properties
   *                         If this bundle is not supplied, then the function
   *                         will obtain the bundle itself. If cached by the
   *                         caller and supplied to this function, then
   *                         performance will be improved over many calls.
   * @return                 A string containing the generated name.
   */
  AString generateName(in long aGenerateFormat,
                       [optional] in nsIStringBundle aBundle);

  /** 
   * Generate a phonetic name from the card, using the firstName and lastName
   * values.
   *
   * @param  aLastNameFirst  Set to True to put the last name before the first.
   * @return                 A string containing the generated phonetic name.
   */
  AString generatePhoneticName(in boolean aLastNameFirst);

  /**
   * Generate a formatted email address from the card, that can be used for
   * sending emails.
   *
   * @param  aExpandList     If this card is a list, and this parameter is set
   *                         to true, then the list will be expanded to include
   *                         the emails of the cards within the list.
   * @param  aGroupMailLists If this card (or the items within this card) is a
   *                         list, and this is set to true, then the list will
   *                         be expanded in the RFC 2822 group format
   *                         "displayname : email1 ; email2 ; etc".
   * @param  aHeaderParser   An optional parameter pointing to the
   *                         nsIMsgHeaderParser service. If this is not supplied
   *                         the function will obtain the service itself. If
   *                         cached by the called and supplied to this function,
   *                         then performance will be improved over many calls.
   * @return                 A string containing a comma-separated list of
   *                         formatted addresses.
   */
  AString generateFormattedEmail(in boolean aExpandList,
                                 in boolean aAsGroupMailLists,
                                 [optional] in nsIMsgHeaderParser aHeaderParser);

...
}

Notes/Thoughts:

  • Most internal properties stored in a property bag, some "important" properties stored local for fast-access.
  • If directories save their own attribute modifications, but cards don't, is
  • this acceptable?

nsIAbCollection

  • Represents a collection of nsIAbItem.
    • Currently unclear as to if we'll allow nsIAbDirectory items to be included in anything other than the top-level).
  • Contains methods for searching its nsIAbItem collection.
interface nsIAbCollection : nsIAbItem
{
  /**
   * Opens the properties dialog for this collection.
   */
  void openPropertiesDialog();

  /**
   * Returns true if this collection is read-only.
   */
  readonly attribute boolean readOnly;

  /**
   * Returns true if the collection requires specific protocol access over a
   * network connection.
   */
  readonly attribute boolean isRemote;

  /**
   * Returns true if the collection is remote and is accessed over a secure
   * protocol (as in LDAP over SSL).
   */
  readonly attribute boolean isSecure;

  /**
   * Returns an array of the child items.
   */
  void getChildItems(out PRUint32 aCount,
                     [array, size_is(count), retval] out nsIAbItem aChildItems);

  /**
   * Returns a new search instance, set up to be able to search the current
   * collection.
   *
   * @exception NS_ERROR_NOT_IMPLEMENTED  Search is not available for this
   *                                      collection.
   */
  readonly attribute nsIAbDirectorySearch searchInstance;

  /** 
   * Returns the first nsIAbItem that matches the specified property. This will
   * only return the first item found, unlike searching via the searchInstance.
   *
   * @param  aProperty      The property on the item to look up.
   * @param  aValue         The value to which to match on the property.
   * @param  aCaseSensitive Set to true for a case sensitive match.
   * @return                The card if it is found.
   * @exceptions NS_ERROR_NOT_FOUND
   *                        No matching cards have been found.
   */
  nsIAbItem cardForProperty(in ACString aProperty, in AString aValue,
                            in boolean aCaseSensitive);

  /**
   * Adds an item to the collection.
   *
   * @param     aItem                     The item to add to the collection.
   * @return                              The item added. This may be different
   *                                      to aItem for implementation-specific
   *                                      items.
   * @exception NS_ERROR_????             The item could not be added to this
   *                                      collection.
   */
  nsIAbItem addItem(in nsIAbItem aItem);

  /**
   * Adds multiple items to the collection.
   *
   * @param     aItems                    The items to add to the collection,
   *                                      these may be exchanged for new items
   *                                      to allow them to be replaced by
   *                                      implementation specific items.
   */
  void addItems(inout nsIMutableArray aItems);

...
}

Notes/Thoughts:

  • Does this need any properties?
  • Do we need an enumerator version of getChildItems?
  • How do we open property dialogs for new nsIAbCollections not created yet?
    • Create an instance via nsIAbManager, then call the function - I've still got to change the manager for this --Standard8 07:05, 25 January 2008 (PST)
  • lastModifiedDate?
  • What about email case-sensitivity?

nsIAbGroup

  • Interface for functions/attributes slightly more specific to groups of items.
  • Not sure what these are yet.
  • A Group could be a Mailing List, Saved Search Folder, Collection of Tags etc.
interface nsIAbGroup : nsIAbCollection
{
...
}

Notes/Thoughts:

nsIAbDirectory

  • Interface for functions/attributes slightly more specific to directories.
  • Not sure what these are yet.
interface nsIAbDirectory : nsICollection
{
...
}

Notes/Thoughts:


nsIAbDirectorySearch

  • Provides an interface to be able to search collections.
  • Implementations may be specific to directory types.
interface nsIAbDirectorySearch : nsISupports
{
  /**
   * Starts the search.
   *
   * @param  aSearchParams  The parameters to use for the search.
   */
  void startSearch(in nsIAbBooleanExpression aSearchParams);

  /**
   * Stops/interrupts the search.
   */
  void stopSearch();
...
}

Notes/Thoughts: