package com.hwlcn.ldap.ldap.sdk.controls; import com.hwlcn.ldap.asn1.ASN1Element; import com.hwlcn.ldap.asn1.ASN1OctetString; import com.hwlcn.ldap.asn1.ASN1Sequence; import com.hwlcn.ldap.ldap.sdk.Control; import com.hwlcn.ldap.ldap.sdk.LDAPException; import com.hwlcn.ldap.ldap.sdk.ResultCode; import com.hwlcn.core.annotation.NotMutable; import com.hwlcn.core.annotation.ThreadSafety; import com.hwlcn.ldap.util.ThreadSafetyLevel; import static com.hwlcn.ldap.ldap.sdk.controls.ControlMessages.*; import static com.hwlcn.ldap.util.Debug.*; import static com.hwlcn.ldap.util.Validator.*; /** * This class provides an implementation of the server-side sort request * control, as defined in * <A HREF="http://www.ietf.org/rfc/rfc2891.txt">RFC 2891</A>. It may be * included in a search request to indicate that the server should sort the * results before returning them to the client. * <BR><BR> * The order in which the entries are to be sorted is specified by one or more * {@link com.hwlcn.ldap.ldap.sdk.controls.SortKey} values. Each sort key includes an attribute name and a flag * that indicates whether to sort in ascending or descending order. It may also * specify a custom matching rule that should be used to specify which logic * should be used to perform the sorting. * <BR><BR> * If the search is successful, then the search result done message may include * the {@link ServerSideSortResponseControl} to provide information about the * status of the sort processing. * <BR><BR> * <H2>Example</H2> * The following example demonstrates the use of the server-side sort controls * to retrieve all users in the Sales department, sorted by last name and then * by first name: * <PRE> * SearchRequest searchRequest = * new SearchRequest("dc=example,dc=com", SearchScope.SUB, "(ou=Sales)"); * searchRequest.addControl(new ServerSideSortRequestControl( * new SortKey("sn"), new SortKey("givenName"))); * SearchResult searchResult = connection.search(searchRequest); * </PRE> * <BR><BR> * <H2>Client-Side Sorting</H2> * The UnboundID LDAP SDK for Java provides support for client-side sorting as * an alternative to server-side sorting. Client-side sorting may be useful in * cases in which the target server does not support the use of the server-side * sort control, or when it is desirable to perform the sort processing on the * client systems rather than on the directory server systems. See the * {@link com.hwlcn.ldap.ldap.sdk.EntrySorter} class for details on performing * client-side sorting in the LDAP SDK. */ @NotMutable() @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) public final class ServerSideSortRequestControl extends Control { public static final String SERVER_SIDE_SORT_REQUEST_OID = "1.2.840.113556.1.4.473"; private static final long serialVersionUID = -3021901578330574772L; private final SortKey[] sortKeys; public ServerSideSortRequestControl(final SortKey... sortKeys) { super(SERVER_SIDE_SORT_REQUEST_OID, false, encodeValue(sortKeys)); this.sortKeys = sortKeys; } public ServerSideSortRequestControl(final boolean isCritical, final SortKey... sortKeys) { super(SERVER_SIDE_SORT_REQUEST_OID, isCritical, encodeValue(sortKeys)); this.sortKeys = sortKeys; } public ServerSideSortRequestControl(final Control control) throws LDAPException { super(control); final ASN1OctetString value = control.getValue(); if (value == null) { throw new LDAPException(ResultCode.DECODING_ERROR, ERR_SORT_REQUEST_NO_VALUE.get()); } try { final ASN1Element valueElement = ASN1Element.decode(value.getValue()); final ASN1Element[] elements = ASN1Sequence.decodeAsSequence(valueElement).elements(); sortKeys = new SortKey[elements.length]; for (int i=0; i < elements.length; i++) { sortKeys[i] = SortKey.decode(elements[i]); } } catch (Exception e) { debugException(e); throw new LDAPException(ResultCode.DECODING_ERROR, ERR_SORT_REQUEST_CANNOT_DECODE.get(e), e); } } private static ASN1OctetString encodeValue(final SortKey[] sortKeys) { ensureNotNull(sortKeys); ensureTrue(sortKeys.length > 0, "ServerSideSortRequestControl.sortKeys must not be empty."); final ASN1Element[] valueElements = new ASN1Element[sortKeys.length]; for (int i=0; i < sortKeys.length; i++) { valueElements[i] = sortKeys[i].encode(); } return new ASN1OctetString(new ASN1Sequence(valueElements).encode()); } public SortKey[] getSortKeys() { return sortKeys; } @Override() public String getControlName() { return INFO_CONTROL_NAME_SORT_REQUEST.get(); } @Override() public void toString(final StringBuilder buffer) { buffer.append("ServerSideSortRequestControl(sortKeys={"); for (int i=0; i < sortKeys.length; i++) { if (i > 0) { buffer.append(", "); } buffer.append('\''); sortKeys[i].toString(buffer); buffer.append('\''); } buffer.append("})"); } }