1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 */
20 package org.apache.directory.server.schema;
21
22
23 import java.util.Comparator;
24
25 import javax.naming.Name;
26 import javax.naming.NamingException;
27
28 import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
29 import org.apache.directory.server.schema.registries.Registries;
30 import org.apache.directory.shared.ldap.name.LdapDN;
31
32
33 /**
34 * A comparator for the uniqueMember match
35 *
36 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
37 * @version $Rev$
38 */
39 public class NameAndOptionalUIDComparator implements Comparator
40 {
41 // @TODO you'll need this to fix the way normalization is done
42 private AttributeTypeRegistry attrRegistry;
43
44
45 public NameAndOptionalUIDComparator( AttributeTypeRegistry attrRegistry )
46 {
47 this.attrRegistry = attrRegistry;
48 }
49
50
51 public NameAndOptionalUIDComparator()
52 {
53 }
54
55
56 public void setRegistries( Registries registries )
57 {
58 attrRegistry = registries.getAttributeTypeRegistry();
59 }
60
61 /**
62 * Comparing two uniqueMember is a matter of following this algorithm:
63 * - if they are only DN, then the values should be equal
64 * - otherwise, both element should contain the same DN and
65 * * if they both have an UID, they should be equals.
66 */
67 public int compare( Object obj0, Object obj1 )
68 {
69 String dnstr0 = null;
70 String dnstr1 = null;
71
72 if ( ( obj0 instanceof String ) && ( obj1 instanceof String) )
73 {
74 dnstr0 = (String)obj0;
75 dnstr1 = (String)obj1;
76
77 int dash0 = dnstr0.lastIndexOf( '#' );
78 int dash1 = dnstr1.lastIndexOf( '#' );
79
80 if ( ( dash0 == -1 ) && ( dash1 == -1 ) )
81 {
82 // no UID part
83 try
84 {
85 return getDn( dnstr0 ).compareTo( getDn ( dnstr1 ) );
86 }
87 catch ( NamingException ne )
88 {
89 return -1;
90 }
91 }
92 else
93 {
94 // Now, check that we don't have another '#'
95 if ( dnstr0.indexOf( '#' ) != dash0 )
96 {
97 // Yes, we have one : this is not allowed, it should have been
98 // escaped.
99 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 }