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 2009 Sun Microsystems, Inc. 025 * Portions copyright 2011-2015 ForgeRock AS 026 */ 027package org.forgerock.opendj.ldap.schema; 028 029import static com.forgerock.opendj.ldap.CoreMessages.*; 030import static java.util.Arrays.*; 031 032import static org.forgerock.opendj.ldap.schema.SchemaUtils.*; 033 034import java.util.Collection; 035import java.util.Collections; 036import java.util.HashSet; 037import java.util.Iterator; 038import java.util.LinkedHashSet; 039import java.util.LinkedList; 040import java.util.List; 041import java.util.Map; 042import java.util.Set; 043 044import org.forgerock.i18n.LocalizableMessage; 045import org.forgerock.i18n.LocalizableMessageDescriptor.Arg2; 046import org.forgerock.util.Reject; 047 048/** 049 * This class defines a DIT content rule, which defines the set of allowed, 050 * required, and prohibited attributes for entries with a given structural 051 * objectclass, and also indicates which auxiliary classes may be included in 052 * the entry. 053 */ 054public final class DITContentRule extends SchemaElement { 055 056 /** A fluent API for incrementally constructing DIT content rule. */ 057 public static final class Builder extends SchemaElementBuilder<Builder> { 058 private String structuralClassOID; 059 private final List<String> names = new LinkedList<>(); 060 private boolean isObsolete; 061 private final Set<String> auxiliaryClassOIDs = new LinkedHashSet<>(); 062 private final Set<String> optionalAttributeOIDs = new LinkedHashSet<>(); 063 private final Set<String> prohibitedAttributeOIDs = new LinkedHashSet<>(); 064 private final Set<String> requiredAttributeOIDs = new LinkedHashSet<>(); 065 066 Builder(final DITContentRule contentRule, final SchemaBuilder schemaBuilder) { 067 super(schemaBuilder, contentRule); 068 structuralClassOID = contentRule.structuralClassOID; 069 names.addAll(contentRule.getNames()); 070 isObsolete = contentRule.isObsolete; 071 auxiliaryClassOIDs.addAll(contentRule.auxiliaryClassOIDs); 072 optionalAttributeOIDs.addAll(contentRule.optionalAttributeOIDs); 073 prohibitedAttributeOIDs.addAll(contentRule.prohibitedAttributeOIDs); 074 requiredAttributeOIDs.addAll(contentRule.requiredAttributeOIDs); 075 } 076 077 Builder(final String structuralClassOID, final SchemaBuilder builder) { 078 super(builder); 079 this.structuralClassOID = structuralClassOID; 080 } 081 082 /** 083 * Adds this DIT content rule to the schema, throwing a 084 * {@code ConflictingSchemaElementException} if there is an existing DIT 085 * content rule with the same structural object class OID. 086 * 087 * @return The parent schema builder. 088 * @throws ConflictingSchemaElementException 089 * If there is an existing DIT content rule with the same 090 * structural object class OID. 091 */ 092 public SchemaBuilder addToSchema() { 093 return getSchemaBuilder().addDITContentRule(new DITContentRule(this), false); 094 } 095 096 /** 097 * Adds this DIT content rule to the schema overwriting any existing 098 * content rule with the same structural class OID. 099 * 100 * @return The parent schema builder. 101 */ 102 public SchemaBuilder addToSchemaOverwrite() { 103 return getSchemaBuilder().addDITContentRule(new DITContentRule(this), true); 104 } 105 106 /** 107 * Adds the provided auxiliary classes to the list of auxiliary object 108 * classes that entries subject to this DIT content rule may belong to. 109 * 110 * @param objectClassNamesOrOIDs 111 * The list of auxiliary class names or OIDs. 112 * @return This builder. 113 */ 114 public Builder auxiliaryObjectClasses(final Collection<String> objectClassNamesOrOIDs) { 115 this.auxiliaryClassOIDs.addAll(objectClassNamesOrOIDs); 116 return this; 117 } 118 119 /** 120 * Adds the provided auxiliary classes to the list of auxiliary object 121 * classes that entries subject to this DIT content rule may belong to. 122 * 123 * @param objectClassNamesOrOIDs 124 * The list of auxiliary class names or OIDs. 125 * @return This builder. 126 */ 127 public Builder auxiliaryObjectClasses(String... objectClassNamesOrOIDs) { 128 this.auxiliaryClassOIDs.addAll(asList(objectClassNamesOrOIDs)); 129 return this; 130 } 131 132 @Override 133 public Builder description(final String description) { 134 return description0(description); 135 } 136 137 @Override 138 public Builder extraProperties(final Map<String, List<String>> extraProperties) { 139 return extraProperties0(extraProperties); 140 } 141 142 @Override 143 public Builder extraProperties(final String extensionName, final String... extensionValues) { 144 return extraProperties0(extensionName, extensionValues); 145 } 146 147 @Override 148 Builder getThis() { 149 return this; 150 } 151 152 /** 153 * Adds the provided user friendly names. 154 * 155 * @param names 156 * The user friendly names. 157 * @return This builder. 158 */ 159 public Builder names(final Collection<String> names) { 160 this.names.addAll(names); 161 return this; 162 } 163 164 /** 165 * Adds the provided user friendly names. 166 * 167 * @param names 168 * The user friendly names. 169 * @return This builder. 170 */ 171 public Builder names(final String... names) { 172 return names(asList(names)); 173 } 174 175 /** 176 * Specifies whether this schema element is obsolete. 177 * 178 * @param isObsolete 179 * {@code true} if this schema element is obsolete (default 180 * is {@code false}). 181 * @return This builder. 182 */ 183 public Builder obsolete(final boolean isObsolete) { 184 this.isObsolete = isObsolete; 185 return this; 186 } 187 188 /** 189 * Adds the provided optional attributes to the list of attribute types 190 * that entries subject to this DIT content rule may contain. 191 * 192 * @param attributeNamesOrOIDs 193 * The list of optional attribute names or OIDs. 194 * @return This builder. 195 */ 196 public Builder optionalAttributes(final Collection<String> attributeNamesOrOIDs) { 197 this.optionalAttributeOIDs.addAll(attributeNamesOrOIDs); 198 return this; 199 } 200 201 /** 202 * Adds the provided optional attributes to the list of attribute types 203 * that entries subject to this DIT content rule may contain. 204 * 205 * @param attributeNamesOrOIDs 206 * The list of optional attribute names or OIDs. 207 * @return This builder. 208 */ 209 public Builder optionalAttributes(final String... attributeNamesOrOIDs) { 210 this.optionalAttributeOIDs.addAll(asList(attributeNamesOrOIDs)); 211 return this; 212 } 213 214 /** 215 * Adds the provided prohibited attributes to the list of attribute types 216 * that entries subject to this DIT content rule must not contain. 217 * 218 * @param attributeNamesOrOIDs 219 * The list of prohibited attribute names or OIDs. 220 * @return This builder. 221 */ 222 public Builder prohibitedAttributes(final Collection<String> attributeNamesOrOIDs) { 223 this.prohibitedAttributeOIDs.addAll(attributeNamesOrOIDs); 224 return this; 225 } 226 227 /** 228 * Adds the provided prohibited attributes to the list of attribute types 229 * that entries subject to this DIT content rule must not contain. 230 * 231 * @param attributeNamesOrOIDs 232 * The list of prohibited attribute names or OIDs. 233 * @return This builder. 234 */ 235 public Builder prohibitedAttributes(final String... attributeNamesOrOIDs) { 236 this.prohibitedAttributeOIDs.addAll(asList(attributeNamesOrOIDs)); 237 return this; 238 } 239 240 /** 241 * Clears the list of auxiliary object classes that entries subject to 242 * this DIT content rule may belong to. 243 * 244 * @return This builder. 245 */ 246 public Builder removeAllAuxiliaryObjectClasses() { 247 this.auxiliaryClassOIDs.clear(); 248 return this; 249 } 250 251 @Override 252 public Builder removeAllExtraProperties() { 253 return removeAllExtraProperties0(); 254 } 255 256 /** 257 * Removes all user defined names. 258 * 259 * @return This builder. 260 */ 261 public Builder removeAllNames() { 262 this.names.clear(); 263 return this; 264 } 265 266 /** 267 * Clears the list of attribute types that entries subject to this DIT 268 * content rule may contain. 269 * 270 * @return This builder. 271 */ 272 public Builder removeAllOptionalAttributes() { 273 this.optionalAttributeOIDs.clear(); 274 return this; 275 } 276 277 /** 278 * Clears the list of attribute types that entries subject to this DIT 279 * content rule must not contain. 280 * 281 * @return This builder. 282 */ 283 public Builder removeAllProhibitedAttributes() { 284 this.prohibitedAttributeOIDs.clear(); 285 return this; 286 } 287 288 /** 289 * Clears the list of attribute types that entries subject to this DIT 290 * content rule must contain. 291 * 292 * @return This builder. 293 */ 294 public Builder removeAllRequiredAttributes() { 295 this.requiredAttributeOIDs.clear(); 296 return this; 297 } 298 299 /** 300 * Removes the provided object class in the list of auxiliary object classes that entries subject to 301 * this DIT content rule may belong to. 302 * 303 * @param objectClassNameOrOID 304 * The auxiliary object class name or OID to be removed. 305 * @return This builder. 306 */ 307 public Builder removeAuxiliaryObjectClass(String objectClassNameOrOID) { 308 this.auxiliaryClassOIDs.remove(objectClassNameOrOID); 309 return this; 310 } 311 312 @Override 313 public Builder removeExtraProperty(String extensionName, String... extensionValues) { 314 return removeExtraProperty0(extensionName, extensionValues); 315 } 316 317 /** 318 * Removes the provided user defined name. 319 * 320 * @param name 321 * The user defined name to be removed. 322 * @return This builder. 323 */ 324 public Builder removeName(String name) { 325 this.names.remove(name); 326 return this; 327 } 328 329 /** 330 * Removes the provided optional attribute in the list of attribute 331 * types that entries subject to this DIT content rule may contain. 332 * 333 * @param attributeNameOrOID 334 * The optional attribute name or OID to be removed. 335 * @return This builder. 336 */ 337 public Builder removeOptionalAttribute(String attributeNameOrOID) { 338 this.optionalAttributeOIDs.remove(attributeNameOrOID); 339 return this; 340 } 341 342 /** 343 * Removes the provided prohibited attribute in the list of attribute 344 * types that entries subject to this DIT content rule must not contain. 345 * 346 * @param attributeNameOrOID 347 * The prohibited attribute name or OID to be removed. 348 * @return This builder. 349 */ 350 public Builder removeProhibitedAttribute(String attributeNameOrOID) { 351 this.prohibitedAttributeOIDs.remove(attributeNameOrOID); 352 return this; 353 } 354 355 /** 356 * Removes the provided required attribute in the list of attribute 357 * types that entries subject to this DIT content rule must contain. 358 * 359 * @param attributeNameOrOID 360 * The provided required attribute name or OID to be removed. 361 * @return This builder. 362 */ 363 public Builder removeRequiredAttribute(String attributeNameOrOID) { 364 this.requiredAttributeOIDs.remove(attributeNameOrOID); 365 return this; 366 } 367 368 /** 369 * Adds the provided attribute to the list of attribute types that 370 * entries subject to this DIT content rule must contain. 371 * 372 * @param attributeNamesOrOIDs 373 * The list of required attribute names or OIDs. 374 * @return This builder. 375 */ 376 public Builder requiredAttributes(final Collection<String> attributeNamesOrOIDs) { 377 this.requiredAttributeOIDs.addAll(attributeNamesOrOIDs); 378 return this; 379 } 380 381 /** 382 * Adds the provided attribute to the list of attribute types that 383 * entries subject to this DIT content rule must contain. 384 * 385 * @param attributeNamesOrOIDs 386 * The list of required attribute names or OIDs. 387 * @return This builder. 388 */ 389 public Builder requiredAttributes(final String... attributeNamesOrOIDs) { 390 this.requiredAttributeOIDs.addAll(asList(attributeNamesOrOIDs)); 391 return this; 392 } 393 394 /** 395 * Sets the structural class OID which uniquely identifies this DIT 396 * content rule. 397 * 398 * @param strucuralClassOID 399 * The numeric OID. 400 * @return This builder. 401 */ 402 public Builder structuralClassOID(String strucuralClassOID) { 403 this.structuralClassOID = strucuralClassOID; 404 return this; 405 } 406 407 } 408 409 /** The structural objectclass for this DIT content rule. */ 410 private final String structuralClassOID; 411 412 /** The set of user defined names for this definition. */ 413 private final List<String> names; 414 415 /** Indicates whether this definition is declared "obsolete". */ 416 private final boolean isObsolete; 417 418 /** 419 * The set of auxiliary objectclasses that entries with this content 420 * rule may contain, in a mapping between the objectclass and the 421 * user-defined name for that class. 422 */ 423 private final Set<String> auxiliaryClassOIDs; 424 425 /** The set of optional attribute types for this DIT content rule. */ 426 private final Set<String> optionalAttributeOIDs; 427 428 /** The set of prohibited attribute types for this DIT content rule. */ 429 private final Set<String> prohibitedAttributeOIDs; 430 431 /** The set of required attribute types for this DIT content rule. */ 432 private final Set<String> requiredAttributeOIDs; 433 434 private ObjectClass structuralClass; 435 private Set<ObjectClass> auxiliaryClasses = Collections.emptySet(); 436 private Set<AttributeType> optionalAttributes = Collections.emptySet(); 437 private Set<AttributeType> prohibitedAttributes = Collections.emptySet(); 438 private Set<AttributeType> requiredAttributes = Collections.emptySet(); 439 440 private DITContentRule(final Builder builder) { 441 super(builder); 442 Reject.ifNull(builder.structuralClassOID); 443 444 structuralClassOID = builder.structuralClassOID; 445 names = unmodifiableCopyOfList(builder.names); 446 isObsolete = builder.isObsolete; 447 auxiliaryClassOIDs = unmodifiableCopyOfSet(builder.auxiliaryClassOIDs); 448 optionalAttributeOIDs = unmodifiableCopyOfSet(builder.optionalAttributeOIDs); 449 prohibitedAttributeOIDs = unmodifiableCopyOfSet(builder.prohibitedAttributeOIDs); 450 requiredAttributeOIDs = unmodifiableCopyOfSet(builder.requiredAttributeOIDs); 451 } 452 453 /** 454 * Returns {@code true} if the provided object is a DIT content rule having 455 * the same structural object class OID as this DIT content rule. 456 * 457 * @param o 458 * The object to be compared. 459 * @return {@code true} if the provided object is a DIT content rule having 460 * the same numeric OID as this DIT content rule. 461 */ 462 @Override 463 public boolean equals(final Object o) { 464 if (this == o) { 465 return true; 466 } else if (o instanceof DITContentRule) { 467 final DITContentRule other = (DITContentRule) o; 468 return structuralClassOID.equals(other.structuralClassOID); 469 } else { 470 return false; 471 } 472 } 473 474 /** 475 * Returns an unmodifiable set containing the auxiliary objectclasses that 476 * may be used for entries associated with this DIT content rule. 477 * 478 * @return An unmodifiable set containing the auxiliary objectclasses that 479 * may be used for entries associated with this DIT content rule. 480 */ 481 public Set<ObjectClass> getAuxiliaryClasses() { 482 return auxiliaryClasses; 483 } 484 485 /** 486 * Returns the name or structural class OID for this schema definition. If 487 * it has one or more names, then the primary name will be returned. If it 488 * does not have any names, then the OID will be returned. 489 * 490 * @return The name or OID for this schema definition. 491 */ 492 public String getNameOrOID() { 493 if (names.isEmpty()) { 494 return structuralClassOID; 495 } 496 return names.get(0); 497 } 498 499 /** 500 * Returns an unmodifiable list containing the user-defined names that may 501 * be used to reference this schema definition. 502 * 503 * @return Returns an unmodifiable list containing the user-defined names 504 * that may be used to reference this schema definition. 505 */ 506 public List<String> getNames() { 507 return names; 508 } 509 510 /** 511 * Returns an unmodifiable set containing the optional attributes for this 512 * DIT content rule. 513 * 514 * @return An unmodifiable set containing the optional attributes for this 515 * DIT content rule. 516 */ 517 public Set<AttributeType> getOptionalAttributes() { 518 return optionalAttributes; 519 } 520 521 /** 522 * Returns an unmodifiable set containing the prohibited attributes for this 523 * DIT content rule. 524 * 525 * @return An unmodifiable set containing the prohibited attributes for this 526 * DIT content rule. 527 */ 528 public Set<AttributeType> getProhibitedAttributes() { 529 return prohibitedAttributes; 530 } 531 532 /** 533 * Returns an unmodifiable set containing the required attributes for this 534 * DIT content rule. 535 * 536 * @return An unmodifiable set containing the required attributes for this 537 * DIT content rule. 538 */ 539 public Set<AttributeType> getRequiredAttributes() { 540 return requiredAttributes; 541 } 542 543 /** 544 * Returns the structural objectclass for this DIT content rule. 545 * 546 * @return The structural objectclass for this DIT content rule. 547 */ 548 public ObjectClass getStructuralClass() { 549 return structuralClass; 550 } 551 552 /** 553 * Returns the structural class OID for this schema definition. 554 * 555 * @return The structural class OID for this schema definition. 556 */ 557 public String getStructuralClassOID() { 558 return structuralClassOID; 559 } 560 561 /** 562 * Returns the hash code for this DIT content rule. It will be calculated as 563 * the hash code of the structural object class OID. 564 * 565 * @return The hash code for this DIT content rule. 566 */ 567 @Override 568 public int hashCode() { 569 return structuralClassOID.hashCode(); 570 } 571 572 /** 573 * Indicates whether this schema definition has the specified name. 574 * 575 * @param name 576 * The name for which to make the determination. 577 * @return <code>true</code> if the specified name is assigned to this 578 * schema definition, or <code>false</code> if not. 579 */ 580 public boolean hasName(final String name) { 581 for (final String n : names) { 582 if (n.equalsIgnoreCase(name)) { 583 return true; 584 } 585 } 586 return false; 587 } 588 589 /** 590 * Indicates whether this schema definition has the specified name or 591 * structural class OID. 592 * 593 * @param value 594 * The value for which to make the determination. 595 * @return <code>true</code> if the provided value matches the OID or one of 596 * the names assigned to this schema definition, or 597 * <code>false</code> if not. 598 */ 599 public boolean hasNameOrOID(final String value) { 600 return hasName(value) || structuralClassOID.equals(value); 601 } 602 603 /** 604 * Indicates whether this schema definition is declared "obsolete". 605 * 606 * @return <code>true</code> if this schema definition is declared 607 * "obsolete", or <code>false</code> if not. 608 */ 609 public boolean isObsolete() { 610 return isObsolete; 611 } 612 613 /** 614 * Indicates whether the provided attribute type is included in the optional 615 * attribute list for this DIT content rule. 616 * 617 * @param attributeType 618 * The attribute type for which to make the determination. 619 * @return <code>true</code> if the provided attribute type is optional for 620 * this DIT content rule, or <code>false</code> if not. 621 */ 622 public boolean isOptional(final AttributeType attributeType) { 623 return optionalAttributes.contains(attributeType); 624 } 625 626 /** 627 * Indicates whether the provided attribute type is included in the required 628 * attribute list for this DIT content rule. 629 * 630 * @param attributeType 631 * The attribute type for which to make the determination. 632 * @return <code>true</code> if the provided attribute type is required by 633 * this DIT content rule, or <code>false</code> if not. 634 */ 635 public boolean isRequired(final AttributeType attributeType) { 636 return requiredAttributes.contains(attributeType); 637 } 638 639 /** 640 * Indicates whether the provided attribute type is in the list of required 641 * or optional attributes for this DIT content rule. 642 * 643 * @param attributeType 644 * The attribute type for which to make the determination. 645 * @return <code>true</code> if the provided attribute type is required or 646 * allowed for this DIT content rule, or <code>false</code> if it is 647 * not. 648 */ 649 public boolean isRequiredOrOptional(final AttributeType attributeType) { 650 return isRequired(attributeType) || isOptional(attributeType); 651 } 652 653 @Override 654 void toStringContent(final StringBuilder buffer) { 655 buffer.append(structuralClassOID); 656 657 if (!names.isEmpty()) { 658 final Iterator<String> iterator = names.iterator(); 659 660 final String firstName = iterator.next(); 661 if (iterator.hasNext()) { 662 buffer.append(" NAME ( '"); 663 buffer.append(firstName); 664 665 while (iterator.hasNext()) { 666 buffer.append("' '"); 667 buffer.append(iterator.next()); 668 } 669 670 buffer.append("' )"); 671 } else { 672 buffer.append(" NAME '"); 673 buffer.append(firstName); 674 buffer.append("'"); 675 } 676 } 677 678 appendDescription(buffer); 679 680 if (isObsolete) { 681 buffer.append(" OBSOLETE"); 682 } 683 684 if (!auxiliaryClassOIDs.isEmpty()) { 685 final Iterator<String> iterator = auxiliaryClassOIDs.iterator(); 686 687 final String firstClass = iterator.next(); 688 if (iterator.hasNext()) { 689 buffer.append(" AUX ("); 690 buffer.append(firstClass); 691 692 while (iterator.hasNext()) { 693 buffer.append(" $ "); 694 buffer.append(iterator.next()); 695 } 696 697 buffer.append(" )"); 698 } else { 699 buffer.append(" AUX "); 700 buffer.append(firstClass); 701 } 702 } 703 704 if (!requiredAttributeOIDs.isEmpty()) { 705 final Iterator<String> iterator = requiredAttributeOIDs.iterator(); 706 707 final String firstName = iterator.next(); 708 if (iterator.hasNext()) { 709 buffer.append(" MUST ( "); 710 buffer.append(firstName); 711 712 while (iterator.hasNext()) { 713 buffer.append(" $ "); 714 buffer.append(iterator.next()); 715 } 716 717 buffer.append(" )"); 718 } else { 719 buffer.append(" MUST "); 720 buffer.append(firstName); 721 } 722 } 723 724 if (!optionalAttributeOIDs.isEmpty()) { 725 final Iterator<String> iterator = optionalAttributeOIDs.iterator(); 726 727 final String firstName = iterator.next(); 728 if (iterator.hasNext()) { 729 buffer.append(" MAY ( "); 730 buffer.append(firstName); 731 732 while (iterator.hasNext()) { 733 buffer.append(" $ "); 734 buffer.append(iterator.next()); 735 } 736 737 buffer.append(" )"); 738 } else { 739 buffer.append(" MAY "); 740 buffer.append(firstName); 741 } 742 } 743 744 if (!prohibitedAttributeOIDs.isEmpty()) { 745 final Iterator<String> iterator = prohibitedAttributeOIDs.iterator(); 746 747 final String firstName = iterator.next(); 748 if (iterator.hasNext()) { 749 buffer.append(" NOT ( "); 750 buffer.append(firstName); 751 752 while (iterator.hasNext()) { 753 buffer.append(" $ "); 754 buffer.append(iterator.next()); 755 } 756 757 buffer.append(" )"); 758 } else { 759 buffer.append(" NOT "); 760 buffer.append(firstName); 761 } 762 } 763 } 764 765 void validate(final Schema schema, final List<LocalizableMessage> warnings) 766 throws SchemaException { 767 // Get the objectclass with the specified OID. If it does not exist 768 // or is not structural, then fail. 769 if (structuralClassOID != null) { 770 try { 771 structuralClass = schema.getObjectClass(structuralClassOID); 772 } catch (final UnknownSchemaElementException e) { 773 final LocalizableMessage message = 774 ERR_ATTR_SYNTAX_DCR_UNKNOWN_STRUCTURAL_CLASS1.get(getNameOrOID(), 775 structuralClassOID); 776 throw new SchemaException(message, e); 777 } 778 if (structuralClass.getObjectClassType() != ObjectClassType.STRUCTURAL) { 779 final LocalizableMessage message = 780 ERR_ATTR_SYNTAX_DCR_STRUCTURAL_CLASS_NOT_STRUCTURAL1.get(getNameOrOID(), 781 structuralClass.getNameOrOID(), structuralClass 782 .getObjectClassType().toString()); 783 warnings.add(message); 784 } 785 } 786 787 if (!auxiliaryClassOIDs.isEmpty()) { 788 auxiliaryClasses = new HashSet<>(auxiliaryClassOIDs.size()); 789 ObjectClass objectClass; 790 for (final String oid : auxiliaryClassOIDs) { 791 try { 792 objectClass = schema.getObjectClass(oid); 793 } catch (final UnknownSchemaElementException e) { 794 // This isn't good because it is an unknown auxiliary class. 795 final LocalizableMessage message = 796 ERR_ATTR_SYNTAX_DCR_UNKNOWN_AUXILIARY_CLASS1.get(getNameOrOID(), oid); 797 throw new SchemaException(message, e); 798 } 799 if (objectClass.getObjectClassType() != ObjectClassType.AUXILIARY) { 800 // This isn't good because it isn't an auxiliary class. 801 final LocalizableMessage message = 802 ERR_ATTR_SYNTAX_DCR_AUXILIARY_CLASS_NOT_AUXILIARY1.get(getNameOrOID(), 803 structuralClass.getOID(), structuralClass.getObjectClassType() 804 .toString()); 805 throw new SchemaException(message); 806 } 807 auxiliaryClasses.add(objectClass); 808 } 809 } 810 811 if (!requiredAttributeOIDs.isEmpty()) { 812 requiredAttributes = 813 getAttributeTypes(schema, requiredAttributeOIDs, ERR_ATTR_SYNTAX_DCR_UNKNOWN_REQUIRED_ATTR1); 814 } 815 816 if (!optionalAttributeOIDs.isEmpty()) { 817 optionalAttributes = 818 getAttributeTypes(schema, optionalAttributeOIDs, ERR_ATTR_SYNTAX_DCR_UNKNOWN_OPTIONAL_ATTR1); 819 } 820 821 if (!prohibitedAttributeOIDs.isEmpty()) { 822 prohibitedAttributes = 823 getAttributeTypes(schema, prohibitedAttributeOIDs, ERR_ATTR_SYNTAX_DCR_UNKNOWN_PROHIBITED_ATTR1); 824 } 825 826 // Make sure that none of the prohibited attributes is required by 827 // the structural or any of the auxiliary classes. 828 for (final AttributeType t : prohibitedAttributes) { 829 if (structuralClass.isRequired(t)) { 830 final LocalizableMessage message = 831 ERR_ATTR_SYNTAX_DCR_PROHIBITED_REQUIRED_BY_STRUCTURAL.get(getNameOrOID(), t 832 .getNameOrOID(), structuralClass.getNameOrOID()); 833 throw new SchemaException(message); 834 } 835 836 for (final ObjectClass oc : auxiliaryClasses) { 837 if (oc.isRequired(t)) { 838 final LocalizableMessage message = 839 ERR_ATTR_SYNTAX_DCR_PROHIBITED_REQUIRED_BY_AUXILIARY.get( 840 getNameOrOID(), t.getNameOrOID(), oc.getNameOrOID()); 841 throw new SchemaException(message); 842 } 843 } 844 } 845 846 auxiliaryClasses = Collections.unmodifiableSet(auxiliaryClasses); 847 optionalAttributes = Collections.unmodifiableSet(optionalAttributes); 848 prohibitedAttributes = Collections.unmodifiableSet(prohibitedAttributes); 849 requiredAttributes = Collections.unmodifiableSet(requiredAttributes); 850 } 851 852 private Set<AttributeType> getAttributeTypes(final Schema schema, Set<String> oids, Arg2<Object, Object> errorMsg) 853 throws SchemaException { 854 Set<AttributeType> attrTypes = new HashSet<>(oids.size()); 855 for (final String oid : oids) { 856 try { 857 attrTypes.add(schema.getAttributeType(oid)); 858 } catch (final UnknownSchemaElementException e) { 859 // This isn't good because it means that the DIT content rule 860 // requires an attribute type that we don't know anything about. 861 throw new SchemaException(errorMsg.get(getNameOrOID(), oid), e); 862 } 863 } 864 return attrTypes; 865 } 866}