Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

300 lines
9.7 KiB
C#

/******************************************************************************
* The MIT License
* Copyright (c) 2003 Novell Inc. www.novell.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the Software), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*******************************************************************************/
//
// Novell.Directory.Ldap.LdapCompareAttrNames.cs
//
// Author:
// Sunil Kumar (Sunilk@novell.com)
//
// (C) 2003 Novell, Inc (http://www.novell.com)
//
using System;
using Novell.Directory.Ldap.Utilclass;
namespace Novell.Directory.Ldap
{
/// <summary> Compares Ldap entries based on attribute name.
///
/// An object of this class defines ordering when sorting LdapEntries,
/// usually from search results. When using this Comparator, LdapEntry objects
/// are sorted by the attribute names(s) passed in on the
/// constructor, in ascending or descending order. The object is typically
/// supplied to an implementation of the collection interfaces such as
/// java.util.TreeSet which performs sorting.
///
/// Comparison is performed via locale-sensitive Java String comparison,
/// which may not correspond to the Ldap ordering rules by which an Ldap server
/// would sort them.
///
/// </summary>
public class LdapCompareAttrNames : System.Collections.IComparer
{
private void InitBlock()
{
// location = Locale.getDefault();
location=System.Globalization.CultureInfo.CurrentCulture;
collator = System.Globalization.CultureInfo.CurrentCulture.CompareInfo;
}
/// <summary> Returns the locale to be used for sorting, if a locale has been
/// specified.
///
/// If locale is null, a basic String.compareTo method is used for
/// collation. If non-null, a locale-specific collation is used.
///
/// </summary>
/// <returns> The locale if one has been specified
/// </returns>
/// <summary> Sets the locale to be used for sorting.
///
/// </summary>
/// <param name="locale"> The locale to be used for sorting.
/// </param>
virtual public System.Globalization.CultureInfo Locale
{
get
{
//currently supports only English local.
return location;
}
set
{
collator = value.CompareInfo;
location = value;
}
}
private System.String[] sortByNames; //names to to sort by.
private bool[] sortAscending; //true if sorting ascending
private System.Globalization.CultureInfo location;
private System.Globalization.CompareInfo collator;
/// <summary> Constructs an object that sorts results by a single attribute, in
/// ascending order.
///
/// </summary>
/// <param name="attrName"> Name of an attribute by which to sort.
///
/// </param>
public LdapCompareAttrNames(System.String attrName)
{
InitBlock();
sortByNames = new System.String[1];
sortByNames[0] = attrName;
sortAscending = new bool[1];
sortAscending[0] = true;
}
/// <summary> Constructs an object that sorts results by a single attribute, in
/// either ascending or descending order.
///
/// </summary>
/// <param name="attrName"> Name of an attribute to sort by.
///
/// </param>
/// <param name="ascendingFlag"> True specifies ascending order; false specifies
/// descending order.
/// </param>
public LdapCompareAttrNames(System.String attrName, bool ascendingFlag)
{
InitBlock();
sortByNames = new System.String[1];
sortByNames[0] = attrName;
sortAscending = new bool[1];
sortAscending[0] = ascendingFlag;
}
/// <summary> Constructs an object that sorts by one or more attributes, in the
/// order provided, in ascending order.
///
/// Note: Novell eDirectory allows sorting by one attribute only. The
/// direcctory server must also be configured to index the specified
/// attribute.
///
/// </summary>
/// <param name="attrNames"> Array of names of attributes to sort by.
///
/// </param>
public LdapCompareAttrNames(System.String[] attrNames)
{
InitBlock();
sortByNames = new System.String[attrNames.Length];
sortAscending = new bool[attrNames.Length];
for (int i = 0; i < attrNames.Length; i++)
{
sortByNames[i] = attrNames[i];
sortAscending[i] = true;
}
}
/// <summary> Constructs an object that sorts by one or more attributes, in the
/// order provided, in either ascending or descending order for each
/// attribute.
///
/// Note: Novell eDirectory supports only ascending sort order (A,B,C ...)
/// and allows sorting only by one attribute. The directory server must be
/// configured to index this attribute.
///
/// </summary>
/// <param name="attrNames"> Array of names of attributes to sort by.
///
/// </param>
/// <param name="ascendingFlags"> Array of flags, one for each attrName, where
/// true specifies ascending order and false specifies
/// descending order. An LdapException is thrown if
/// the length of ascendingFlags is not greater than
/// or equal to the length of attrNames.
///
/// </param>
/// <exception> LdapException A general exception which includes an error
/// message and an Ldap error code.
///
/// </exception>
public LdapCompareAttrNames(System.String[] attrNames, bool[] ascendingFlags)
{
InitBlock();
if (attrNames.Length != ascendingFlags.Length)
{
throw new LdapException(ExceptionMessages.UNEQUAL_LENGTHS, LdapException.INAPPROPRIATE_MATCHING, (System.String) null);
//"Length of attribute Name array does not equal length of Flags array"
}
sortByNames = new System.String[attrNames.Length];
sortAscending = new bool[ascendingFlags.Length];
for (int i = 0; i < attrNames.Length; i++)
{
sortByNames[i] = attrNames[i];
sortAscending[i] = ascendingFlags[i];
}
}
/// <summary> Compares the the attributes of the first LdapEntry to the second.
/// Only the values of the attributes named at the construction of this
/// object will be compared. Multi-valued attributes compare on the first
/// value only.
///
/// </summary>
/// <param name="object1"> Target entry for comparison.
///
/// </param>
/// <param name="object2"> Entry to be compared to.
///
/// </param>
/// <returns> Negative value if the first entry is less than the second and
/// positive if the first is greater than the second. Zero is returned if all
/// attributes to be compared are the same.
/// </returns>
public virtual int Compare(System.Object object1, System.Object object2)
{
LdapEntry entry1 = (LdapEntry) object1;
LdapEntry entry2 = (LdapEntry) object2;
LdapAttribute one, two;
System.String[] first; //multivalued attributes are ignored.
System.String[] second; //we just use the first element
int compare, i = 0;
if (collator == null)
{
//using default locale
collator = System.Globalization.CultureInfo.CurrentCulture.CompareInfo;
}
do
{
//while first and second are equal
one = entry1.getAttribute(sortByNames[i]);
two = entry2.getAttribute(sortByNames[i]);
if ((one != null) && (two != null))
{
first = one.StringValueArray;
second = two.StringValueArray;
compare = collator.Compare(first[0], second[0]);
}
//We could also use the other multivalued attributes to break ties.
//one of the entries was null
else
{
if (one != null)
compare = - 1;
//one is greater than two
else if (two != null)
compare = 1;
//one is lesser than two
else
compare = 0; //tie - break it with the next attribute name
}
i++;
}
while ((compare == 0) && (i < sortByNames.Length));
if (sortAscending[i - 1])
{
// return the normal ascending comparison.
return compare;
}
else
{
// negate the comparison for a descending comparison.
return - compare;
}
}
/// <summary> Determines if this comparator is equal to the comparator passed in.
///
/// This will return true if the comparator is an instance of
/// LdapCompareAttrNames and compares the same attributes names in the same
/// order.
///
/// </summary>
/// <returns> true the comparators are equal
/// </returns>
public override bool Equals(System.Object comparator)
{
if (!(comparator is LdapCompareAttrNames))
{
return false;
}
LdapCompareAttrNames comp = (LdapCompareAttrNames) comparator;
// Test to see if the attribute to compare are the same length
if ((comp.sortByNames.Length != this.sortByNames.Length) || (comp.sortAscending.Length != this.sortAscending.Length))
{
return false;
}
// Test to see if the attribute names and sorting orders are the same.
for (int i = 0; i < this.sortByNames.Length; i++)
{
if (comp.sortAscending[i] != this.sortAscending[i])
return false;
if (!comp.sortByNames[i].ToUpper().Equals(this.sortByNames[i].ToUpper()))
return false;
}
return true;
}
}
}