/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * 
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsISupports.idl"

interface nsISimpleEnumerator;
interface nsILDAPMessage;
interface nsIAbCard;

/**
 * A mapping between addressbook properties and ldap attributes.
 *
 * Each addressbook property can map to one or more attributes.  If
 * there is no entry in preferences for a field, the getters generally
 * return null; empty strings are passed through as usual. The intent is
 * that properties with a non-zero number of attributes can be overridden for
 * a specific server by supplying a zero-length string.  For this to work,
 * most callers are likely to want to check for both success and a 
 * non-empty string. 
 *
 * Note that the one exception to this pattern is getAttributes, which
 * throws NS_ERROR_FAILURE for non-existent property entries, since
 * XPConnect doesn't like returning null arrays.
 *
 * Note that each LDAP attribute can map to at most one addressbook
 * property.  The checkState method is a useful tool in enforcing
 * this.  Failure to enforce it may make it impossible to guarantee
 * that getProperty will do something consistent and reasonable.
 *
 * Maybe someday once we support ldap autoconfig stuff (ie
 * draft-joslin-config-schema-11.txt), we can simplify this and other
 * code and only allow a property to map to a single attribute.
 */
[scriptable, uuid(fa019fd1-7f3d-417a-8957-154cca0240be)]
interface nsIAbLDAPAttributeMap : nsISupports
{
  /**
   * Get all the LDAP attributes associated with a given property
   * name, in order of precedence (highest to lowest).
   *
   * @param       aProperty   the address book property to return attrs for   
   *    
   * @return      a comma-separated list of attributes, null if no entry is
   *              present
   */
  ACString getAttributeList(in ACString aProperty);

  /**
   * Get all the LDAP attributes associated with a given property name, in 
   * order of precedence (highest to lowest).
   * 
   * @param       aProperty   the address book property to return attrs for   
   *
   * @return      an array of attributes
   *
   * @exception   NS_ERROR_FAILURE if there is no entry for this property
   */
  void getAttributes(in ACString aProperty, out unsigned long aCount,
                     [retval, array, size_is(aCount)] out string aAttrs);

  /**
   * Get the first (canonical) LDAP attribute associated with a given property
   * name
   *
   * @param       aProperty   the address book property to return attrs for   
   * 
   * @return      the first attribute associated with a given property, 
   *              null if there is no entry for this property
   */
  ACString getFirstAttribute(in ACString aProperty);

  /**
   * Set an existing mapping to the comma-separated list of attributes.
   * 
   * @param aProperty               the mozilla addressbook property name
   *
   * @param aAttributeList          a comma-separated list of attributes in
   *                                order of precedence from high to low
   *
   * @param aAllowInconsistencies   allow changes that would result in
   *                                a map with an LDAP attribute associated
   *                                with more than one property.  Useful for
   *                                doing a bunch of sets at once, and
   *                                calling checkState at the end.
   *
   * @exception NS_ERROR_FAILURE    making this change would result in a map
   *                                with an LDAP attribute pointing to more
   *                                than one property
   */
  void setAttributeList(in ACString aProperty, in ACString aAttributeList,
                        in boolean allowInconsistencies);

  /**
   * Find the Mozilla addressbook property name that this attribute should
   * map to. 
   * 
   * @return the addressbook property name, null if it's not used in the map
   */
  ACString getProperty(in ACString aAttribute);

  /**
   * Get all attributes that may be used in an addressbook card via this
   * property map (used for passing to to an LDAP search when you want
   * everything that could be in a card returned).
   *
   * @return                      a comma-separated list of attribute names
   *
   * @exception NS_ERROR_FAILURE  there are no attributes in this property map
   */
  ACString getAllCardAttributes();
  
  /**
   * Get all properties that may be used in an addressbook card via this
   * property map.
   *
   * @return                      an array of properties
   *
   * @exception NS_ERROR_FAILURE  there are no attributes in this property map
   */
  void getAllCardProperties(out unsigned long aCount,
                            [retval, array, size_is(aCount)] out string aProps);

  /**
   * Check that no LDAP attributes are listed in more than one property.
   *
   * @exception NS_ERROR_FAILURE    one or more LDAP attributes are listed
   *                                multiple times.  The object is now in an
   *                                inconsistent state, and should be either
   *                                manually repaired or discarded.
   */
  void checkState();

  /* These last two methods are really just for the convenience of the caller
   * and to avoid tons of unnecessary crossing of the XPConnect boundary.
   */

  /**
   * Set any attributes specified in the given prefbranch on this object.
   *
   * @param aPrefBranchName         the pref branch containing all the
   *                                property names
   * 
   * @exception NS_ERROR_FAILURE    one or more LDAP attributes are listed
   *                                multiple times.  The object is now in an
   *                                inconsistent state, and should be either
   *                                manually repaired or discarded.
   */
  void setFromPrefs(in ACString aPrefBranchName);

  /**
   * Set the properties on an addressbook card from the given LDAP message
   * using the map in this object.
   *
   * @param       aCard is the card object whose values are to be set
   * @param       aMessage is the LDAP message to get the values from
   *
   * @exception   NS_ERROR_FAILURE is thrown if no addressbook properties
   *              are found in the message
   */
  void setCardPropertiesFromLDAPMessage(in nsILDAPMessage aMessage,
                                        in nsIAbCard aCard);
};

/**
 * The nsIAbLDAPAttributeMapService is used to build and hold a cache
 * of maps.  
 */
[scriptable, uuid(12e2d589-3c2a-48e4-8c82-b1e6464a0dfd)]
interface nsIAbLDAPAttributeMapService : nsISupports
{
  /**
   * Accessor to construct or return a cached copy of the attribute
   * map for a given preference branch.  The map is constructed by
   * first taking the default map (as specified by the
   * "ldap_2.servers.default.attrmap" prefbranch), and then having any
   * preferences specified by aPrefBranchName override the defaults.
   * LDIF import and export code should use the default map.
   *
   * @return      the requested map
   *
   * @exception   NS_ERROR_FAILURE    error constructing the map;
   *                                  possibly because of a failure
   *                                  from checkState()
   */
  nsIAbLDAPAttributeMap getMapForPrefBranch(in ACString aPrefBranchName);
};


%{C++
// test whether one of the getters has actually found an attribute
#define ATTRMAP_FOUND_ATTR(rv, str) (NS_SUCCEEDED(rv) && !(str).IsEmpty())
%}
