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 */ 020package org.apache.directory.api.ldap.model.schema; 021 022 023 024 025/** 026 * An attributeType specification. attributeType specifications describe the 027 * nature of attributes within the directory. The attributeType specification's 028 * properties are accessible through this interface. 029 * <p> 030 * According to ldapbis [MODELS]: 031 * </p> 032 * 033 * <pre> 034 * 4.1.2. Attribute Types 035 * 036 * Attribute Type definitions are written according to the ABNF: 037 * 038 * AttributeTypeDescription = LPAREN WSP 039 * numericoid ; object identifier 040 * [ SP "NAME" SP qdescrs ] ; short names (descriptors) 041 * [ SP "DESC" SP qdstring ] ; description 042 * [ SP "OBSOLETE" ] ; not active 043 * [ SP "SUP" SP oid ] ; supertype 044 * [ SP "EQUALITY" SP oid ] ; equality matching rule 045 * [ SP "ORDERING" SP oid ] ; ordering matching rule 046 * [ SP "SUBSTR" SP oid ] ; substrings matching rule 047 * [ SP "SYNTAX" SP noidlen ] ; value syntax 048 * [ SP "SINGLE-VALUE" ] ; single-value 049 * [ SP "COLLECTIVE" ] ; collective 050 * [ SP "NO-USER-MODIFICATION" ]; not user modifiable 051 * [ SP "USAGE" SP usage ] ; usage 052 * extensions WSP RPAREN ; extensions 053 * 054 * usage = "userApplications" / ; user 055 * "directoryOperation" / ; directory operational 056 * "distributedOperation" / ; DSA-shared operational 057 * "dSAOperation" ; DSA-specific operational 058 * 059 * where: 060 * [numericoid] is object identifier assigned to this attribute type; 061 * NAME [qdescrs] are short names (descriptors) identifying this 062 * attribute type; 063 * DESC [qdstring] is a short descriptive string; 064 * OBSOLETE indicates this attribute type is not active; 065 * SUP oid specifies the direct supertype of this type; 066 * EQUALITY, ORDERING, SUBSTRING provide the oid of the equality, 067 * ordering, and substrings matching rules, respectively; 068 * SYNTAX identifies value syntax by object identifier and may suggest 069 * a minimum upper bound; 070 * COLLECTIVE indicates this attribute type is collective [X.501]; 071 * NO-USER-MODIFICATION indicates this attribute type is not user 072 * modifiable; 073 * USAGE indicates the application of this attribute type; and 074 * [extensions] describe extensions. 075 * 076 * Each attribute type description must contain at least one of the SUP 077 * or SYNTAX fields. 078 * 079 * Usage of userApplications, the default, indicates that attributes of 080 * this type represent user information. That is, they are user 081 * attributes. 082 * 083 * COLLECTIVE requires usage userApplications. Use of collective 084 * attribute types in LDAP is not discussed in this technical 085 * specification. 086 * 087 * A usage of directoryOperation, distributedOperation, or dSAOperation 088 * indicates that attributes of this type represent operational and/or 089 * administrative information. That is, they are operational attributes. 090 * 091 * directoryOperation usage indicates that the attribute of this type is 092 * a directory operational attribute. distributedOperation usage 093 * indicates that the attribute of this DSA-shared usage operational 094 * attribute. dSAOperation usage indicates that the attribute of this 095 * type is a DSA-specific operational attribute. 096 * 097 * NO-USER-MODIFICATION requires an operational usage. 098 * 099 * Note that the [AttributeTypeDescription] does not list the matching 100 * rules which can be used with that attribute type in an extensibleMatch 101 * search filter. This is done using the 'matchingRuleUse' attribute 102 * described in Section 4.1.4. 103 * 104 * This document refines the schema description of X.501 by requiring 105 * that the SYNTAX field in an [AttributeTypeDescription] be a string 106 * representation of an object identifier for the LDAP string syntax 107 * definition with an optional indication of the suggested minimum bound 108 * of a value of this attribute. 109 * 110 * A suggested minimum upper bound on the number of characters in a value 111 * with a string-based syntax, or the number of bytes in a value for all 112 * other syntaxes, may be indicated by appending this bound count inside 113 * of curly braces following the syntax's OBJECT IDENTIFIER in an 114 * 115 * Attribute Type Description. This bound is not part of the syntax name 116 * itself. For instance, "1.3.6.4.1.1466.0{64}" suggests that server 117 * implementations should allow a string to be 64 characters long, 118 * although they may allow longer strings. Note that a single character 119 * of the Directory String syntax may be encoded in more than one octet 120 * since UTF-8 is a variable-length encoding. 121 * </pre> 122 * 123 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC 2252 Section 4.2</a> 124 * @see <a 125 * href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt"> 126 * ldapbis [MODELS]</a> 127 * @see DescriptionUtils#getDescription(AttributeType) 128 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 129 */ 130public class AttributeType extends AbstractSchemaObject implements Cloneable 131{ 132 /** The mandatory serialVersionUID */ 133 public static final long serialVersionUID = 1L; 134 135 /** The syntax OID associated with this AttributeType */ 136 protected String syntaxOid; 137 138 /** The syntax associated with the syntaxID */ 139 protected LdapSyntax syntax; 140 141 /** The equality OID associated with this AttributeType */ 142 protected String equalityOid; 143 144 /** The equality MatchingRule associated with the equalityID */ 145 protected MatchingRule equality; 146 147 /** The substring OID associated with this AttributeType */ 148 protected String substringOid; 149 150 /** The substring MatchingRule associated with the substringID */ 151 protected MatchingRule substring; 152 153 /** The ordering OID associated with this AttributeType */ 154 protected String orderingOid; 155 156 /** The ordering MatchingRule associated with the orderingID */ 157 protected MatchingRule ordering; 158 159 /** The superior AttributeType OID */ 160 protected String superiorOid; 161 162 /** The superior AttributeType */ 163 protected AttributeType superior; 164 165 /** whether or not this type is single valued */ 166 protected boolean isSingleValued = false; 167 168 /** whether or not this type is a collective attribute */ 169 protected boolean isCollective = false; 170 171 /** whether or not this type can be modified by directory users */ 172 protected boolean canUserModify = true; 173 174 /** the usage for this attributeType */ 175 protected UsageEnum usage = UsageEnum.USER_APPLICATIONS; 176 177 /** the length of this attribute in bytes */ 178 protected long syntaxLength = 0L; 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 * Determines the usage for this AttributeType. 228 * 229 * @return a type safe UsageEnum 230 */ 231 public UsageEnum getUsage() 232 { 233 return usage; 234 } 235 236 237 /** 238 * Gets a length limit for this AttributeType. 239 * 240 * @return the length of the attribute 241 */ 242 public long getSyntaxLength() 243 { 244 return syntaxLength; 245 } 246 247 248 /** 249 * Gets the the superior AttributeType of this AttributeType. 250 * 251 * @return the superior AttributeType for this AttributeType 252 */ 253 public AttributeType getSuperior() 254 { 255 return superior; 256 } 257 258 259 /** 260 * Gets the OID of the superior AttributeType for this AttributeType. 261 * 262 * @return The OID of the superior AttributeType for this AttributeType. 263 */ 264 public String getSuperiorOid() 265 { 266 return superiorOid; 267 } 268 269 270 /** 271 * Gets the Name of the superior AttributeType for this AttributeType. 272 * 273 * @return The Name of the superior AttributeType for this AttributeType. 274 */ 275 public String getSuperiorName() 276 { 277 if ( superior != null ) 278 { 279 return superior.getName(); 280 } 281 else 282 { 283 return superiorOid; 284 } 285 } 286 287 288 /** 289 * Gets the Syntax for this AttributeType's values. 290 * 291 * @return the value syntax 292 */ 293 public LdapSyntax getSyntax() 294 { 295 return syntax; 296 } 297 298 299 /** 300 * Gets the Syntax name for this AttributeType's values. 301 * 302 * @return the value syntax name 303 */ 304 public String getSyntaxName() 305 { 306 if ( syntax != null ) 307 { 308 return syntax.getName(); 309 } 310 else 311 { 312 return syntaxOid; 313 } 314 } 315 316 317 /** 318 * Gets the Syntax OID for this AttributeType's values. 319 * 320 * @return the value syntax's OID 321 */ 322 public String getSyntaxOid() 323 { 324 return syntaxOid; 325 } 326 327 328 /** 329 * Gets the MatchingRule for this AttributeType used for equality matching. 330 * 331 * @return the equality matching rule 332 */ 333 public MatchingRule getEquality() 334 { 335 return equality; 336 } 337 338 339 /** 340 * Gets the Equality OID for this AttributeType's values. 341 * 342 * @return the value Equality's OID 343 */ 344 public String getEqualityOid() 345 { 346 return equalityOid; 347 } 348 349 350 /** 351 * Gets the Equality Name for this AttributeType's values. 352 * 353 * @return the value Equality's Name 354 */ 355 public String getEqualityName() 356 { 357 if ( equality != null ) 358 { 359 return equality.getName(); 360 } 361 else 362 { 363 return equalityOid; 364 } 365 } 366 367 368 /** 369 * Gets the MatchingRule for this AttributeType used for Ordering matching. 370 * 371 * @return the Ordering matching rule 372 */ 373 public MatchingRule getOrdering() 374 { 375 return ordering; 376 } 377 378 379 /** 380 * Gets the MatchingRule name for this AttributeType used for Ordering matching. 381 * 382 * @return the Ordering matching rule name 383 */ 384 public String getOrderingName() 385 { 386 if ( ordering != null ) 387 { 388 return ordering.getName(); 389 } 390 else 391 { 392 return orderingOid; 393 } 394 } 395 396 397 /** 398 * Gets the Ordering OID for this AttributeType's values. 399 * 400 * @return the value Equality's OID 401 */ 402 public String getOrderingOid() 403 { 404 return orderingOid; 405 } 406 407 408 /** 409 * Gets the MatchingRule for this AttributeType used for Substr matching. 410 * 411 * @return the Substr matching rule 412 */ 413 public MatchingRule getSubstring() 414 { 415 return substring; 416 } 417 418 419 /** 420 * Gets the MatchingRule name for this AttributeType used for Substring matching. 421 * 422 * @return the Substring matching rule name 423 */ 424 public String getSubstringName() 425 { 426 if ( substring != null ) 427 { 428 return substring.getName(); 429 } 430 else 431 { 432 return substringOid; 433 } 434 } 435 436 437 /** 438 * Gets the Substr OID for this AttributeType's values. 439 * 440 * @return the value Substr's OID 441 */ 442 public String getSubstringOid() 443 { 444 return substringOid; 445 } 446 447 448 /** 449 * Tells if the attributeType is a USER attribute or not 450 * @return true if this is a USER attributeType 451 */ 452 public boolean isUser() 453 { 454 return usage == UsageEnum.USER_APPLICATIONS; 455 } 456 457 458 /** 459 * Tells if the attributeType is an OPERATIONAL attribute or not 460 * @return true if this is an OPERATIONAL attributeType 461 */ 462 public boolean isOperational() 463 { 464 return usage != UsageEnum.USER_APPLICATIONS; 465 } 466 467 468 /** 469 * Checks to see if this AttributeType is the ancestor of another 470 * attributeType. 471 * 472 * @param descendant the perspective descendant to check 473 * @return true if the descendant is truly a derived from this AttributeType 474 */ 475 public boolean isAncestorOf( AttributeType descendant ) 476 { 477 if ( ( descendant == null ) || this.equals( descendant ) ) 478 { 479 return false; 480 } 481 482 return isAncestorOrEqual( this, descendant ); 483 } 484 485 486 /** 487 * Checks to see if this AttributeType is the descendant of another 488 * attributeType. 489 * 490 * @param ancestor the perspective ancestor to check 491 * @return true if this AttributeType truly descends from the ancestor 492 */ 493 public boolean isDescendantOf( AttributeType ancestor ) 494 { 495 if ( ( ancestor == null ) || equals( ancestor ) ) 496 { 497 return false; 498 } 499 500 return isAncestorOrEqual( ancestor, this ); 501 } 502 503 504 /** 505 * Recursive method which checks to see if a descendant is really an ancestor or if the two 506 * are equal. 507 * 508 * @param ancestor the possible ancestor of the descendant 509 * @param descendant the possible descendant of the ancestor 510 * @return true if the ancestor equals the descendant or if the descendant is really 511 * a subtype of the ancestor. otherwise false 512 */ 513 private boolean isAncestorOrEqual( AttributeType ancestor, AttributeType descendant ) 514 { 515 if ( ( ancestor == null ) || ( descendant == null ) ) 516 { 517 return false; 518 } 519 520 if ( ancestor.equals( descendant ) ) 521 { 522 return true; 523 } 524 525 return isAncestorOrEqual( ancestor, descendant.getSuperior() ); 526 } 527 528 529 /** 530 * {@inheritDoc} 531 */ 532 public String toString() 533 { 534 return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this ); 535 } 536 537 538 /** 539 * {@inheritDoc} 540 */ 541 public AttributeType copy() 542 { 543 MutableAttributeType copy = new MutableAttributeType( oid ); 544 545 // Copy the SchemaObject common data 546 copy.copy( this ); 547 548 // Copy the canUserModify flag 549 copy.canUserModify = canUserModify; 550 551 // Copy the isCollective flag 552 copy.isCollective = isCollective; 553 554 // Copy the isSingleValue flag 555 copy.isSingleValued = isSingleValued; 556 557 // Copy the USAGE type 558 copy.usage = usage; 559 560 // All the references to other Registries object are set to null, 561 // all the OIDs are copied 562 // The EQUALITY MR 563 copy.equality = null; 564 copy.equalityOid = equalityOid; 565 566 // The ORDERING MR 567 copy.ordering = null; 568 copy.orderingOid = orderingOid; 569 570 // The SUBSTR MR 571 copy.substring = null; 572 copy.substringOid = substringOid; 573 574 // The SUP AT 575 copy.superior = null; 576 copy.superiorOid = superiorOid; 577 578 // The SYNTAX 579 copy.syntax = null; 580 copy.syntaxOid = syntaxOid; 581 copy.syntaxLength = syntaxLength; 582 583 return copy; 584 } 585 586 587 /** 588 * {@inheritDoc} 589 */ 590 public boolean equals( Object o ) 591 { 592 if ( !super.equals( o ) ) 593 { 594 return false; 595 } 596 597 if ( !( o instanceof AttributeType ) ) 598 { 599 return false; 600 } 601 602 AttributeType that = ( AttributeType ) o; 603 604 // The COLLECTIVE 605 if ( isCollective != that.isCollective ) 606 { 607 return false; 608 } 609 610 // The SINGLE_VALUE 611 if ( isSingleValued != that.isSingleValued ) 612 { 613 return false; 614 } 615 616 // The NO_USER_MODIFICATION 617 if ( canUserModify != that.canUserModify ) 618 { 619 return false; 620 } 621 622 // The USAGE 623 if ( usage != that.usage ) 624 { 625 return false; 626 } 627 628 // The equality 629 if ( !compareOid( equalityOid, that.equalityOid ) ) 630 { 631 return false; 632 } 633 634 if ( equality != null ) 635 { 636 if ( !equality.equals( that.equality ) ) 637 { 638 return false; 639 } 640 } 641 else 642 { 643 if ( that.equality != null ) 644 { 645 return false; 646 } 647 } 648 649 // The ordering 650 if ( !compareOid( orderingOid, that.orderingOid ) ) 651 { 652 return false; 653 } 654 655 if ( ordering != null ) 656 { 657 if ( !ordering.equals( that.ordering ) ) 658 { 659 return false; 660 } 661 } 662 else 663 { 664 if ( that.ordering != null ) 665 { 666 return false; 667 } 668 } 669 670 // The substring 671 if ( !compareOid( substringOid, that.substringOid ) ) 672 { 673 return false; 674 } 675 676 if ( substring != null ) 677 { 678 if ( !substring.equals( that.substring ) ) 679 { 680 return false; 681 } 682 } 683 else 684 { 685 if ( that.substring != null ) 686 { 687 return false; 688 } 689 } 690 691 // The superior 692 if ( !compareOid( superiorOid, that.superiorOid ) ) 693 { 694 return false; 695 } 696 697 if ( superior != null ) 698 { 699 if ( !superior.equals( that.superior ) ) 700 { 701 return false; 702 } 703 } 704 else 705 { 706 if ( that.superior != null ) 707 { 708 return false; 709 } 710 } 711 712 // The syntax 713 if ( !compareOid( syntaxOid, that.syntaxOid ) ) 714 { 715 return false; 716 } 717 718 if ( syntaxLength != that.syntaxLength ) 719 { 720 return false; 721 } 722 723 if ( syntax == null ) 724 { 725 return that.syntax == null; 726 } 727 728 if ( syntax.equals( that.syntax ) ) 729 { 730 return syntaxLength == that.syntaxLength; 731 } 732 else 733 { 734 return false; 735 } 736 } 737}