| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| package org.apache.directory.server.core.shared; |
| |
| |
| import java.io.Serializable; |
| import java.util.Comparator; |
| import java.util.TreeSet; |
| |
| import org.apache.directory.api.ldap.model.constants.SchemaConstants; |
| import org.apache.directory.api.ldap.model.entry.Attribute; |
| import org.apache.directory.api.ldap.model.entry.Entry; |
| import org.apache.directory.api.ldap.model.entry.Value; |
| import org.apache.directory.api.ldap.model.exception.LdapException; |
| import org.apache.directory.api.ldap.model.schema.AttributeType; |
| import org.apache.directory.api.ldap.model.schema.LdapComparator; |
| import org.apache.directory.api.ldap.model.schema.MatchingRule; |
| import org.apache.directory.api.ldap.model.schema.SchemaManager; |
| import org.apache.directory.api.ldap.model.schema.comparators.ParsedDnComparator; |
| |
| /** |
| * A comparator to sort the entries as per <a href="http://tools.ietf.org/html/rfc2891">RFC 2891</a> |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| */ |
| class SortedEntryComparator implements Comparator<Entry>, Serializable |
| { |
| |
| /** the attribute's type */ |
| private transient AttributeType type; |
| |
| /** comparator used for comparing the values of the given attribute type */ |
| private transient LdapComparator comparator; |
| |
| /** flag to indicate if the attribute type is multivalued */ |
| private boolean multivalued; |
| |
| /** flag for indicating the order of sorting */ |
| private boolean reverse; |
| |
| /** flag to indicate if the attribute is human readable or binary */ |
| private boolean hr; |
| |
| |
| /** |
| * |
| * Creates a new instance of SortedEntryComparator. |
| * |
| * @param at the attribute's type |
| * @param mrOid the OID or name of the matchingrule |
| * @param reverse flag to indicate the sort order |
| */ |
| SortedEntryComparator( AttributeType at, String mrule, boolean reverse, SchemaManager schemaManager ) throws LdapException |
| { |
| this.type = at; |
| this.reverse = reverse; |
| |
| if ( !at.isSingleValued() ) |
| { |
| multivalued = true; |
| } |
| |
| // Special case : entryDn |
| if ( SchemaConstants.ENTRY_DN_AT_OID.equals( at.getOid() ) ) |
| { |
| // We will use the Entry's DN comparator. |
| comparator = new ParsedDnComparator( SchemaConstants.ENTRY_DN_AT_OID ); |
| comparator.setSchemaManager( schemaManager ); |
| hr = true; |
| } |
| else |
| { |
| hr = at.getSyntax().isHumanReadable(); |
| |
| if ( mrule != null ) |
| { |
| comparator = schemaManager.lookupComparatorRegistry( mrule ); |
| } |
| else |
| { |
| MatchingRule mr = at.getOrdering(); |
| |
| if ( mr == null ) |
| { |
| mr = at.getEquality(); |
| } |
| |
| comparator = schemaManager.lookupComparatorRegistry( mr.getOid() ); |
| } |
| |
| comparator.setSchemaManager( schemaManager ); |
| } |
| } |
| |
| |
| @Override |
| public int compare( Entry entry1, Entry entry2 ) |
| { |
| Attribute at1 = entry1.get( type ); |
| |
| Attribute at2 = entry2.get( type ); |
| |
| // as per section 2.2 of the spec null values are considered larger |
| if ( at1 == null ) |
| { |
| return reverse ? -1 : 1; |
| } |
| else if ( at2 == null ) |
| { |
| return reverse ? 1 : -1; |
| } |
| |
| Object o1; |
| Object o2; |
| |
| if ( multivalued ) |
| { |
| TreeSet ts = new TreeSet( comparator ); |
| |
| o1 = sortAndGetFirst( at1, ts ); |
| |
| ts.clear(); |
| o2 = sortAndGetFirst( at2, ts ); |
| } |
| else |
| { |
| Value v1 = at1.get(); |
| Value v2 = at2.get(); |
| |
| if ( hr ) |
| { |
| o1 = v1.getString(); |
| o2 = v2.getString(); |
| } |
| else |
| { |
| o1 = v1.getBytes(); |
| o2 = v2.getBytes(); |
| } |
| } |
| |
| int c; |
| |
| try |
| { |
| if ( reverse ) |
| { |
| c = comparator.compare( comparator.getNormalizer().normalize( ( String ) o2 ), o1 ); |
| } |
| else |
| { |
| c = comparator.compare( comparator.getNormalizer().normalize( ( String ) o1 ), o2 ); |
| } |
| |
| if ( c == 0 ) |
| { |
| return 1; |
| } |
| |
| return c; |
| } |
| catch ( LdapException le ) |
| { |
| return 0; |
| } |
| } |
| |
| |
| /** |
| * sorts the values of an attribute and picks the least value |
| * |
| * @param at the attribute |
| * @param ts the TreeSet for sorting |
| * @return the least value among the values of the attribute |
| */ |
| private Object sortAndGetFirst( Attribute at, TreeSet ts ) |
| { |
| for ( Value v : at ) |
| { |
| if ( hr ) |
| { |
| ts.add( v.getNormalized() ); |
| } |
| else |
| { |
| ts.add( v.getBytes() ); |
| } |
| } |
| |
| return ts.first(); |
| } |
| } |