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.api.ldap.model.schema; 21 22 23 /** 24 * An attributeType specification. attributeType specifications describe the 25 * nature of attributes within the directory. The attributeType specification's 26 * properties are accessible through this interface. 27 * <p> 28 * According to ldapbis [MODELS]: 29 * </p> 30 * 31 * <pre> 32 * 4.1.2. Attribute Types 33 * 34 * Attribute Type definitions are written according to the ABNF: 35 * 36 * AttributeTypeDescription = LPAREN WSP 37 * numericoid ; object identifier 38 * [ SP "NAME" SP qdescrs ] ; short names (descriptors) 39 * [ SP "DESC" SP qdstring ] ; description 40 * [ SP "OBSOLETE" ] ; not active 41 * [ SP "SUP" SP oid ] ; supertype 42 * [ SP "EQUALITY" SP oid ] ; equality matching rule 43 * [ SP "ORDERING" SP oid ] ; ordering matching rule 44 * [ SP "SUBSTR" SP oid ] ; substrings matching rule 45 * [ SP "SYNTAX" SP noidlen ] ; value syntax 46 * [ SP "SINGLE-VALUE" ] ; single-value 47 * [ SP "COLLECTIVE" ] ; collective 48 * [ SP "NO-USER-MODIFICATION" ]; not user modifiable 49 * [ SP "USAGE" SP usage ] ; usage 50 * extensions WSP RPAREN ; extensions 51 * 52 * usage = "userApplications" / ; user 53 * "directoryOperation" / ; directory operational 54 * "distributedOperation" / ; DSA-shared operational 55 * "dSAOperation" ; DSA-specific operational 56 * 57 * where: 58 * [numericoid] is object identifier assigned to this attribute type; 59 * NAME [qdescrs] are short names (descriptors) identifying this 60 * attribute type; 61 * DESC [qdstring] is a short descriptive string; 62 * OBSOLETE indicates this attribute type is not active; 63 * SUP oid specifies the direct supertype of this type; 64 * EQUALITY, ORDERING, SUBSTRING provide the oid of the equality, 65 * ordering, and substrings matching rules, respectively; 66 * SYNTAX identifies value syntax by object identifier and may suggest 67 * a minimum upper bound; 68 * COLLECTIVE indicates this attribute type is collective [X.501]; 69 * NO-USER-MODIFICATION indicates this attribute type is not user 70 * modifiable; 71 * USAGE indicates the application of this attribute type; and 72 * [extensions] describe extensions. 73 * 74 * Each attribute type description must contain at least one of the SUP 75 * or SYNTAX fields. 76 * 77 * Usage of userApplications, the default, indicates that attributes of 78 * this type represent user information. That is, they are user 79 * attributes. 80 * 81 * COLLECTIVE requires usage userApplications. Use of collective 82 * attribute types in LDAP is not discussed in this technical 83 * specification. 84 * 85 * A usage of directoryOperation, distributedOperation, or dSAOperation 86 * indicates that attributes of this type represent operational and/or 87 * administrative information. That is, they are operational attributes. 88 * 89 * directoryOperation usage indicates that the attribute of this type is 90 * a directory operational attribute. distributedOperation usage 91 * indicates that the attribute of this DSA-shared usage operational 92 * attribute. dSAOperation usage indicates that the attribute of this 93 * type is a DSA-specific operational attribute. 94 * 95 * NO-USER-MODIFICATION requires an operational usage. 96 * 97 * Note that the [AttributeTypeDescription] does not list the matching 98 * rules which can be used with that attribute type in an extensibleMatch 99 * search filter. This is done using the 'matchingRuleUse' attribute 100 * described in Section 4.1.4. 101 * 102 * This document refines the schema description of X.501 by requiring 103 * that the SYNTAX field in an [AttributeTypeDescription] be a string 104 * representation of an object identifier for the LDAP string syntax 105 * definition with an optional indication of the suggested minimum bound 106 * of a value of this attribute. 107 * 108 * A suggested minimum upper bound on the number of characters in a value 109 * with a string-based syntax, or the number of bytes in a value for all 110 * other syntaxes, may be indicated by appending this bound count inside 111 * of curly braces following the syntax's OBJECT IDENTIFIER in an 112 * 113 * Attribute Type Description. This bound is not part of the syntax name 114 * itself. For instance, "1.3.6.4.1.1466.0{64}" suggests that server 115 * implementations should allow a string to be 64 characters long, 116 * although they may allow longer strings. Note that a single character 117 * of the Directory String syntax may be encoded in more than one octet 118 * since UTF-8 is a variable-length encoding. 119 * </pre> 120 * 121 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC 2252 Section 4.2</a> 122 * @see <a 123 * href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt"> 124 * ldapbis [MODELS]</a> 125 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 126 */ 127 public class AttributeType extends AbstractSchemaObject implements Cloneable 128 { 129 /** The mandatory serialVersionUID */ 130 public static final long serialVersionUID = 1L; 131 132 /** The syntax OID associated with this AttributeType */ 133 protected String syntaxOid; 134 135 /** The syntax associated with the syntaxID */ 136 protected LdapSyntax syntax; 137 138 /** The equality OID associated with this AttributeType */ 139 protected String equalityOid; 140 141 /** The equality MatchingRule associated with the equalityID */ 142 protected MatchingRule equality; 143 144 /** The substring OID associated with this AttributeType */ 145 protected String substringOid; 146 147 /** The substring MatchingRule associated with the substringID */ 148 protected MatchingRule substring; 149 150 /** The ordering OID associated with this AttributeType */ 151 protected String orderingOid; 152 153 /** The ordering MatchingRule associated with the orderingID */ 154 protected MatchingRule ordering; 155 156 /** The superior AttributeType OID */ 157 protected String superiorOid; 158 159 /** The superior AttributeType */ 160 protected AttributeType superior; 161 162 /** whether or not this type is single valued */ 163 protected boolean isSingleValued = false; 164 165 /** whether or not this type is a collective attribute */ 166 protected boolean isCollective = false; 167 168 /** whether or not this type can be modified by directory users */ 169 protected boolean canUserModify = true; 170 171 /** the usage for this attributeType */ 172 protected UsageEnum usage = UsageEnum.USER_APPLICATIONS; 173 174 /** the length of this attribute in bytes */ 175 protected long syntaxLength = 0L; 176 177 /** A flag set when the SchemaManager is in relaxed mode */ 178 private boolean isRelaxed = false; 179 180 181 /** 182 * Creates a AttributeType object using a unique OID. 183 * 184 * @param oid the OID for this AttributeType 185 */ 186 public AttributeType( String oid ) 187 { 188 super( SchemaObjectType.ATTRIBUTE_TYPE, oid ); 189 } 190 191 192 /** 193 * Gets whether or not this AttributeType is single-valued. 194 * 195 * @return true if only one value can exist for this AttributeType, false 196 * otherwise 197 */ 198 public boolean isSingleValued() 199 { 200 return isSingleValued; 201 } 202 203 204 /** 205 * Gets whether or not this AttributeType can be modified by a user. 206 * 207 * @return true if users can modify it, false if only the directory can. 208 */ 209 public boolean isUserModifiable() 210 { 211 return canUserModify; 212 } 213 214 215 /** 216 * Gets whether or not this AttributeType is a collective attribute. 217 * 218 * @return true if the attribute is collective, false otherwise 219 */ 220 public boolean isCollective() 221 { 222 return isCollective; 223 } 224 225 226 /** 227 * @return Tells if the AttributeType is relaxed (the SyntaxChecker will not be activated) 228 */ 229 public boolean isRelaxed() 230 { 231 return isRelaxed; 232 } 233 234 235 /** 236 * Set this AttributeType mode to relaxed 237 * 238 * @param isRelaxed <tt>true</tt> if the syntax checker for this AttributeType should not be activated 239 */ 240 public void setRelaxed( boolean isRelaxed ) 241 { 242 this.isRelaxed = isRelaxed; 243 } 244 245 246 /** 247 * Determines the usage for this AttributeType. 248 * 249 * @return a type safe UsageEnum 250 */ 251 public UsageEnum getUsage() 252 { 253 return usage; 254 } 255 256 257 /** 258 * Gets a length limit for this AttributeType. 259 * 260 * @return the length of the attribute 261 */ 262 public long getSyntaxLength() 263 { 264 return syntaxLength; 265 } 266 267 268 /** 269 * Gets the the superior AttributeType of this AttributeType. 270 * 271 * @return the superior AttributeType for this AttributeType 272 */ 273 public AttributeType getSuperior() 274 { 275 return superior; 276 } 277 278 279 /** 280 * Gets the OID of the superior AttributeType for this AttributeType. 281 * 282 * @return The OID of the superior AttributeType for this AttributeType. 283 */ 284 public String getSuperiorOid() 285 { 286 return superiorOid; 287 } 288 289 290 /** 291 * Gets the Name of the superior AttributeType for this AttributeType. 292 * 293 * @return The Name of the superior AttributeType for this AttributeType. 294 */ 295 public String getSuperiorName() 296 { 297 if ( superior != null ) 298 { 299 return superior.getName(); 300 } 301 else 302 { 303 return superiorOid; 304 } 305 } 306 307 308 /** 309 * Gets the Syntax for this AttributeType's values. 310 * 311 * @return the value syntax 312 */ 313 public LdapSyntax getSyntax() 314 { 315 return syntax; 316 } 317 318 319 /** 320 * Gets the Syntax name for this AttributeType's values. 321 * 322 * @return the value syntax name 323 */ 324 public String getSyntaxName() 325 { 326 if ( syntax != null ) 327 { 328 return syntax.getName(); 329 } 330 else 331 { 332 return syntaxOid; 333 } 334 } 335 336 337 /** 338 * Gets the Syntax OID for this AttributeType's values. 339 * 340 * @return the value syntax's OID 341 */ 342 public String getSyntaxOid() 343 { 344 return syntaxOid; 345 } 346 347 348 /** 349 * Gets the MatchingRule for this AttributeType used for equality matching. 350 * 351 * @return the equality matching rule 352 */ 353 public MatchingRule getEquality() 354 { 355 return equality; 356 } 357 358 359 /** 360 * Gets the Equality OID for this AttributeType's values. 361 * 362 * @return the value Equality's OID 363 */ 364 public String getEqualityOid() 365 { 366 return equalityOid; 367 } 368 369 370 /** 371 * Gets the Equality Name for this AttributeType's values. 372 * 373 * @return the value Equality's Name 374 */ 375 public String getEqualityName() 376 { 377 if ( equality != null ) 378 { 379 return equality.getName(); 380 } 381 else 382 { 383 return equalityOid; 384 } 385 } 386 387 388 /** 389 * Gets the MatchingRule for this AttributeType used for Ordering matching. 390 * 391 * @return the Ordering matching rule 392 */ 393 public MatchingRule getOrdering() 394 { 395 return ordering; 396 } 397 398 399 /** 400 * Gets the MatchingRule name for this AttributeType used for Ordering matching. 401 * 402 * @return the Ordering matching rule name 403 */ 404 public String getOrderingName() 405 { 406 if ( ordering != null ) 407 { 408 return ordering.getName(); 409 } 410 else 411 { 412 return orderingOid; 413 } 414 } 415 416 417 /** 418 * Gets the Ordering OID for this AttributeType's values. 419 * 420 * @return the value Equality's OID 421 */ 422 public String getOrderingOid() 423 { 424 return orderingOid; 425 } 426 427 428 /** 429 * Gets the MatchingRule for this AttributeType used for Substr matching. 430 * 431 * @return the Substr matching rule 432 */ 433 public MatchingRule getSubstring() 434 { 435 return substring; 436 } 437 438 439 /** 440 * Gets the MatchingRule name for this AttributeType used for Substring matching. 441 * 442 * @return the Substring matching rule name 443 */ 444 public String getSubstringName() 445 { 446 if ( substring != null ) 447 { 448 return substring.getName(); 449 } 450 else 451 { 452 return substringOid; 453 } 454 } 455 456 457 /** 458 * Gets the Substr OID for this AttributeType's values. 459 * 460 * @return the value Substr's OID 461 */ 462 public String getSubstringOid() 463 { 464 return substringOid; 465 } 466 467 468 /** 469 * Tells if the attributeType is a USER attribute or not 470 * @return true if this is a USER attributeType 471 */ 472 public boolean isUser() 473 { 474 return usage == UsageEnum.USER_APPLICATIONS; 475 } 476 477 478 /** 479 * Tells if the attributeType is an OPERATIONAL attribute or not 480 * @return true if this is an OPERATIONAL attributeType 481 */ 482 public boolean isOperational() 483 { 484 return usage != UsageEnum.USER_APPLICATIONS; 485 } 486 487 488 /** 489 * Checks to see if this AttributeType is the ancestor of another 490 * attributeType. 491 * 492 * @param descendant the perspective descendant to check 493 * @return true if the descendant is truly a derived from this AttributeType 494 */ 495 public boolean isAncestorOf( AttributeType descendant ) 496 { 497 if ( ( descendant == null ) || this.equals( descendant ) ) 498 { 499 return false; 500 } 501 502 return isAncestorOrEqual( this, descendant ); 503 } 504 505 506 /** 507 * Checks to see if this AttributeType is the descendant of another 508 * attributeType. 509 * 510 * @param ancestor the perspective ancestor to check 511 * @return true if this AttributeType truly descends from the ancestor 512 */ 513 public boolean isDescendantOf( AttributeType ancestor ) 514 { 515 if ( ( ancestor == null ) || equals( ancestor ) ) 516 { 517 return false; 518 } 519 520 return isAncestorOrEqual( ancestor, this ); 521 } 522 523 524 /** 525 * Recursive method which checks to see if a descendant is really an ancestor or if the two 526 * are equal. 527 * 528 * @param ancestor the possible ancestor of the descendant 529 * @param descendant the possible descendant of the ancestor 530 * @return true if the ancestor equals the descendant or if the descendant is really 531 * a subtype of the ancestor. otherwise false 532 */ 533 private boolean isAncestorOrEqual( AttributeType ancestor, AttributeType descendant ) 534 { 535 if ( ( ancestor == null ) || ( descendant == null ) ) 536 { 537 return false; 538 } 539 540 if ( ancestor.equals( descendant ) ) 541 { 542 return true; 543 } 544 545 return isAncestorOrEqual( ancestor, descendant.getSuperior() ); 546 } 547 548 549 /** 550 * {@inheritDoc} 551 */ 552 @Override 553 public String toString() 554 { 555 return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this ); 556 } 557 558 559 /** 560 * {@inheritDoc} 561 */ 562 @Override 563 public AttributeType copy() 564 { 565 MutableAttributeType copy = new MutableAttributeType( oid ); 566 567 // Copy the SchemaObject common data 568 copy.copy( this ); 569 570 // Copy the canUserModify flag 571 copy.canUserModify = canUserModify; 572 573 // Copy the isCollective flag 574 copy.isCollective = isCollective; 575 576 // Copy the isSingleValue flag 577 copy.isSingleValued = isSingleValued; 578 579 // Copy the USAGE type 580 copy.usage = usage; 581 582 // All the references to other Registries object are set to null, 583 // all the OIDs are copied 584 // The EQUALITY MR 585 copy.equality = null; 586 copy.equalityOid = equalityOid; 587 588 // The ORDERING MR 589 copy.ordering = null; 590 copy.orderingOid = orderingOid; 591 592 // The SUBSTR MR 593 copy.substring = null; 594 copy.substringOid = substringOid; 595 596 // The SUP AT 597 copy.superior = null; 598 copy.superiorOid = superiorOid; 599 600 // The SYNTAX 601 copy.syntax = null; 602 copy.syntaxOid = syntaxOid; 603 copy.syntaxLength = syntaxLength; 604 605 // The relaxed flag 606 copy.setRelaxed( isRelaxed ); 607 608 return copy; 609 } 610 611 612 /** 613 * {@inheritDoc} 614 */ 615 @Override 616 public boolean equals( Object o ) 617 { 618 if ( !super.equals( o ) ) 619 { 620 return false; 621 } 622 623 if ( !( o instanceof AttributeType ) ) 624 { 625 return false; 626 } 627 628 AttributeType that = ( AttributeType ) o; 629 630 // The COLLECTIVE 631 if ( isCollective != that.isCollective ) 632 { 633 return false; 634 } 635 636 // The SINGLE_VALUE 637 if ( isSingleValued != that.isSingleValued ) 638 { 639 return false; 640 } 641 642 // The NO_USER_MODIFICATION 643 if ( canUserModify != that.canUserModify ) 644 { 645 return false; 646 } 647 648 // The USAGE 649 if ( usage != that.usage ) 650 { 651 return false; 652 } 653 654 // The equality 655 if ( !compareOid( equalityOid, that.equalityOid ) ) 656 { 657 return false; 658 } 659 660 if ( equality != null ) 661 { 662 if ( !equality.equals( that.equality ) ) 663 { 664 return false; 665 } 666 } 667 else 668 { 669 if ( that.equality != null ) 670 { 671 return false; 672 } 673 } 674 675 // The ordering 676 if ( !compareOid( orderingOid, that.orderingOid ) ) 677 { 678 return false; 679 } 680 681 if ( ordering != null ) 682 { 683 if ( !ordering.equals( that.ordering ) ) 684 { 685 return false; 686 } 687 } 688 else 689 { 690 if ( that.ordering != null ) 691 { 692 return false; 693 } 694 } 695 696 // The substring 697 if ( !compareOid( substringOid, that.substringOid ) ) 698 { 699 return false; 700 } 701 702 if ( substring != null ) 703 { 704 if ( !substring.equals( that.substring ) ) 705 { 706 return false; 707 } 708 } 709 else 710 { 711 if ( that.substring != null ) 712 { 713 return false; 714 } 715 } 716 717 // The superior 718 if ( !compareOid( superiorOid, that.superiorOid ) ) 719 { 720 return false; 721 } 722 723 if ( superior != null ) 724 { 725 if ( !superior.equals( that.superior ) ) 726 { 727 return false; 728 } 729 } 730 else 731 { 732 if ( that.superior != null ) 733 { 734 return false; 735 } 736 } 737 738 // The syntax 739 if ( !compareOid( syntaxOid, that.syntaxOid ) ) 740 { 741 return false; 742 } 743 744 if ( syntaxLength != that.syntaxLength ) 745 { 746 return false; 747 } 748 749 if ( syntax == null ) 750 { 751 return that.syntax == null; 752 } 753 754 if ( syntax.equals( that.syntax ) ) 755 { 756 return syntaxLength == that.syntaxLength; 757 } 758 else 759 { 760 return false; 761 } 762 } 763 }