001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.ldap.model.schema.comparators; 021 022 023import org.apache.directory.api.i18n.I18n; 024import org.apache.directory.api.ldap.model.constants.SchemaConstants; 025import org.apache.directory.api.ldap.model.exception.LdapException; 026import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; 027import org.apache.directory.api.ldap.model.name.Dn; 028import org.apache.directory.api.ldap.model.schema.LdapComparator; 029import org.apache.directory.api.ldap.model.schema.SchemaManager; 030 031 032/** 033 * A comparator that sorts OIDs based on their numeric id value. Needs a 034 * OidRegistry to properly do it's job. Public method to set the oid 035 * registry will be used by the server after instantiation in deserialization. 036 * 037 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 038 */ 039public class UniqueMemberComparator extends LdapComparator<String> 040{ 041 /** The serial version UID */ 042 private static final long serialVersionUID = 2L; 043 044 /** A reference to the schema manager */ 045 private transient SchemaManager schemaManager; 046 047 private transient ParsedDnComparator dnComparator = new ParsedDnComparator( SchemaConstants.ENTRY_DN_AT_OID ); 048 049 050 /** 051 * The IntegerComparator constructor. Its OID is the IntegerOrderingMatch matching 052 * rule OID. 053 * 054 * @param oid The Comparator's OID 055 */ 056 public UniqueMemberComparator( String oid ) 057 { 058 super( oid ); 059 } 060 061 062 /** 063 * {@inheritDoc} 064 */ 065 public int compare( String dnstr1, String dnstr2 ) 066 { 067 int dash1 = dnstr1.lastIndexOf( '#' ); 068 int dash2 = dnstr2.lastIndexOf( '#' ); 069 070 if ( ( dash1 == -1 ) && ( dash2 == -1 ) ) 071 { 072 // no UID part 073 try 074 { 075 Dn dn1 = getDn( dnstr1 ); 076 Dn dn2 = getDn( dnstr2 ); 077 078 return dnComparator.compare( dn1, dn2 ); 079 } 080 catch ( LdapInvalidDnException ne ) 081 { 082 return -1; 083 } 084 } 085 else 086 { 087 // Now, check that we don't have another '#' 088 if ( dnstr1.indexOf( '#' ) != dash1 ) 089 { 090 // Yes, we have one : this is not allowed, it should have been 091 // escaped. 092 return -1; 093 } 094 095 if ( dnstr2.indexOf( '#' ) != dash1 ) 096 { 097 // Yes, we have one : this is not allowed, it should have been 098 // escaped. 099 return 1; 100 } 101 102 Dn dn1; 103 Dn dn2; 104 105 // This is an UID if the '#' is immediatly 106 // followed by a BitString, except if the '#' is 107 // on the last position 108 String uid1 = dnstr1.substring( dash1 + 1 ); 109 110 if ( dash1 > 0 ) 111 { 112 try 113 { 114 dn1 = new Dn( dnstr1.substring( 0, dash1 ) ); 115 } 116 catch ( LdapException ne ) 117 { 118 return -1; 119 } 120 } 121 else 122 { 123 return -1; 124 } 125 126 // This is an UID if the '#' is immediately 127 // followed by a BitString, except if the '#' is 128 // on the last position 129 String uid2 = dnstr2.substring( dash2 + 1 ); 130 131 if ( dash2 > 0 ) 132 { 133 try 134 { 135 dn2 = new Dn( dnstr1.substring( 0, dash2 ) ); 136 } 137 catch ( LdapException ne ) 138 { 139 return 1; 140 } 141 } 142 else 143 { 144 return 1; 145 } 146 147 int dnResult = dnComparator.compare( dn1, dn2 ); 148 149 if ( dnResult == 0 ) 150 { 151 return uid1.compareTo( uid2 ); 152 } 153 154 return dnResult; 155 } 156 } 157 158 159 /** 160 * {@inheritDoc} 161 */ 162 @Override 163 public void setSchemaManager( SchemaManager schemaManager ) 164 { 165 this.schemaManager = schemaManager; 166 } 167 168 169 /** 170 * Get the DN from the given object 171 * 172 * @param obj The object containing a DN (either as an instance of Dn or as a String) 173 * @return A Dn instance 174 * @throws LdapInvalidDnException If the Dn is invalid 175 */ 176 public Dn getDn( Object obj ) throws LdapInvalidDnException 177 { 178 Dn dn; 179 180 if ( obj instanceof Dn ) 181 { 182 dn = ( Dn ) obj; 183 184 dn = dn.isSchemaAware() ? dn : new Dn( schemaManager, dn ); 185 } 186 else if ( obj instanceof String ) 187 { 188 dn = new Dn( schemaManager, ( String ) obj ); 189 } 190 else 191 { 192 throw new IllegalStateException( I18n.err( I18n.ERR_13720_CANNOT_HANDLE_DN_COMPARISONS, obj == null ? null : obj.getClass() ) ); 193 } 194 195 return dn; 196 } 197}