1 /******************************************************************************
3 * Copyright (c) 2003 Novell Inc. www.novell.com
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the Software), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 *******************************************************************************/
24 // Novell.Directory.Ldap.LdapCompareAttrNames.cs
27 // Sunil Kumar (Sunilk@novell.com)
29 // (C) 2003 Novell, Inc (http://www.novell.com)
33 using Novell.Directory.Ldap.Utilclass;
35 namespace Novell.Directory.Ldap
39 /// <summary> Compares Ldap entries based on attribute name.
41 /// An object of this class defines ordering when sorting LdapEntries,
42 /// usually from search results. When using this Comparator, LdapEntry objects
43 /// are sorted by the attribute names(s) passed in on the
44 /// constructor, in ascending or descending order. The object is typically
45 /// supplied to an implementation of the collection interfaces such as
46 /// java.util.TreeSet which performs sorting.
48 /// Comparison is performed via locale-sensitive Java String comparison,
49 /// which may not correspond to the Ldap ordering rules by which an Ldap server
53 public class LdapCompareAttrNames : System.Collections.IComparer
55 private void InitBlock()
57 // location = Locale.getDefault();
58 location=System.Globalization.CultureInfo.CurrentCulture;
59 collator = System.Globalization.CultureInfo.CurrentCulture.CompareInfo;
61 /// <summary> Returns the locale to be used for sorting, if a locale has been
64 /// If locale is null, a basic String.compareTo method is used for
65 /// collation. If non-null, a locale-specific collation is used.
68 /// <returns> The locale if one has been specified
70 /// <summary> Sets the locale to be used for sorting.
73 /// <param name="locale"> The locale to be used for sorting.
75 virtual public System.Globalization.CultureInfo Locale
79 //currently supports only English local.
85 collator = value.CompareInfo;
90 private System.String[] sortByNames; //names to to sort by.
91 private bool[] sortAscending; //true if sorting ascending
92 private System.Globalization.CultureInfo location;
93 private System.Globalization.CompareInfo collator;
95 /// <summary> Constructs an object that sorts results by a single attribute, in
99 /// <param name="attrName"> Name of an attribute by which to sort.
102 public LdapCompareAttrNames(System.String attrName)
105 sortByNames = new System.String[1];
106 sortByNames[0] = attrName;
107 sortAscending = new bool[1];
108 sortAscending[0] = true;
111 /// <summary> Constructs an object that sorts results by a single attribute, in
112 /// either ascending or descending order.
115 /// <param name="attrName"> Name of an attribute to sort by.
118 /// <param name="ascendingFlag"> True specifies ascending order; false specifies
119 /// descending order.
121 public LdapCompareAttrNames(System.String attrName, bool ascendingFlag)
124 sortByNames = new System.String[1];
125 sortByNames[0] = attrName;
126 sortAscending = new bool[1];
127 sortAscending[0] = ascendingFlag;
131 /// <summary> Constructs an object that sorts by one or more attributes, in the
132 /// order provided, in ascending order.
134 /// Note: Novell eDirectory allows sorting by one attribute only. The
135 /// direcctory server must also be configured to index the specified
139 /// <param name="attrNames"> Array of names of attributes to sort by.
142 public LdapCompareAttrNames(System.String[] attrNames)
145 sortByNames = new System.String[attrNames.Length];
146 sortAscending = new bool[attrNames.Length];
147 for (int i = 0; i < attrNames.Length; i++)
149 sortByNames[i] = attrNames[i];
150 sortAscending[i] = true;
154 /// <summary> Constructs an object that sorts by one or more attributes, in the
155 /// order provided, in either ascending or descending order for each
158 /// Note: Novell eDirectory supports only ascending sort order (A,B,C ...)
159 /// and allows sorting only by one attribute. The directory server must be
160 /// configured to index this attribute.
163 /// <param name="attrNames"> Array of names of attributes to sort by.
166 /// <param name="ascendingFlags"> Array of flags, one for each attrName, where
167 /// true specifies ascending order and false specifies
168 /// descending order. An LdapException is thrown if
169 /// the length of ascendingFlags is not greater than
170 /// or equal to the length of attrNames.
173 /// <exception> LdapException A general exception which includes an error
174 /// message and an Ldap error code.
177 public LdapCompareAttrNames(System.String[] attrNames, bool[] ascendingFlags)
180 if (attrNames.Length != ascendingFlags.Length)
182 throw new LdapException(ExceptionMessages.UNEQUAL_LENGTHS, LdapException.INAPPROPRIATE_MATCHING, (System.String) null);
183 //"Length of attribute Name array does not equal length of Flags array"
185 sortByNames = new System.String[attrNames.Length];
186 sortAscending = new bool[ascendingFlags.Length];
187 for (int i = 0; i < attrNames.Length; i++)
189 sortByNames[i] = attrNames[i];
190 sortAscending[i] = ascendingFlags[i];
194 /// <summary> Compares the the attributes of the first LdapEntry to the second.
195 /// Only the values of the attributes named at the construction of this
196 /// object will be compared. Multi-valued attributes compare on the first
200 /// <param name="object1"> Target entry for comparison.
203 /// <param name="object2"> Entry to be compared to.
206 /// <returns> Negative value if the first entry is less than the second and
207 /// positive if the first is greater than the second. Zero is returned if all
208 /// attributes to be compared are the same.
210 public virtual int Compare(System.Object object1, System.Object object2)
212 LdapEntry entry1 = (LdapEntry) object1;
213 LdapEntry entry2 = (LdapEntry) object2;
214 LdapAttribute one, two;
215 System.String[] first; //multivalued attributes are ignored.
216 System.String[] second; //we just use the first element
218 if (collator == null)
220 //using default locale
221 collator = System.Globalization.CultureInfo.CurrentCulture.CompareInfo;
226 //while first and second are equal
227 one = entry1.getAttribute(sortByNames[i]);
228 two = entry2.getAttribute(sortByNames[i]);
229 if ((one != null) && (two != null))
231 first = one.StringValueArray;
232 second = two.StringValueArray;
233 compare = collator.Compare(first[0], second[0]);
235 //We could also use the other multivalued attributes to break ties.
236 //one of the entries was null
241 //one is greater than two
242 else if (two != null)
244 //one is lesser than two
246 compare = 0; //tie - break it with the next attribute name
251 while ((compare == 0) && (i < sortByNames.Length));
253 if (sortAscending[i - 1])
255 // return the normal ascending comparison.
260 // negate the comparison for a descending comparison.
265 /// <summary> Determines if this comparator is equal to the comparator passed in.
267 /// This will return true if the comparator is an instance of
268 /// LdapCompareAttrNames and compares the same attributes names in the same
272 /// <returns> true the comparators are equal
274 public override bool Equals(System.Object comparator)
276 if (!(comparator is LdapCompareAttrNames))
280 LdapCompareAttrNames comp = (LdapCompareAttrNames) comparator;
282 // Test to see if the attribute to compare are the same length
283 if ((comp.sortByNames.Length != this.sortByNames.Length) || (comp.sortAscending.Length != this.sortAscending.Length))
288 // Test to see if the attribute names and sorting orders are the same.
289 for (int i = 0; i < this.sortByNames.Length; i++)
291 if (comp.sortAscending[i] != this.sortAscending[i])
293 if (!comp.sortByNames[i].ToUpper().Equals(this.sortByNames[i].ToUpper()))