**** Merged from MCS ****
[mono-project.git] / mcs / class / Novell.Directory.Ldap / Novell.Directory.Ldap / LdapCompareAttrNames.cs
blob0863542a214c5539175fdc51fa0942cbd53acd3d
1 /******************************************************************************
2 * The MIT License
3 * Copyright (c) 2003 Novell Inc. www.novell.com
4 *
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
21 * SOFTWARE.
22 *******************************************************************************/
24 // Novell.Directory.Ldap.LdapCompareAttrNames.cs
26 // Author:
27 // Sunil Kumar (Sunilk@novell.com)
29 // (C) 2003 Novell, Inc (http://www.novell.com)
32 using System;
33 using Novell.Directory.Ldap.Utilclass;
35 namespace Novell.Directory.Ldap
39 /// <summary> Compares Ldap entries based on attribute name.
40 ///
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.
47 ///
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
50 /// would sort them.
51 ///
52 /// </summary>
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
62 /// specified.
63 ///
64 /// If locale is null, a basic String.compareTo method is used for
65 /// collation. If non-null, a locale-specific collation is used.
66 ///
67 /// </summary>
68 /// <returns> The locale if one has been specified
69 /// </returns>
70 /// <summary> Sets the locale to be used for sorting.
71 ///
72 /// </summary>
73 /// <param name="locale"> The locale to be used for sorting.
74 /// </param>
75 virtual public System.Globalization.CultureInfo Locale
77 get
79 //currently supports only English local.
80 return location;
83 set
85 collator = value.CompareInfo;
86 location = value;
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
96 /// ascending order.
97 ///
98 /// </summary>
99 /// <param name="attrName"> Name of an attribute by which to sort.
100 ///
101 /// </param>
102 public LdapCompareAttrNames(System.String attrName)
104 InitBlock();
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.
113 ///
114 /// </summary>
115 /// <param name="attrName"> Name of an attribute to sort by.
116 ///
117 /// </param>
118 /// <param name="ascendingFlag"> True specifies ascending order; false specifies
119 /// descending order.
120 /// </param>
121 public LdapCompareAttrNames(System.String attrName, bool ascendingFlag)
123 InitBlock();
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.
133 ///
134 /// Note: Novell eDirectory allows sorting by one attribute only. The
135 /// direcctory server must also be configured to index the specified
136 /// attribute.
137 ///
138 /// </summary>
139 /// <param name="attrNames"> Array of names of attributes to sort by.
140 ///
141 /// </param>
142 public LdapCompareAttrNames(System.String[] attrNames)
144 InitBlock();
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
156 /// attribute.
157 ///
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.
161 ///
162 /// </summary>
163 /// <param name="attrNames"> Array of names of attributes to sort by.
164 ///
165 /// </param>
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.
171 ///
172 /// </param>
173 /// <exception> LdapException A general exception which includes an error
174 /// message and an Ldap error code.
175 ///
176 /// </exception>
177 public LdapCompareAttrNames(System.String[] attrNames, bool[] ascendingFlags)
179 InitBlock();
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
197 /// value only.
198 ///
199 /// </summary>
200 /// <param name="object1"> Target entry for comparison.
201 ///
202 /// </param>
203 /// <param name="object2"> Entry to be compared to.
204 ///
205 /// </param>
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.
209 /// </returns>
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
217 int compare, i = 0;
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
237 else
239 if (one != null)
240 compare = - 1;
241 //one is greater than two
242 else if (two != null)
243 compare = 1;
244 //one is lesser than two
245 else
246 compare = 0; //tie - break it with the next attribute name
249 i++;
251 while ((compare == 0) && (i < sortByNames.Length));
253 if (sortAscending[i - 1])
255 // return the normal ascending comparison.
256 return compare;
258 else
260 // negate the comparison for a descending comparison.
261 return - compare;
265 /// <summary> Determines if this comparator is equal to the comparator passed in.
266 ///
267 /// This will return true if the comparator is an instance of
268 /// LdapCompareAttrNames and compares the same attributes names in the same
269 /// order.
270 ///
271 /// </summary>
272 /// <returns> true the comparators are equal
273 /// </returns>
274 public override bool Equals(System.Object comparator)
276 if (!(comparator is LdapCompareAttrNames))
278 return false;
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))
285 return false;
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])
292 return false;
293 if (!comp.sortByNames[i].ToUpper().Equals(this.sortByNames[i].ToUpper()))
294 return false;
296 return true;