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 * http://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 */
020 package org.apache.directory.server.schema;
021
022
023 import java.util.Comparator;
024
025 import javax.naming.Name;
026 import javax.naming.NamingException;
027
028 import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
029 import org.apache.directory.server.schema.registries.Registries;
030 import org.apache.directory.shared.ldap.name.LdapDN;
031
032
033 /**
034 * A comparator for the uniqueMember match
035 *
036 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
037 * @version $Rev$
038 */
039 public class NameAndOptionalUIDComparator implements Comparator
040 {
041 // @TODO you'll need this to fix the way normalization is done
042 private AttributeTypeRegistry attrRegistry;
043
044
045 public NameAndOptionalUIDComparator( AttributeTypeRegistry attrRegistry )
046 {
047 this.attrRegistry = attrRegistry;
048 }
049
050
051 public NameAndOptionalUIDComparator()
052 {
053 }
054
055
056 public void setRegistries( Registries registries )
057 {
058 attrRegistry = registries.getAttributeTypeRegistry();
059 }
060
061 /**
062 * Comparing two uniqueMember is a matter of following this algorithm:
063 * - if they are only DN, then the values should be equal
064 * - otherwise, both element should contain the same DN and
065 * * if they both have an UID, they should be equals.
066 */
067 public int compare( Object obj0, Object obj1 )
068 {
069 String dnstr0 = null;
070 String dnstr1 = null;
071
072 if ( ( obj0 instanceof String ) && ( obj1 instanceof String) )
073 {
074 dnstr0 = (String)obj0;
075 dnstr1 = (String)obj1;
076
077 int dash0 = dnstr0.lastIndexOf( '#' );
078 int dash1 = dnstr1.lastIndexOf( '#' );
079
080 if ( ( dash0 == -1 ) && ( dash1 == -1 ) )
081 {
082 // no UID part
083 try
084 {
085 return getDn( dnstr0 ).compareTo( getDn ( dnstr1 ) );
086 }
087 catch ( NamingException ne )
088 {
089 return -1;
090 }
091 }
092 else
093 {
094 // Now, check that we don't have another '#'
095 if ( dnstr0.indexOf( '#' ) != dash0 )
096 {
097 // Yes, we have one : this is not allowed, it should have been
098 // escaped.
099 return -1;
100 }
101
102 if ( dnstr1.indexOf( '#' ) != dash0 )
103 {
104 // Yes, we have one : this is not allowed, it should have been
105 // escaped.
106 return 1;
107 }
108
109 LdapDN dn0 = null;
110 LdapDN dn1 = null;
111
112 // This is an UID if the '#' is immediatly
113 // followed by a BitString, except if the '#' is
114 // on the last position
115 String uid0 = dnstr0.substring( dash0 + 1 );
116
117 if ( dash0 > 0 )
118 {
119 try
120 {
121 dn0 = new LdapDN( dnstr0.substring( 0, dash0 ) );
122 }
123 catch ( NamingException ne )
124 {
125 return -1;
126 }
127 }
128 else
129 {
130 return -1;
131 }
132
133 // This is an UID if the '#' is immediatly
134 // followed by a BitString, except if the '#' is
135 // on the last position
136 String uid1 = dnstr1.substring( dash1 + 1 );
137
138 if ( dash1 > 0 )
139 {
140 try
141 {
142 dn1 = new LdapDN( dnstr0.substring( 0, dash1 ) );
143 }
144 catch ( NamingException ne )
145 {
146 return 1;
147 }
148 }
149 else
150 {
151 return 1;
152 }
153
154 int dnComp = dn0.compareTo( dn1 );
155
156 if ( dnComp != 0 )
157 {
158 return dnComp;
159 }
160
161 return uid0.compareTo( uid1 );
162 }
163 }
164 else
165 {
166 return -1;
167 }
168 }
169
170
171 public LdapDN getDn( Object obj ) throws NamingException
172 {
173 LdapDN dn = null;
174
175 if ( obj instanceof LdapDN )
176 {
177 dn = (LdapDN)obj;
178
179 dn = ( dn.isNormalized() ? dn : LdapDN.normalize( dn, attrRegistry.getNormalizerMapping() ) );
180 }
181 else if ( obj instanceof Name )
182 {
183 dn = new LdapDN( ( Name ) obj );
184 dn.normalize( attrRegistry.getNormalizerMapping() );
185 }
186 else if ( obj instanceof String )
187 {
188 dn = new LdapDN( ( String ) obj );
189 dn.normalize( attrRegistry.getNormalizerMapping() );
190 }
191 else
192 {
193 throw new IllegalStateException( "I do not know how to handle dn comparisons with objects of class: "
194 + (obj == null ? null : obj.getClass() ) );
195 }
196
197 return dn;
198 }
199 }