/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * 
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is mozilla addressbook code.
 *
 * The Initial Developer of the Original Code is Oracle Corporation.
 * Portions created by the Initial Developer are Copyright (C) 2005
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Dan Mosedale <dan.mosedale@oracle.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#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(2ba46eae-9141-4d79-af90-3c7ecf2dc357)]
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();

  /**
   * 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())
%}
