/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * The contents of this file are subject to the Netscape 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/NPL/ * * 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.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1999 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ package netscape.ldap; import java.util.*; import java.text.*; /** * Compares LDAP entries based on one or more attribute values. *

* * To use this comparison for sorting search results, pass * an object of this class to the sort method in * LDAPSearchResults. *

* * @version 1.0 * @see LDAPEntryComparator * @see LDAPSearchResults#sort */ public class LDAPCompareAttrNames implements LDAPEntryComparator, java.io.Serializable { static final long serialVersionUID = -2567450425231175944L; private String m_attrs[]; private boolean m_ascending[]; private Locale m_locale = null; private Collator m_collator = null; private boolean m_sensitive = true; /** * Constructs a comparator that compares the string values of * a named attribute in LDAP entries and sorts the entries in * ascending order. *

* * @param attribute name of attribute for comparisons */ public LDAPCompareAttrNames (String attribute) { m_attrs = new String[1]; m_attrs[0] = attribute; m_ascending = new boolean[1]; m_ascending[0] = true; } /** * Constructs a comparator that compares the string values of * a named attribute in LDAP entries and that allows you to sort * entries either in ascending or descending order. *

* * @param attribute name of attribute for comparisons * @param ascendingFlag if true, sort in ascending order */ public LDAPCompareAttrNames (String attribute, boolean ascendingFlag) { m_attrs = new String[1]; m_attrs[0] = attribute; m_ascending = new boolean[1]; m_ascending[0] = ascendingFlag; } /** * Constructs a comparator that compares the string values of * a set of named attributes in LDAP entries and that sort * the entries in ascending order. *

* * Use an array of strings to specify the set of attributes * to use for sorting. If the values of the first attribute * (the name specified in attribute[0]) are equal, * then the values of the next attribute are compared. *

* * For example, if attributes[0] = "cn" and * attributes[1]="uid", results are first sorted * by the cn attribute. If two entries have the * same value for cn, then the uid * attribute is used to sort the entries. *

* * @param attributes array of the attribute names used for comparisons */ public LDAPCompareAttrNames (String[] attributes) { m_attrs = attributes; m_ascending = new boolean[attributes.length]; for( int i = 0; i < attributes.length; i++ ) m_ascending[i] = true; } /** * Constructs a comparator that compares the string values of * a set of named attributes in LDAP entries and allows you * to sort the entries in ascending or descending order. *

* * Use an array of strings to specify the set of attributes * to use for sorting. If the values of the first attribute * (the name specified in attribute[0]) * are equal, then the values of the next attribute are compared. *

* * For example, if attributes[0] = "cn" and * attributes[1]="uid", results are first sorted * by the cn attribute. If two entries have the * same value for cn, then the uid * attribute is used to sort the entries. *

* * Use an array of boolean values to specify whether each attribute * should be sorted in ascending or descending order. For example, * suppose that attributes[0] = "cn" and * attributes[1]="roomNumber". If * ascendingFlags[0]=true and * ascendingFlags[1]=false, attributes are sorted first by * cn in ascending order, then by roomNumber * in descending order. *

* * If the size of the array of attribute names is not the same as * the size of the array of boolean values, an * LDAPException is thrown. *

* * @param attribute array of the attribute names to use for comparisons * @param ascendingFlags array of boolean values specifying ascending * or descending order to use for each attribute name. If * true, the attributes are sorted in ascending order. */ public LDAPCompareAttrNames (String[] attributes, boolean[] ascendingFlags) { m_attrs = attributes; m_ascending = ascendingFlags; if ( m_ascending == null ) { m_ascending = new boolean[attributes.length]; for( int i = 0; i < attributes.length; i++ ) m_ascending[i] = true; } } /** * Gets the locale, if any, used for collation. If the locale is null, * an ordinary string comparison is used for sorting. * * @return the locale used for collation, or null. */ public Locale getLocale() { return m_locale; } /** * Set the locale, if any, used for collation. If the locale is null, * an ordinary string comparison is used for sorting. If sorting * has been set to case-insensitive, the collation strength is set * to Collator.PRIMARY, otherwise to Collator.IDENTICAL. If a * different collation strength setting is required, use the signature * that takes a collation strength parameter. * * @param locale the locale used for collation, or null. */ public void setLocale( Locale locale ) { if ( m_sensitive ) { setLocale( locale, Collator.IDENTICAL ); } else { setLocale( locale, Collator.PRIMARY ); } } /** * Sets the locale, if any, used for collation. If the locale is null, * an ordinary string comparison is used for sorting. * * @param locale the locale used for collation, or null. * @param strength collation strength: Collator.PRIMARY, * Collator.SECONDARY, Collator.TERTIARY, or Collator.IDENTICAL */ public void setLocale( Locale locale, int strength ) { m_locale = locale; if ( m_locale == null ) { m_collator = null; } else { m_collator = Collator.getInstance( m_locale ); m_collator.setStrength(strength); } } /** * Gets the state of the case-sensitivity flag. This only applies to * Unicode sort order; for locale-specific sorting, case-sensitivity * is controlled by the collation strength. * * @return true for case-sensitive sorting; this is * the default */ public boolean getCaseSensitive() { return m_sensitive; } /** * Sets the state of the case-sensitivity flag. This only applies to * Unicode sort order; for locale-specific sorting, case-sensitivity * is controlled by the collation strength. * * @param sensitive true for case-sensitive sorting; * this is the default */ public void setCaseSensitive( boolean sensitive ) { m_sensitive = sensitive; } /** * Returns true if the value of the attribute in the first entry is greater * than the value of the attribute in the second entry. *

* * If one of the entries is missing the attribute, the other is * considered greater. By default, the first entry is greater. *

* * If either entry contains multiple values, only the first value * is used for comparisons. *

* * @param greater entry against which to test * @param less entry to test * @return true if (greater > less). */ public boolean isGreater (LDAPEntry greater, LDAPEntry less) { if (greater.equals (less)) return false; return attrGreater (greater, less, 0); } /** * Compares a particular attribute in both entries. If equal, * moves on to the next. * @param greater greater arg from isGreater * @param less less arg from isGreater * @param attrPos the index in an array of attributes, indicating * the attribute to compare * @return (greater > less) */ boolean attrGreater (LDAPEntry greater, LDAPEntry less, int attrPos) { Enumeration greaterAttrSet = greater.getAttributeSet().getAttributes(); Enumeration lessAttrSet = less.getAttributeSet().getAttributes(); String greaterValue = null; String lessValue = null; String attrName = m_attrs[attrPos]; boolean ascending = m_ascending[attrPos]; try { while (lessAttrSet.hasMoreElements()) { LDAPAttribute currAttr = (LDAPAttribute)(lessAttrSet.nextElement()); if (!attrName.equalsIgnoreCase (currAttr.getName())) continue; lessValue = (String)(currAttr.getStringValues().nextElement()); break; } while (greaterAttrSet.hasMoreElements()) { LDAPAttribute currAttr = (LDAPAttribute)(greaterAttrSet.nextElement()); if (!attrName.equalsIgnoreCase (currAttr.getName())) continue; greaterValue = (String)(currAttr.getStringValues().nextElement()); break; } } catch (ClassCastException cce) { // i.e. one of the enumerations did not contain the // right type !? return false; } catch (NoSuchElementException nse) { // i.e. one of the attributes had no values !? return false; } if ((lessValue == null) ^ (greaterValue == null)) return greaterValue != null; // Check for equality if ( (lessValue == null) || ((m_collator != null) && (m_collator.compare( greaterValue, lessValue ) == 0) ) || ((m_collator == null) && m_sensitive && lessValue.equals(greaterValue)) || ((m_collator == null) && !m_sensitive && lessValue.equalsIgnoreCase(greaterValue)) ) { if (attrPos == m_attrs.length - 1) { return false; } else { return attrGreater (greater, less, attrPos+1); } } // Not equal, check for order if ( ascending ) { if ( m_collator != null ) { return ( m_collator.compare( greaterValue, lessValue ) > 0 ); } else if ( m_sensitive ) { return (greaterValue.compareTo (lessValue) > 0); } else { return (greaterValue.toLowerCase().compareTo ( lessValue.toLowerCase()) > 0); } } else { if ( m_collator != null ) { return ( m_collator.compare( greaterValue, lessValue ) < 0 ); } else if ( m_sensitive ) { return (greaterValue.compareTo (lessValue) < 0); } else { return (greaterValue.toLowerCase().compareTo ( lessValue.toLowerCase()) < 0); } } } }