001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2011-2015 ForgeRock AS 026 */ 027package org.opends.server.types; 028 029import java.util.Collection; 030import java.util.List; 031import java.util.Map; 032 033import org.forgerock.i18n.slf4j.LocalizedLogger; 034import org.forgerock.opendj.ldap.schema.AttributeUsage; 035import org.forgerock.opendj.ldap.schema.Syntax; 036import org.forgerock.opendj.ldap.schema.MatchingRule; 037import org.opends.server.core.DirectoryServer; 038 039import static org.forgerock.util.Reject.*; 040import static org.opends.server.util.ServerConstants.*; 041 042/** 043 * This class defines a data structure for storing and interacting 044 * with an attribute type, which contains information about the format 045 * of an attribute and the syntax and matching rules that should be 046 * used when interacting with it. 047 * <p> 048 * Any methods which accesses the set of names associated with this 049 * attribute type, will retrieve the primary name as the first name, 050 * regardless of whether or not it was contained in the original set 051 * of <code>names</code> passed to the constructor. 052 * <p> 053 * Where ordered sets of names, or extra properties are provided, the 054 * ordering will be preserved when the associated fields are accessed 055 * via their getters or via the {@link #toString()} methods. 056 */ 057@org.opends.server.types.PublicAPI( 058 stability=org.opends.server.types.StabilityLevel.UNCOMMITTED, 059 mayInstantiate=false, 060 mayExtend=false, 061 mayInvoke=true) 062public final class AttributeType 063 extends CommonSchemaElements 064 implements Comparable<AttributeType> 065{ 066 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 067 068 /** The approximate matching rule for this attribute type. */ 069 private final MatchingRule approximateMatchingRule; 070 071 /** The syntax for this attribute type. */ 072 private final Syntax syntax; 073 074 /** The superior attribute type from which this attribute type inherits. */ 075 private final AttributeType superiorType; 076 077 /** The attribute usage for this attribute type. */ 078 private final AttributeUsage attributeUsage; 079 080 /** Indicates whether this attribute type is declared "collective". */ 081 private final boolean isCollective; 082 083 /** 084 * Indicates whether this attribute type is declared 085 * "no-user-modification". 086 */ 087 private final boolean isNoUserModification; 088 089 /** Indicates whether this attribute type is the objectclass type. */ 090 private final boolean isObjectClassType; 091 092 /** Indicates whether this attribute type is operational. */ 093 private final boolean isOperational; 094 095 /** Indicates whether this attribute type is declared "single-value". */ 096 private final boolean isSingleValue; 097 098 /** 099 * Indicates whether there is a possibility that this attribute type 100 * may have one or more subtypes that list this type or one of its 101 * subtypes as a superior. Note that this variable is intentional 102 * not declared "final", but if it ever gets set to "true", then it 103 * should never be unset back to "false". 104 */ 105 private boolean mayHaveSubordinateTypes; 106 /** The definition string used to create this attribute type. */ 107 private final String definition; 108 109 /** The equality matching rule for this attribute type. */ 110 private final MatchingRule equalityMatchingRule; 111 /** The ordering matching rule for this attribute type. */ 112 private final MatchingRule orderingMatchingRule; 113 /** The substring matching rule for this attribute type. */ 114 private final MatchingRule substringMatchingRule; 115 116 /** True once this attribute type has been removed from the schema. */ 117 private volatile boolean isDirty; 118 119 120 121 /** 122 * Creates a new attribute type with the provided information. 123 * <p> 124 * If no <code>primaryName</code> is specified, but a set of 125 * <code>names</code> is specified, then the first name retrieved 126 * from the set of <code>names</code> will be used as the primary 127 * name. 128 * 129 * @param definition 130 * The definition string used to create this attribute 131 * type. It must not be {@code null}. 132 * @param primaryName 133 * The primary name for this attribute type, or 134 * <code>null</code> if there is no primary name. 135 * @param typeNames 136 * The full set of names for this attribute type, or 137 * <code>null</code> if there are no names. 138 * @param oid 139 * The OID for this attribute type. It must not be 140 * {@code null}. 141 * @param description 142 * The description for the attribute type, or 143 * <code>null</code> if there is no description. 144 * @param superiorType 145 * The reference to the superior type for this attribute 146 * type, or <code>null</code> if there is no superior 147 * type. 148 * @param syntax 149 * The syntax for this attribute type, or <code>null</code> 150 * if there is no syntax. 151 * @param attributeUsage 152 * The attribute usage for this attribute type, or 153 * <code>null</code> to default to user applications. 154 * @param isCollective 155 * Indicates whether this attribute type is declared 156 * "collective". 157 * @param isNoUserModification 158 * Indicates whether this attribute type is declared 159 * "no-user-modification". 160 * @param isObsolete 161 * Indicates whether this attribute type is declared 162 * "obsolete". 163 * @param isSingleValue 164 * Indicates whether this attribute type is declared 165 * "single-value". 166 */ 167 public AttributeType(String definition, String primaryName, 168 Collection<String> typeNames, 169 String oid, String description, 170 AttributeType superiorType, 171 Syntax syntax, 172 AttributeUsage attributeUsage, 173 boolean isCollective, 174 boolean isNoUserModification, 175 boolean isObsolete, boolean isSingleValue) 176 { 177 this(definition, primaryName, typeNames, oid, description, 178 superiorType, syntax, null, null, null, 179 null, attributeUsage, isCollective, 180 isNoUserModification, isObsolete, isSingleValue, null); 181 } 182 183 184 185 /** 186 * Creates a new attribute type with the provided information. 187 * <p> 188 * If no <code>primaryName</code> is specified, but a set of 189 * <code>names</code> is specified, then the first name retrieved 190 * from the set of <code>names</code> will be used as the primary 191 * name. 192 * 193 * @param definition 194 * The definition string used to create this attribute 195 * type. It must not be {@code null}. 196 * @param primaryName 197 * The primary name for this attribute type, or 198 * <code>null</code> if there is no primary name. 199 * @param typeNames 200 * The full set of names for this attribute type, or 201 * <code>null</code> if there are no names. 202 * @param oid 203 * The OID for this attribute type. It must not be 204 * {@code null}. 205 * @param description 206 * The description for the attribute type, or 207 * <code>null</code> if there is no description. 208 * @param superiorType 209 * The reference to the superior type for this attribute 210 * type, or <code>null</code> if there is no superior 211 * type. 212 * @param syntax 213 * The syntax for this attribute type, or <code>null</code> 214 * if there is no syntax. 215 * @param approximateMatchingRule 216 * The approximate matching rule for this attribute type, 217 * or <code>null</code> if there is no rule. 218 * @param equalityMatchingRule 219 * The equality matching rule for this attribute type, or 220 * <code>null</code> if there is no rule. 221 * @param orderingMatchingRule 222 * The ordering matching rule for this attribute type, or 223 * <code>null</code> if there is no rule. 224 * @param substringMatchingRule 225 * The substring matching rule for this attribute type, or 226 * <code>null</code> if there is no rule. 227 * @param attributeUsage 228 * The attribute usage for this attribute type, or 229 * <code>null</code> to default to user applications. 230 * @param isCollective 231 * Indicates whether this attribute type is declared 232 * "collective". 233 * @param isNoUserModification 234 * Indicates whether this attribute type is declared 235 * "no-user-modification". 236 * @param isObsolete 237 * Indicates whether this attribute type is declared 238 * "obsolete". 239 * @param isSingleValue 240 * Indicates whether this attribute type is declared 241 * "single-value". 242 * @param extraProperties 243 * A set of extra properties for this attribute type, or 244 * <code>null</code> if there are no extra properties. 245 */ 246 public AttributeType(String definition, String primaryName, 247 Collection<String> typeNames, 248 String oid, String description, 249 AttributeType superiorType, 250 Syntax syntax, 251 MatchingRule approximateMatchingRule, 252 MatchingRule equalityMatchingRule, 253 MatchingRule orderingMatchingRule, 254 MatchingRule substringMatchingRule, 255 AttributeUsage attributeUsage, 256 boolean isCollective, 257 boolean isNoUserModification, 258 boolean isObsolete, boolean isSingleValue, 259 Map<String,List<String>> extraProperties) 260 { 261 super(primaryName, typeNames, oid, description, isObsolete, 262 extraProperties); 263 264 265 ifNull(definition, oid); 266 267 this.superiorType = superiorType; 268 this.isCollective = isCollective; 269 this.isNoUserModification = isNoUserModification; 270 this.isSingleValue = isSingleValue; 271 272 mayHaveSubordinateTypes = false; 273 274 int schemaFilePos = definition.indexOf(SCHEMA_PROPERTY_FILENAME); 275 if (schemaFilePos > 0) 276 { 277 String defStr; 278 try 279 { 280 int firstQuotePos = definition.indexOf('\'', schemaFilePos); 281 int secondQuotePos = definition.indexOf('\'', 282 firstQuotePos+1); 283 284 defStr = definition.substring(0, schemaFilePos).trim() + " " + 285 definition.substring(secondQuotePos+1).trim(); 286 } 287 catch (Exception e) 288 { 289 logger.traceException(e); 290 291 defStr = definition; 292 } 293 294 this.definition = defStr; 295 } 296 else 297 { 298 this.definition = definition; 299 } 300 301 if (syntax == null) 302 { 303 if (superiorType != null) 304 { 305 this.syntax = superiorType.getSyntax(); 306 } 307 else 308 { 309 this.syntax = DirectoryServer.getDefaultAttributeSyntax(); 310 } 311 } 312 else 313 { 314 this.syntax = syntax; 315 } 316 317 if (approximateMatchingRule == null) 318 { 319 this.approximateMatchingRule = 320 this.syntax.getApproximateMatchingRule(); 321 } 322 else 323 { 324 this.approximateMatchingRule = approximateMatchingRule; 325 } 326 327 328 if (equalityMatchingRule == null) 329 { 330 this.equalityMatchingRule = 331 this.syntax.getEqualityMatchingRule(); 332 } 333 else 334 { 335 this.equalityMatchingRule = equalityMatchingRule; 336 } 337 338 339 if (orderingMatchingRule == null) 340 { 341 this.orderingMatchingRule = 342 this.syntax.getOrderingMatchingRule(); 343 } 344 else 345 { 346 this.orderingMatchingRule = orderingMatchingRule; 347 } 348 349 350 if (substringMatchingRule == null) 351 { 352 this.substringMatchingRule = 353 this.syntax.getSubstringMatchingRule(); 354 } 355 else 356 { 357 this.substringMatchingRule = substringMatchingRule; 358 } 359 360 if (attributeUsage != null) 361 { 362 this.attributeUsage = attributeUsage; 363 } 364 else 365 { 366 this.attributeUsage = AttributeUsage.USER_APPLICATIONS; 367 } 368 369 if (oid.equals(OBJECTCLASS_ATTRIBUTE_TYPE_OID)) 370 { 371 isObjectClassType = true; 372 } 373 else 374 { 375 isObjectClassType = hasName(OBJECTCLASS_ATTRIBUTE_TYPE_NAME); 376 } 377 378 isOperational = this.attributeUsage.isOperational(); 379 } 380 381 382 383 /** 384 * Retrieves the superior type for this attribute type. 385 * 386 * @return The superior type for this attribute type, or 387 * <CODE>null</CODE> if it does not have one. 388 */ 389 public AttributeType getSuperiorType() 390 { 391 return superiorType; 392 } 393 394 395 396 /** 397 * Indicates whether there is a possibility that this attribute type 398 * may have one or more subordinate attribute types defined in the 399 * server schema. This is only intended for use by the 400 * {@code org.opends.server.types.Entry} class for the purpose of 401 * determining whether to check for subtypes when retrieving 402 * attributes. Note that it is possible for this method to report 403 * false positives (if an attribute type that previously had one or 404 * more subordinate types no longer has any), but not false 405 * negatives. 406 * 407 * @return {@code true} if the {@code hasSubordinateTypes} flag has 408 * been set for this attribute type at any time since 409 * startup, or {@code false} if not. 410 */ 411 boolean mayHaveSubordinateTypes() 412 { 413 return mayHaveSubordinateTypes; 414 } 415 416 417 418 /** 419 * Sets a flag indicating that this attribute type may have one or 420 * more subordinate attribute types defined in the server schema. 421 * This is only intended for use by the 422 * {@code org.opends.server.types.Schema} class. 423 */ 424 void setMayHaveSubordinateTypes() 425 { 426 mayHaveSubordinateTypes = true; 427 } 428 429 430 431 /** 432 * Retrieves the syntax for this attribute type. 433 * 434 * @return The syntax for this attribute type. 435 */ 436 public Syntax getSyntax() 437 { 438 return syntax; 439 } 440 441 /** 442 * Retrieves the matching rule that should be used for approximate 443 * matching with this attribute type. 444 * 445 * @return The matching rule that should be used for approximate 446 * matching with this attribute type. 447 */ 448 public MatchingRule getApproximateMatchingRule() 449 { 450 return approximateMatchingRule; 451 } 452 453 454 455 /** 456 * Retrieves the matching rule that should be used for equality 457 * matching with this attribute type. 458 * 459 * @return The matching rule that should be used for equality 460 * matching with this attribute type. 461 */ 462 public MatchingRule getEqualityMatchingRule() 463 { 464 return equalityMatchingRule; 465 } 466 467 468 469 /** 470 * Retrieves the matching rule that should be used for ordering with 471 * this attribute type. 472 * 473 * @return The matching rule that should be used for ordering with 474 * this attribute type. 475 */ 476 public MatchingRule getOrderingMatchingRule() 477 { 478 return orderingMatchingRule; 479 } 480 481 482 483 /** 484 * Retrieves the matching rule that should be used for substring 485 * matching with this attribute type. 486 * 487 * @return The matching rule that should be used for substring 488 * matching with this attribute type. 489 */ 490 public MatchingRule getSubstringMatchingRule() 491 { 492 return substringMatchingRule; 493 } 494 495 496 497 /** 498 * Retrieves the usage indicator for this attribute type. 499 * 500 * @return The usage indicator for this attribute type. 501 */ 502 public AttributeUsage getUsage() 503 { 504 return attributeUsage; 505 } 506 507 508 509 /** 510 * Indicates whether this is an operational attribute. An 511 * operational attribute is one with a usage of 512 * "directoryOperation", "distributedOperation", or "dSAOperation" 513 * (i.e., only userApplications is not operational). 514 * 515 * @return <CODE>true</CODE> if this is an operational attribute, 516 * or <CODE>false</CODE> if not. 517 */ 518 public boolean isOperational() 519 { 520 return isOperational; 521 } 522 523 524 525 /** 526 * Indicates whether this attribute type is declared "collective". 527 * 528 * @return <CODE>true</CODE> if this attribute type is declared 529 * "collective", or <CODE>false</CODE> if not. 530 */ 531 public boolean isCollective() 532 { 533 return isCollective; 534 } 535 536 537 538 /** 539 * Indicates whether this attribute type is declared 540 * "no-user-modification". 541 * 542 * @return <CODE>true</CODE> if this attribute type is declared 543 * "no-user-modification", or <CODE>false</CODE> if not. 544 */ 545 public boolean isNoUserModification() 546 { 547 return isNoUserModification; 548 } 549 550 551 552 /** 553 * Indicates whether this attribute type is declared "single-value". 554 * 555 * @return <CODE>true</CODE> if this attribute type is declared 556 * "single-value", or <CODE>false</CODE> if not. 557 */ 558 public boolean isSingleValue() 559 { 560 return isSingleValue; 561 } 562 563 564 565 /** 566 * Indicates whether this attribute type represents the 567 * "objectclass" attribute. The determination will be made based on 568 * the name and/or OID. 569 * 570 * @return <CODE>true</CODE> if this attribute type is the 571 * objectclass type, or <CODE>false</CODE> if not. 572 */ 573 public boolean isObjectClass() 574 { 575 return isObjectClassType; 576 } 577 578 /** {@inheritDoc} */ 579 @Override 580 public String toString() 581 { 582 return definition; 583 } 584 585 /** {@inheritDoc} */ 586 @Override 587 public int compareTo(AttributeType o) { 588 return getNormalizedPrimaryNameOrOID().compareTo( 589 o.getNormalizedPrimaryNameOrOID()); 590 } 591 592 593 594 /** 595 * Marks this attribute type as dirty, indicating that it has been removed or 596 * replaced in the schema. 597 * 598 * @return A reference to this attribute type. 599 */ 600 public AttributeType setDirty() 601 { 602 isDirty = true; 603 return this; 604 } 605 606 607 608 /** 609 * Returns {@code true} if this attribute type has been removed or replaced in 610 * the schema. 611 * 612 * @return {@code true} if this attribute type has been removed or replaced in 613 * the schema. 614 */ 615 public boolean isDirty() 616 { 617 return isDirty; 618 } 619} 620