1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.schema.registries;
21
22
23 import java.util.Collections;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.Iterator;
27 import java.util.Map;
28 import java.util.Set;
29
30 import javax.naming.NamingException;
31 import javax.naming.directory.NoSuchAttributeException;
32
33 import org.apache.directory.shared.ldap.constants.SchemaConstants;
34 import org.apache.directory.shared.ldap.schema.AttributeType;
35 import org.apache.directory.shared.ldap.schema.MatchingRule;
36 import org.apache.directory.shared.ldap.schema.NoOpNormalizer;
37 import org.apache.directory.shared.ldap.schema.OidNormalizer;
38 import org.apache.directory.shared.ldap.util.StringTools;
39
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43
44
45
46
47
48
49
50 public class DefaultAttributeTypeRegistry implements AttributeTypeRegistry
51 {
52
53 private static final Logger LOG = LoggerFactory.getLogger( DefaultAttributeTypeRegistry.class );
54
55
56 private static final boolean IS_DEBUG = LOG.isDebugEnabled();
57
58
59 private final Map<String,AttributeType> byOid;
60
61 private final Map<String,Set<AttributeType>> oidToDescendantSet;
62
63 private final OidRegistry oidRegistry;
64
65 private transient Map<String, OidNormalizer> mapping;
66
67
68
69
70
71
72
73
74
75
76
77
78
79 public DefaultAttributeTypeRegistry( OidRegistry oidRegistry )
80 {
81 this.byOid = new HashMap<String,AttributeType>();
82 this.oidToDescendantSet= new HashMap<String,Set<AttributeType>>();
83 this.oidRegistry = oidRegistry;
84 }
85
86
87
88
89
90
91
92 public void register( AttributeType attributeType ) throws NamingException
93 {
94 if ( byOid.containsKey( attributeType.getOid() ) )
95 {
96 throw new NamingException( "attributeType w/ OID " + attributeType.getOid()
97 + " has already been registered!" );
98 }
99
100 String[] names = attributeType.getNamesRef();
101 for ( String name : names )
102 {
103 oidRegistry.register( name, attributeType.getOid() );
104 }
105 oidRegistry.register( attributeType.getOid(), attributeType.getOid() );
106
107 if ( mapping != null )
108 {
109 addMappingFor( attributeType );
110 }
111
112 registerDescendants( attributeType );
113 byOid.put( attributeType.getOid(), attributeType );
114
115 if ( IS_DEBUG )
116 {
117 LOG.debug( "registed attributeType: " + attributeType );
118 }
119 }
120
121
122 public Set<String> getBinaryAttributes() throws NamingException
123 {
124 Set<String> binaries = new HashSet<String>();
125 Iterator<AttributeType> list = iterator();
126 while ( list.hasNext() )
127 {
128 AttributeType type = list.next();
129
130 if ( ! type.getSyntax().isHumanReadable() )
131 {
132
133 binaries.add( type.getOid() );
134
135
136 String[] names = type.getNamesRef();
137
138 for ( String name : names )
139 {
140
141 binaries.add( StringTools.lowerCaseAscii( StringTools.trim( name ) ) );
142 }
143 }
144 }
145
146 return binaries;
147 }
148
149
150 public void registerDescendants( AttributeType attributeType ) throws NamingException
151 {
152
153 oidToDescendantSet.put( attributeType.getOid(), new HashSet<AttributeType>( 5 ) );
154
155
156 onRegisterAddToAncestorDescendants( attributeType, attributeType.getSuperior() );
157 }
158
159
160
161
162
163
164
165
166
167
168 protected void onRegisterAddToAncestorDescendants( AttributeType newType, AttributeType ancestor )
169 throws NamingException
170 {
171 if ( ancestor == null )
172 {
173 return;
174 }
175
176 if ( ancestor.getName() != null && ancestor.getName().equals( SchemaConstants.TOP_OC ) )
177 {
178 return;
179 }
180
181 Set<AttributeType> descendants = oidToDescendantSet.get( ancestor.getOid() );
182 if ( descendants == null )
183 {
184 descendants = new HashSet<AttributeType>( 5 );
185 oidToDescendantSet.put( ancestor.getOid(), descendants );
186 }
187 descendants.add( newType );
188 onRegisterAddToAncestorDescendants( newType, ancestor.getSuperior() );
189 }
190
191
192 public AttributeType lookup( String id ) throws NamingException
193 {
194 String oid = oidRegistry.getOid( id );
195
196 if ( !byOid.containsKey( oid ) )
197 {
198 throw new NoSuchAttributeException( "attributeType w/ OID " + oid + " not registered!" );
199 }
200
201 AttributeType attributeType = byOid.get( oid );
202
203 if ( IS_DEBUG )
204 {
205 LOG.debug( "lookup with id" + oid + "' of attributeType: " + attributeType );
206 }
207
208 return attributeType;
209 }
210
211
212 public boolean hasAttributeType( String id )
213 {
214 if ( oidRegistry.hasOid( id ) )
215 {
216 try
217 {
218 return byOid.containsKey( oidRegistry.getOid( id ) );
219 }
220 catch ( NamingException e )
221 {
222 return false;
223 }
224 }
225
226 return false;
227 }
228
229
230 public String getSchemaName( String id ) throws NamingException
231 {
232 id = oidRegistry.getOid( id );
233 AttributeType at = byOid.get( id );
234
235 if ( at != null )
236 {
237 return at.getSchema();
238 }
239
240 throw new NamingException( "OID " + id + " not found in oid to " + "AttributeType map!" );
241 }
242
243
244 public Iterator list()
245 {
246 return byOid.values().iterator();
247 }
248
249
250 private void removeMappingFor( AttributeType type ) throws NamingException
251 {
252 if ( type == null )
253 {
254 return;
255 }
256
257 MatchingRule matchingRule = type.getEquality();
258 mapping.remove( type.getOid() );
259 String[] aliases = type.getNamesRef();
260 for ( String aliase : aliases )
261 {
262 mapping.remove( aliase );
263 mapping.remove( aliase.toLowerCase() );
264 }
265 }
266
267
268 private void addMappingFor( AttributeType type ) throws NamingException
269 {
270 MatchingRule matchingRule = type.getEquality();
271 OidNormalizer oidNormalizer;
272
273 if ( matchingRule == null )
274 {
275 LOG.debug( "Attribute " + type.getName() + " does not have normalizer : using NoopNormalizer" );
276 oidNormalizer = new OidNormalizer( type.getOid(), new NoOpNormalizer() );
277 }
278 else
279 {
280 oidNormalizer = new OidNormalizer( type.getOid(), matchingRule.getNormalizer() );
281 }
282
283 mapping.put( type.getOid(), oidNormalizer );
284 String[] aliases = type.getNamesRef();
285 for ( String aliase : aliases )
286 {
287 mapping.put( aliase, oidNormalizer );
288 mapping.put( aliase.toLowerCase(), oidNormalizer );
289 }
290 }
291
292
293 public Map<String,OidNormalizer> getNormalizerMapping() throws NamingException
294 {
295 if ( mapping == null )
296 {
297 mapping = new HashMap<String,OidNormalizer>( byOid.size() << 1 );
298 for ( AttributeType type : byOid.values() )
299 {
300 addMappingFor( type );
301 }
302 }
303
304 return Collections.unmodifiableMap( mapping );
305 }
306
307
308 public Iterator<AttributeType> descendants( String ancestorId ) throws NamingException
309 {
310 String oid = oidRegistry.getOid( ancestorId );
311 Set<AttributeType> descendants = oidToDescendantSet.get( oid );
312 if ( descendants == null )
313 {
314
315 return Collections.EMPTY_SET.iterator();
316 }
317 return descendants.iterator();
318 }
319
320
321 public boolean hasDescendants( String ancestorId ) throws NamingException
322 {
323 String oid = oidRegistry.getOid( ancestorId );
324 Set descendants = oidToDescendantSet.get( oid );
325 return descendants != null && !descendants.isEmpty();
326 }
327
328
329 public Iterator<AttributeType> iterator()
330 {
331 return byOid.values().iterator();
332 }
333
334
335 public void unregister( String numericOid ) throws NamingException
336 {
337 if ( ! Character.isDigit( numericOid.charAt( 0 ) ) )
338 {
339 throw new NamingException( "Looks like the arg is not a numeric OID" );
340 }
341
342 if ( mapping != null )
343 {
344 removeMappingFor( byOid.get( numericOid ));
345 }
346
347 byOid.remove( numericOid );
348 oidToDescendantSet.remove( numericOid );
349 }
350 }