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.shared.ldap.schema; 021 022 023 import java.util.List; 024 025 import org.apache.directory.shared.i18n.I18n; 026 import org.apache.directory.shared.ldap.exception.LdapException; 027 import org.apache.directory.shared.ldap.exception.LdapProtocolErrorException; 028 import org.apache.directory.shared.ldap.schema.comparators.ComparableComparator; 029 import org.apache.directory.shared.ldap.schema.normalizers.NoOpNormalizer; 030 import org.apache.directory.shared.ldap.schema.registries.Registries; 031 032 033 /** 034 * A matchingRule definition. MatchingRules associate a comparator and a 035 * normalizer, forming the basic tools necessary to assert actions against 036 * attribute values. MatchingRules are associated with a specific Syntax for the 037 * purpose of resolving a normalized form and for comparisons. 038 * <p> 039 * According to ldapbis [MODELS]: 040 * </p> 041 * 042 * <pre> 043 * 4.1.3. Matching Rules 044 * 045 * Matching rules are used by servers to compare attribute values against 046 * assertion values when performing Search and Compare operations. They 047 * are also used to identify the value to be added or deleted when 048 * modifying entries, and are used when comparing a purported 049 * distinguished name with the name of an entry. 050 * 051 * A matching rule specifies the syntax of the assertion value. 052 * 053 * Each matching rule is identified by an object identifier (OID) and, 054 * optionally, one or more short names (descriptors). 055 * 056 * Matching rule definitions are written according to the ABNF: 057 * 058 * MatchingRuleDescription = LPAREN WSP 059 * numericoid ; object identifier 060 * [ SP "NAME" SP qdescrs ] ; short names (descriptors) 061 * [ SP "DESC" SP qdstring ] ; description 062 * [ SP "OBSOLETE" ] ; not active 063 * SP "SYNTAX" SP numericoid ; assertion syntax 064 * extensions WSP RPAREN ; extensions 065 * 066 * where: 067 * [numericoid] is object identifier assigned to this matching rule; 068 * NAME [qdescrs] are short names (descriptors) identifying this 069 * matching rule; 070 * DESC [qdstring] is a short descriptive string; 071 * OBSOLETE indicates this matching rule is not active; 072 * SYNTAX identifies the assertion syntax by object identifier; and 073 * [extensions] describe extensions. 074 * </pre> 075 * 076 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC 2252 Section 4.5</a> 077 * @see <a 078 * href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis 079 * [MODELS]</a> 080 * @see DescriptionUtils#getDescription(MatchingRule) 081 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 082 * @version $Rev: 927122 $ 083 */ 084 public class MatchingRule extends AbstractSchemaObject 085 { 086 /** The serialVersionUID */ 087 private static final long serialVersionUID = 1L; 088 089 /** The associated Comparator */ 090 protected LdapComparator<? super Object> ldapComparator; 091 092 /** The associated Normalizer */ 093 protected Normalizer normalizer; 094 095 /** The associated LdapSyntax */ 096 protected LdapSyntax ldapSyntax; 097 098 /** The associated LdapSyntax OID */ 099 private String ldapSyntaxOid; 100 101 102 /** 103 * Creates a new instance of MatchingRule. 104 * 105 * @param oid The MatchingRule OID 106 * @param registries The Registries reference 107 */ 108 public MatchingRule( String oid ) 109 { 110 super( SchemaObjectType.MATCHING_RULE, oid ); 111 } 112 113 114 /** 115 * Inject the MatchingRule into the registries, updating the references to 116 * other SchemaObject 117 * 118 * @param registries The Registries 119 * @exception If the addition failed 120 */ 121 public void addToRegistries( List<Throwable> errors, Registries registries ) throws LdapException 122 { 123 if ( registries != null ) 124 { 125 try 126 { 127 // Gets the associated Comparator 128 ldapComparator = ( LdapComparator<? super Object> ) registries.getComparatorRegistry().lookup( oid ); 129 } 130 catch ( LdapException ne ) 131 { 132 // Default to a catch all comparator 133 ldapComparator = new ComparableComparator( oid ); 134 } 135 136 try 137 { 138 // Gets the associated Normalizer 139 normalizer = registries.getNormalizerRegistry().lookup( oid ); 140 } 141 catch ( LdapException ne ) 142 { 143 // Default to the NoOp normalizer 144 normalizer = new NoOpNormalizer( oid ); 145 } 146 147 try 148 { 149 // Get the associated LdapSyntax 150 ldapSyntax = registries.getLdapSyntaxRegistry().lookup( ldapSyntaxOid ); 151 } 152 catch ( LdapException ne ) 153 { 154 // The Syntax is a mandatory element, it must exist. 155 throw new LdapProtocolErrorException( I18n.err( I18n.ERR_04317 ) ); 156 } 157 158 /** 159 * Add the MR references (using and usedBy) : 160 * MR -> C 161 * MR -> N 162 * MR -> S 163 */ 164 if ( ldapComparator != null ) 165 { 166 registries.addReference( this, ldapComparator ); 167 } 168 169 if ( normalizer != null ) 170 { 171 registries.addReference( this, normalizer ); 172 } 173 174 if ( ldapSyntax != null ) 175 { 176 registries.addReference( this, ldapSyntax ); 177 } 178 179 } 180 } 181 182 183 /** 184 * Remove the MatchingRule from the registries, updating the references to 185 * other SchemaObject. 186 * 187 * If one of the referenced SchemaObject does not exist (), 188 * an exception is thrown. 189 * 190 * @param registries The Registries 191 * @exception If the MatchingRule is not valid 192 */ 193 public void removeFromRegistries( List<Throwable> errors, Registries registries ) throws LdapException 194 { 195 if ( registries != null ) 196 { 197 /** 198 * Remove the MR references (using and usedBy) : 199 * MR -> C 200 * MR -> N 201 * MR -> S 202 */ 203 if ( ldapComparator != null ) 204 { 205 registries.delReference( this, ldapComparator ); 206 } 207 208 if ( ldapSyntax != null ) 209 { 210 registries.delReference( this, ldapSyntax ); 211 } 212 213 if ( normalizer != null ) 214 { 215 registries.delReference( this, normalizer ); 216 } 217 } 218 } 219 220 221 /** 222 * Gets the LdapSyntax used by this MatchingRule. 223 * 224 * @return the LdapSyntax of this MatchingRule 225 */ 226 public LdapSyntax getSyntax() 227 { 228 return ldapSyntax; 229 } 230 231 232 /** 233 * Gets the LdapSyntax OID used by this MatchingRule. 234 * 235 * @return the LdapSyntax of this MatchingRule 236 * @throws NamingException if there is a failure resolving the object 237 */ 238 public String getSyntaxOid() 239 { 240 return ldapSyntaxOid; 241 } 242 243 244 /** 245 * Sets the Syntax's OID 246 * 247 * @param oid The Syntax's OID 248 */ 249 public void setSyntaxOid( String oid ) 250 { 251 if ( locked ) 252 { 253 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 254 } 255 256 if ( !isReadOnly ) 257 { 258 this.ldapSyntaxOid = oid; 259 } 260 } 261 262 263 /** 264 * Sets the Syntax 265 * 266 * @param oid The Syntax 267 */ 268 public void setSyntax( LdapSyntax ldapSyntax ) 269 { 270 if ( locked ) 271 { 272 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 273 } 274 275 if ( !isReadOnly ) 276 { 277 this.ldapSyntax = ldapSyntax; 278 this.ldapSyntaxOid = ldapSyntax.getOid(); 279 } 280 } 281 282 283 /** 284 * Update the associated Syntax, even if the SchemaObject is readOnly 285 * 286 * @param oid The Syntax 287 */ 288 public void updateSyntax( LdapSyntax ldapSyntax ) 289 { 290 if ( locked ) 291 { 292 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 293 } 294 295 this.ldapSyntax = ldapSyntax; 296 this.ldapSyntaxOid = ldapSyntax.getOid(); 297 } 298 299 300 /** 301 * Gets the LdapComparator enabling the use of this MatchingRule for ORDERING 302 * and sorted indexing. 303 * 304 * @return the ordering LdapComparator 305 * @throws NamingException if there is a failure resolving the object 306 */ 307 public LdapComparator<? super Object> getLdapComparator() 308 { 309 return ldapComparator; 310 } 311 312 313 /** 314 * Sets the LdapComparator 315 * 316 * @param oid The LdapComparator 317 */ 318 public void setLdapComparator( LdapComparator<?> ldapComparator ) 319 { 320 if ( locked ) 321 { 322 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 323 } 324 325 if ( !isReadOnly ) 326 { 327 this.ldapComparator = ( LdapComparator<? super Object> ) ldapComparator; 328 } 329 } 330 331 332 /** 333 * Update the associated Comparator, even if the SchemaObject is readOnly 334 * 335 * @param oid The LdapComparator 336 */ 337 public void updateLdapComparator( LdapComparator<?> ldapComparator ) 338 { 339 if ( locked ) 340 { 341 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 342 } 343 344 this.ldapComparator = ( LdapComparator<? super Object> ) ldapComparator; 345 } 346 347 348 /** 349 * Gets the Normalizer enabling the use of this MatchingRule for EQUALITY 350 * matching and indexing. 351 * 352 * @return the associated normalizer 353 * @throws NamingException if there is a failure resolving the object 354 */ 355 public Normalizer getNormalizer() 356 { 357 return normalizer; 358 } 359 360 361 /** 362 * Sets the Normalizer 363 * 364 * @param oid The Normalizer 365 */ 366 public void setNormalizer( Normalizer normalizer ) 367 { 368 if ( locked ) 369 { 370 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 371 } 372 373 if ( !isReadOnly ) 374 { 375 this.normalizer = normalizer; 376 } 377 } 378 379 380 /** 381 * Update the associated Normalizer, even if the SchemaObject is readOnly 382 * 383 * @param oid The Normalizer 384 */ 385 public void updateNormalizer( Normalizer normalizer ) 386 { 387 if ( locked ) 388 { 389 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 390 } 391 392 this.normalizer = normalizer; 393 } 394 395 396 /** 397 * @see Object#toString() 398 */ 399 public String toString() 400 { 401 return objectType + " " + DescriptionUtils.getDescription( this ); 402 } 403 404 405 /** 406 * Copy an MatchingRule 407 */ 408 public MatchingRule copy() 409 { 410 MatchingRule copy = new MatchingRule( oid ); 411 412 // Copy the SchemaObject common data 413 copy.copy( this ); 414 415 // All the references to other Registries object are set to null. 416 copy.ldapComparator = null; 417 copy.ldapSyntax = null; 418 copy.normalizer = null; 419 420 // Copy the syntax OID 421 copy.ldapSyntaxOid = ldapSyntaxOid; 422 423 return copy; 424 } 425 426 427 /** 428 * @see Object#equals() 429 */ 430 public boolean equals( Object o ) 431 { 432 if ( !super.equals( o ) ) 433 { 434 return false; 435 } 436 437 if ( !( o instanceof MatchingRule ) ) 438 { 439 return false; 440 } 441 442 MatchingRule that = ( MatchingRule ) o; 443 444 // Check the Comparator 445 if ( ldapComparator != null ) 446 { 447 if ( !ldapComparator.equals( that.ldapComparator ) ) 448 { 449 return false; 450 } 451 } 452 else 453 { 454 if ( that.ldapComparator != null ) 455 { 456 return false; 457 } 458 } 459 460 // Check the Normalizer 461 if ( normalizer != null ) 462 { 463 if ( !normalizer.equals( that.normalizer ) ) 464 { 465 return false; 466 } 467 } 468 else 469 { 470 if ( that.normalizer != null ) 471 { 472 return false; 473 } 474 } 475 476 // Check the Syntax 477 if ( !compareOid( ldapSyntaxOid, that.ldapSyntaxOid ) ) 478 { 479 return false; 480 } 481 482 return ldapSyntax.equals( that.ldapSyntax ); 483 } 484 485 486 /** 487 * {@inheritDoc} 488 */ 489 public void clear() 490 { 491 // Clear the common elements 492 super.clear(); 493 494 // Clear the references 495 ldapComparator = null; 496 ldapSyntax = null; 497 normalizer = null; 498 } 499 }