/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Copyright 2008 Sun Microsystems, Inc. */ package org.opends.server.types; import org.opends.server.api.OrderingMatchingRule; import static org.opends.server.loggers.debug.DebugLogger.*; import org.opends.server.loggers.debug.DebugTracer; /** * This class defines a data structure that may be used as a sort key. * It includes an attribute type and a boolean value that indicates * whether the sort should be ascending or descending. It may also * contain a specific ordering matching rule that should be used for * the sorting process, although if none is provided it will use the * default ordering matching rule for the attribute type. */ @org.opends.server.types.PublicAPI( stability=org.opends.server.types.StabilityLevel.VOLATILE, mayInstantiate=true, mayExtend=false, mayInvoke=true) public final class SortKey { /** * The tracer object for the debug logger. */ private static final DebugTracer TRACER = getTracer(); // The attribute type for this sort key. private AttributeType attributeType; // The indication of whether the sort should be ascending. private boolean ascending; // The ordering matching rule to use with this sort key. private OrderingMatchingRule orderingRule; /** * Creates a new sort key with the provided information. * * @param attributeType The attribute type for this sort key. * @param ascending Indicates whether the sort should be in * ascending order rather than descending. */ public SortKey(AttributeType attributeType, boolean ascending) { this.attributeType = attributeType; this.ascending = ascending; orderingRule = null; } /** * Creates a new sort key with the provided information. * * @param attributeType The attribute type for this sort key. * @param ascending Indicates whether the sort should be in * ascending order rather than descending. * @param orderingRule The ordering matching rule to use with * this sort key. */ public SortKey(AttributeType attributeType, boolean ascending, OrderingMatchingRule orderingRule) { this.attributeType = attributeType; this.ascending = ascending; this.orderingRule = orderingRule; } /** * Retrieves the attribute type for this sort key. * * @return The attribute type for this sort key. */ public AttributeType getAttributeType() { return attributeType; } /** * Indicates whether the specified attribute should be sorted in * ascending order. * * @return {@code true} if the attribute should be sorted in * ascending order, or {@code false} if it should be sorted * in descending order. */ public boolean ascending() { return ascending; } /** * Retrieves the ordering matching rule to use with this sort key. * * @return The ordering matching rule to use with this sort key. */ public OrderingMatchingRule getOrderingRule() { return orderingRule; } /** * Compares the provided values using this sort key. * * @param value1 The first value to be compared. * @param value2 The second value to be compared. * * @return A negative value if the first value should come before * the second in a sorted list, a positive value if the * first value should come after the second in a sorted * list, or zero if there is no relative difference between * the values. */ public int compareValues(AttributeValue value1, AttributeValue value2) { // A null value will always come after a non-null value. if (value1 == null) { if (value2 == null) { return 0; } else { return 1; } } else if (value2 == null) { return -1; } // Use the ordering matching rule if one is provided. Otherwise, // fall back on the default ordering rule for the attribute type. if (orderingRule == null) { try { OrderingMatchingRule rule = attributeType.getOrderingMatchingRule(); if (rule == null) { return 0; } if (ascending) { return rule.compareValues(value1.getNormalizedValue(), value2.getNormalizedValue()); } else { return rule.compareValues(value2.getNormalizedValue(), value1.getNormalizedValue()); } } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } return 0; } } else { try { if (ascending) { return orderingRule.compareValues( orderingRule.normalizeValue(value1.getValue()), orderingRule.normalizeValue(value2.getValue())); } else { return orderingRule.compareValues( orderingRule.normalizeValue(value2.getValue()), orderingRule.normalizeValue(value1.getValue())); } } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } return 0; } } } /** * Retrieves a string representation of this sort key. * * @return A string representation of this sort key. */ public String toString() { StringBuilder buffer = new StringBuilder(); toString(buffer); return buffer.toString(); } /** * Appends a string representation of this sort key to the * provided buffer. * * @param buffer The buffer to which the information should be * appended. */ public void toString(StringBuilder buffer) { buffer.append("SortKey("); if (ascending) { buffer.append("+"); } else { buffer.append("-"); } buffer.append(attributeType.getNameOrOID()); if (orderingRule != null) { buffer.append(":"); buffer.append(orderingRule.getNameOrOID()); } buffer.append(")"); } /** * Retrieves the hash code for this sort key. * * @return The hash code for this sort key. */ public int hashCode() { int hashCode = 0; if(ascending) { hashCode += 1; } hashCode += attributeType.hashCode(); if(orderingRule != null) { hashCode += orderingRule.hashCode(); } return hashCode; } /** * Indicates whether this sort key is equal to the provided * object. * * @param o The object for which to make the determination. * * @return <CODE>true</CODE> if the provide object is equal to this * sort key, or <CODE>false</CODE> if it is not. */ public boolean equals(Object o) { if(o == null) { return false; } if (o == this) { return true; } if (! (o instanceof SortKey)) { return false; } SortKey s = (SortKey) o; if(ascending != s.ascending) { return false; } if(!attributeType.equals(s.attributeType)) { return false; } if(orderingRule != null) { if(s.orderingRule != null) { if(!orderingRule.equals(s.orderingRule)) { return false; } } else if(!orderingRule.equals( s.attributeType.getOrderingMatchingRule())) { return false; } } else if(s.orderingRule != null) { if(!attributeType.getOrderingMatchingRule().equals( s.orderingRule)) { return false; } } return true; } }