001/* 002 * Copyright 2007-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2007-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2007-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk.schema; 037 038 039 040import java.util.ArrayList; 041import java.util.Collection; 042import java.util.Collections; 043import java.util.Map; 044import java.util.LinkedHashMap; 045 046import com.unboundid.ldap.sdk.LDAPException; 047import com.unboundid.ldap.sdk.ResultCode; 048import com.unboundid.util.NotMutable; 049import com.unboundid.util.NotNull; 050import com.unboundid.util.Nullable; 051import com.unboundid.util.StaticUtils; 052import com.unboundid.util.ThreadSafety; 053import com.unboundid.util.ThreadSafetyLevel; 054import com.unboundid.util.Validator; 055 056import static com.unboundid.ldap.sdk.schema.SchemaMessages.*; 057 058 059 060/** 061 * This class provides a data structure that describes an LDAP DIT content rule 062 * schema element. 063 */ 064@NotMutable() 065@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 066public final class DITContentRuleDefinition 067 extends SchemaElement 068{ 069 /** 070 * The serial version UID for this serializable class. 071 */ 072 private static final long serialVersionUID = 3224440505307817586L; 073 074 075 076 // Indicates whether this DIT content rule is declared obsolete. 077 private final boolean isObsolete; 078 079 // The set of extensions for this DIT content rule. 080 @NotNull private final Map<String,String[]> extensions; 081 082 // The description for this DIT content rule. 083 @Nullable private final String description; 084 085 // The string representation of this DIT content rule. 086 @NotNull private final String ditContentRuleString; 087 088 // The OID of the structural object class with which this DIT content rule is 089 // associated. 090 @NotNull private final String oid; 091 092 // The names/OIDs of the allowed auxiliary classes. 093 @NotNull private final String[] auxiliaryClasses; 094 095 // The set of names for this DIT content rule. 096 @NotNull private final String[] names; 097 098 // The names/OIDs of the optional attributes. 099 @NotNull private final String[] optionalAttributes; 100 101 // The names/OIDs of the prohibited attributes. 102 @NotNull private final String[] prohibitedAttributes; 103 104 // The names/OIDs of the required attributes. 105 @NotNull private final String[] requiredAttributes; 106 107 108 109 /** 110 * Creates a new DIT content rule from the provided string representation. 111 * 112 * @param s The string representation of the DIT content rule to create, 113 * using the syntax described in RFC 4512 section 4.1.6. It must 114 * not be {@code null}. 115 * 116 * @throws LDAPException If the provided string cannot be decoded as a DIT 117 * content rule definition. 118 */ 119 public DITContentRuleDefinition(@NotNull final String s) 120 throws LDAPException 121 { 122 Validator.ensureNotNull(s); 123 124 ditContentRuleString = s.trim(); 125 126 // The first character must be an opening parenthesis. 127 final int length = ditContentRuleString.length(); 128 if (length == 0) 129 { 130 throw new LDAPException(ResultCode.DECODING_ERROR, 131 ERR_DCR_DECODE_EMPTY.get()); 132 } 133 else if (ditContentRuleString.charAt(0) != '(') 134 { 135 throw new LDAPException(ResultCode.DECODING_ERROR, 136 ERR_DCR_DECODE_NO_OPENING_PAREN.get( 137 ditContentRuleString)); 138 } 139 140 141 // Skip over any spaces until we reach the start of the OID, then read the 142 // OID until we find the next space. 143 int pos = skipSpaces(ditContentRuleString, 1, length); 144 145 StringBuilder buffer = new StringBuilder(); 146 pos = readOID(ditContentRuleString, pos, length, buffer); 147 oid = buffer.toString(); 148 149 150 // Technically, DIT content elements are supposed to appear in a specific 151 // order, but we'll be lenient and allow remaining elements to come in any 152 // order. 153 final ArrayList<String> nameList = new ArrayList<>(5); 154 final ArrayList<String> reqAttrs = new ArrayList<>(10); 155 final ArrayList<String> optAttrs = new ArrayList<>(10); 156 final ArrayList<String> notAttrs = new ArrayList<>(10); 157 final ArrayList<String> auxOCs = new ArrayList<>(10); 158 final Map<String,String[]> exts = 159 new LinkedHashMap<>(StaticUtils.computeMapCapacity(5)); 160 Boolean obsolete = null; 161 String descr = null; 162 163 while (true) 164 { 165 // Skip over any spaces until we find the next element. 166 pos = skipSpaces(ditContentRuleString, pos, length); 167 168 // Read until we find the next space or the end of the string. Use that 169 // token to figure out what to do next. 170 final int tokenStartPos = pos; 171 while ((pos < length) && (ditContentRuleString.charAt(pos) != ' ')) 172 { 173 pos++; 174 } 175 176 // It's possible that the token could be smashed right up against the 177 // closing parenthesis. If that's the case, then extract just the token 178 // and handle the closing parenthesis the next time through. 179 String token = ditContentRuleString.substring(tokenStartPos, pos); 180 if ((token.length() > 1) && (token.endsWith(")"))) 181 { 182 token = token.substring(0, token.length() - 1); 183 pos--; 184 } 185 186 final String lowerToken = StaticUtils.toLowerCase(token); 187 if (lowerToken.equals(")")) 188 { 189 // This indicates that we're at the end of the value. There should not 190 // be any more closing characters. 191 if (pos < length) 192 { 193 throw new LDAPException(ResultCode.DECODING_ERROR, 194 ERR_DCR_DECODE_CLOSE_NOT_AT_END.get( 195 ditContentRuleString)); 196 } 197 break; 198 } 199 else if (lowerToken.equals("name")) 200 { 201 if (nameList.isEmpty()) 202 { 203 pos = skipSpaces(ditContentRuleString, pos, length); 204 pos = readQDStrings(ditContentRuleString, pos, length, token, 205 nameList); 206 } 207 else 208 { 209 throw new LDAPException(ResultCode.DECODING_ERROR, 210 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get( 211 ditContentRuleString, "NAME")); 212 } 213 } 214 else if (lowerToken.equals("desc")) 215 { 216 if (descr == null) 217 { 218 pos = skipSpaces(ditContentRuleString, pos, length); 219 220 buffer = new StringBuilder(); 221 pos = readQDString(ditContentRuleString, pos, length, token, buffer); 222 descr = buffer.toString(); 223 } 224 else 225 { 226 throw new LDAPException(ResultCode.DECODING_ERROR, 227 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get( 228 ditContentRuleString, "DESC")); 229 } 230 } 231 else if (lowerToken.equals("obsolete")) 232 { 233 if (obsolete == null) 234 { 235 obsolete = true; 236 } 237 else 238 { 239 throw new LDAPException(ResultCode.DECODING_ERROR, 240 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get( 241 ditContentRuleString, "OBSOLETE")); 242 } 243 } 244 else if (lowerToken.equals("aux")) 245 { 246 if (auxOCs.isEmpty()) 247 { 248 pos = skipSpaces(ditContentRuleString, pos, length); 249 pos = readOIDs(ditContentRuleString, pos, length, token, auxOCs); 250 } 251 else 252 { 253 throw new LDAPException(ResultCode.DECODING_ERROR, 254 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get( 255 ditContentRuleString, "AUX")); 256 } 257 } 258 else if (lowerToken.equals("must")) 259 { 260 if (reqAttrs.isEmpty()) 261 { 262 pos = skipSpaces(ditContentRuleString, pos, length); 263 pos = readOIDs(ditContentRuleString, pos, length, token, reqAttrs); 264 } 265 else 266 { 267 throw new LDAPException(ResultCode.DECODING_ERROR, 268 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get( 269 ditContentRuleString, "MUST")); 270 } 271 } 272 else if (lowerToken.equals("may")) 273 { 274 if (optAttrs.isEmpty()) 275 { 276 pos = skipSpaces(ditContentRuleString, pos, length); 277 pos = readOIDs(ditContentRuleString, pos, length, token, optAttrs); 278 } 279 else 280 { 281 throw new LDAPException(ResultCode.DECODING_ERROR, 282 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get( 283 ditContentRuleString, "MAY")); 284 } 285 } 286 else if (lowerToken.equals("not")) 287 { 288 if (notAttrs.isEmpty()) 289 { 290 pos = skipSpaces(ditContentRuleString, pos, length); 291 pos = readOIDs(ditContentRuleString, pos, length, token, notAttrs); 292 } 293 else 294 { 295 throw new LDAPException(ResultCode.DECODING_ERROR, 296 ERR_DCR_DECODE_MULTIPLE_ELEMENTS.get( 297 ditContentRuleString, "NOT")); 298 } 299 } 300 else if (lowerToken.startsWith("x-")) 301 { 302 pos = skipSpaces(ditContentRuleString, pos, length); 303 304 final ArrayList<String> valueList = new ArrayList<>(5); 305 pos = readQDStrings(ditContentRuleString, pos, length, token, 306 valueList); 307 308 final String[] values = new String[valueList.size()]; 309 valueList.toArray(values); 310 311 if (exts.containsKey(token)) 312 { 313 throw new LDAPException(ResultCode.DECODING_ERROR, 314 ERR_DCR_DECODE_DUP_EXT.get( 315 ditContentRuleString, token)); 316 } 317 318 exts.put(token, values); 319 } 320 else 321 { 322 throw new LDAPException(ResultCode.DECODING_ERROR, 323 ERR_DCR_DECODE_DUP_EXT.get( 324 ditContentRuleString, token)); 325 } 326 } 327 328 description = descr; 329 330 names = new String[nameList.size()]; 331 nameList.toArray(names); 332 333 auxiliaryClasses = new String[auxOCs.size()]; 334 auxOCs.toArray(auxiliaryClasses); 335 336 requiredAttributes = new String[reqAttrs.size()]; 337 reqAttrs.toArray(requiredAttributes); 338 339 optionalAttributes = new String[optAttrs.size()]; 340 optAttrs.toArray(optionalAttributes); 341 342 prohibitedAttributes = new String[notAttrs.size()]; 343 notAttrs.toArray(prohibitedAttributes); 344 345 isObsolete = (obsolete != null); 346 347 extensions = Collections.unmodifiableMap(exts); 348 } 349 350 351 352 /** 353 * Creates a new DIT content rule with the provided information. 354 * 355 * @param oid The OID for the structural object class with 356 * which this DIT content rule is associated. 357 * It must not be {@code null}. 358 * @param name The name for this DIT content rule. It may 359 * be {@code null} if the DIT content rule 360 * should only be referenced by OID. 361 * @param description The description for this DIT content rule. 362 * It may be {@code null} if there is no 363 * description. 364 * @param auxiliaryClasses The names/OIDs of the auxiliary object 365 * classes that may be present in entries 366 * containing this DIT content rule. 367 * @param requiredAttributes The names/OIDs of the attributes which must 368 * be present in entries containing this DIT 369 * content rule. 370 * @param optionalAttributes The names/OIDs of the attributes which may be 371 * present in entries containing this DIT 372 * content rule. 373 * @param prohibitedAttributes The names/OIDs of the attributes which may 374 * not be present in entries containing this DIT 375 * content rule. 376 * @param extensions The set of extensions for this DIT content 377 * rule. It may be {@code null} or empty if 378 * there should not be any extensions. 379 */ 380 public DITContentRuleDefinition(@NotNull final String oid, 381 @Nullable final String name, 382 @Nullable final String description, 383 @Nullable final String[] auxiliaryClasses, 384 @Nullable final String[] requiredAttributes, 385 @Nullable final String[] optionalAttributes, 386 @Nullable final String[] prohibitedAttributes, 387 @Nullable final Map<String,String[]> extensions) 388 { 389 this(oid, ((name == null) ? null : new String[] { name }), description, 390 false, auxiliaryClasses, requiredAttributes, optionalAttributes, 391 prohibitedAttributes, extensions); 392 } 393 394 395 396 /** 397 * Creates a new DIT content rule with the provided information. 398 * 399 * @param oid The OID for the structural object class with 400 * which this DIT content rule is associated. 401 * It must not be {@code null}. 402 * @param name The name for this DIT content rule. It may 403 * be {@code null} if the DIT content rule 404 * should only be referenced by OID. 405 * @param description The description for this DIT content rule. 406 * It may be {@code null} if there is no 407 * description. 408 * @param auxiliaryClasses The names/OIDs of the auxiliary object 409 * classes that may be present in entries 410 * containing this DIT content rule. 411 * @param requiredAttributes The names/OIDs of the attributes which must 412 * be present in entries containing this DIT 413 * content rule. 414 * @param optionalAttributes The names/OIDs of the attributes which may be 415 * present in entries containing this DIT 416 * content rule. 417 * @param prohibitedAttributes The names/OIDs of the attributes which may 418 * not be present in entries containing this DIT 419 * content rule. 420 * @param extensions The set of extensions for this DIT content 421 * rule. It may be {@code null} or empty if 422 * there should not be any extensions. 423 */ 424 public DITContentRuleDefinition(@NotNull final String oid, 425 @Nullable final String name, 426 @Nullable final String description, 427 @Nullable final Collection<String> auxiliaryClasses, 428 @Nullable final Collection<String> requiredAttributes, 429 @Nullable final Collection<String> optionalAttributes, 430 @Nullable final Collection<String> prohibitedAttributes, 431 @Nullable final Map<String,String[]> extensions) 432 { 433 this(oid, ((name == null) ? null : new String[] { name }), description, 434 false, toArray(auxiliaryClasses), toArray(requiredAttributes), 435 toArray(optionalAttributes), toArray(prohibitedAttributes), 436 extensions); 437 } 438 439 440 441 /** 442 * Creates a new DIT content rule with the provided information. 443 * 444 * @param oid The OID for the structural object class with 445 * which this DIT content rule is associated. 446 * It must not be {@code null}. 447 * @param names The set of names for this DIT content rule. 448 * It may be {@code null} or empty if the DIT 449 * content rule should only be referenced by 450 * OID. 451 * @param description The description for this DIT content rule. 452 * It may be {@code null} if there is no 453 * description. 454 * @param isObsolete Indicates whether this DIT content rule is 455 * declared obsolete. 456 * @param auxiliaryClasses The names/OIDs of the auxiliary object 457 * classes that may be present in entries 458 * containing this DIT content rule. 459 * @param requiredAttributes The names/OIDs of the attributes which must 460 * be present in entries containing this DIT 461 * content rule. 462 * @param optionalAttributes The names/OIDs of the attributes which may be 463 * present in entries containing this DIT 464 * content rule. 465 * @param prohibitedAttributes The names/OIDs of the attributes which may 466 * not be present in entries containing this DIT 467 * content rule. 468 * @param extensions The set of extensions for this DIT content 469 * rule. It may be {@code null} or empty if 470 * there should not be any extensions. 471 */ 472 public DITContentRuleDefinition(@NotNull final String oid, 473 @Nullable final String[] names, 474 @Nullable final String description, 475 final boolean isObsolete, 476 @Nullable final String[] auxiliaryClasses, 477 @Nullable final String[] requiredAttributes, 478 @Nullable final String[] optionalAttributes, 479 @Nullable final String[] prohibitedAttributes, 480 @Nullable final Map<String,String[]> extensions) 481 { 482 Validator.ensureNotNull(oid); 483 484 this.oid = oid; 485 this.isObsolete = isObsolete; 486 this.description = description; 487 488 if (names == null) 489 { 490 this.names = StaticUtils.NO_STRINGS; 491 } 492 else 493 { 494 this.names = names; 495 } 496 497 if (auxiliaryClasses == null) 498 { 499 this.auxiliaryClasses = StaticUtils.NO_STRINGS; 500 } 501 else 502 { 503 this.auxiliaryClasses = auxiliaryClasses; 504 } 505 506 if (requiredAttributes == null) 507 { 508 this.requiredAttributes = StaticUtils.NO_STRINGS; 509 } 510 else 511 { 512 this.requiredAttributes = requiredAttributes; 513 } 514 515 if (optionalAttributes == null) 516 { 517 this.optionalAttributes = StaticUtils.NO_STRINGS; 518 } 519 else 520 { 521 this.optionalAttributes = optionalAttributes; 522 } 523 524 if (prohibitedAttributes == null) 525 { 526 this.prohibitedAttributes = StaticUtils.NO_STRINGS; 527 } 528 else 529 { 530 this.prohibitedAttributes = prohibitedAttributes; 531 } 532 533 if (extensions == null) 534 { 535 this.extensions = Collections.emptyMap(); 536 } 537 else 538 { 539 this.extensions = Collections.unmodifiableMap(extensions); 540 } 541 542 final StringBuilder buffer = new StringBuilder(); 543 createDefinitionString(buffer); 544 ditContentRuleString = buffer.toString(); 545 } 546 547 548 549 /** 550 * Constructs a string representation of this DIT content rule definition in 551 * the provided buffer. 552 * 553 * @param buffer The buffer in which to construct a string representation of 554 * this DIT content rule definition. 555 */ 556 private void createDefinitionString(@NotNull final StringBuilder buffer) 557 { 558 buffer.append("( "); 559 buffer.append(oid); 560 561 if (names.length == 1) 562 { 563 buffer.append(" NAME '"); 564 buffer.append(names[0]); 565 buffer.append('\''); 566 } 567 else if (names.length > 1) 568 { 569 buffer.append(" NAME ("); 570 for (final String name : names) 571 { 572 buffer.append(" '"); 573 buffer.append(name); 574 buffer.append('\''); 575 } 576 buffer.append(" )"); 577 } 578 579 if (description != null) 580 { 581 buffer.append(" DESC '"); 582 encodeValue(description, buffer); 583 buffer.append('\''); 584 } 585 586 if (isObsolete) 587 { 588 buffer.append(" OBSOLETE"); 589 } 590 591 if (auxiliaryClasses.length == 1) 592 { 593 buffer.append(" AUX "); 594 buffer.append(auxiliaryClasses[0]); 595 } 596 else if (auxiliaryClasses.length > 1) 597 { 598 buffer.append(" AUX ("); 599 for (int i=0; i < auxiliaryClasses.length; i++) 600 { 601 if (i >0) 602 { 603 buffer.append(" $ "); 604 } 605 else 606 { 607 buffer.append(' '); 608 } 609 buffer.append(auxiliaryClasses[i]); 610 } 611 buffer.append(" )"); 612 } 613 614 if (requiredAttributes.length == 1) 615 { 616 buffer.append(" MUST "); 617 buffer.append(requiredAttributes[0]); 618 } 619 else if (requiredAttributes.length > 1) 620 { 621 buffer.append(" MUST ("); 622 for (int i=0; i < requiredAttributes.length; i++) 623 { 624 if (i >0) 625 { 626 buffer.append(" $ "); 627 } 628 else 629 { 630 buffer.append(' '); 631 } 632 buffer.append(requiredAttributes[i]); 633 } 634 buffer.append(" )"); 635 } 636 637 if (optionalAttributes.length == 1) 638 { 639 buffer.append(" MAY "); 640 buffer.append(optionalAttributes[0]); 641 } 642 else if (optionalAttributes.length > 1) 643 { 644 buffer.append(" MAY ("); 645 for (int i=0; i < optionalAttributes.length; i++) 646 { 647 if (i > 0) 648 { 649 buffer.append(" $ "); 650 } 651 else 652 { 653 buffer.append(' '); 654 } 655 buffer.append(optionalAttributes[i]); 656 } 657 buffer.append(" )"); 658 } 659 660 if (prohibitedAttributes.length == 1) 661 { 662 buffer.append(" NOT "); 663 buffer.append(prohibitedAttributes[0]); 664 } 665 else if (prohibitedAttributes.length > 1) 666 { 667 buffer.append(" NOT ("); 668 for (int i=0; i < prohibitedAttributes.length; i++) 669 { 670 if (i > 0) 671 { 672 buffer.append(" $ "); 673 } 674 else 675 { 676 buffer.append(' '); 677 } 678 buffer.append(prohibitedAttributes[i]); 679 } 680 buffer.append(" )"); 681 } 682 683 for (final Map.Entry<String,String[]> e : extensions.entrySet()) 684 { 685 final String name = e.getKey(); 686 final String[] values = e.getValue(); 687 if (values.length == 1) 688 { 689 buffer.append(' '); 690 buffer.append(name); 691 buffer.append(" '"); 692 encodeValue(values[0], buffer); 693 buffer.append('\''); 694 } 695 else 696 { 697 buffer.append(' '); 698 buffer.append(name); 699 buffer.append(" ("); 700 for (final String value : values) 701 { 702 buffer.append(" '"); 703 encodeValue(value, buffer); 704 buffer.append('\''); 705 } 706 buffer.append(" )"); 707 } 708 } 709 710 buffer.append(" )"); 711 } 712 713 714 715 /** 716 * Retrieves the OID for the structural object class associated with this 717 * DIT content rule. 718 * 719 * @return The OID for the structural object class associated with this DIT 720 * content rule. 721 */ 722 @NotNull() 723 public String getOID() 724 { 725 return oid; 726 } 727 728 729 730 /** 731 * Retrieves the set of names for this DIT content rule. 732 * 733 * @return The set of names for this DIT content rule, or an empty array if 734 * it does not have any names. 735 */ 736 @NotNull() 737 public String[] getNames() 738 { 739 return names; 740 } 741 742 743 744 /** 745 * Retrieves the primary name that can be used to reference this DIT content 746 * rule. If one or more names are defined, then the first name will be used. 747 * Otherwise, the structural object class OID will be returned. 748 * 749 * @return The primary name that can be used to reference this DIT content 750 * rule. 751 */ 752 @NotNull() 753 public String getNameOrOID() 754 { 755 if (names.length == 0) 756 { 757 return oid; 758 } 759 else 760 { 761 return names[0]; 762 } 763 } 764 765 766 767 /** 768 * Indicates whether the provided string matches the OID or any of the names 769 * for this DIT content rule. 770 * 771 * @param s The string for which to make the determination. It must not be 772 * {@code null}. 773 * 774 * @return {@code true} if the provided string matches the OID or any of the 775 * names for this DIT content rule, or {@code false} if not. 776 */ 777 public boolean hasNameOrOID(@NotNull final String s) 778 { 779 for (final String name : names) 780 { 781 if (s.equalsIgnoreCase(name)) 782 { 783 return true; 784 } 785 } 786 787 return s.equalsIgnoreCase(oid); 788 } 789 790 791 792 /** 793 * Retrieves the description for this DIT content rule, if available. 794 * 795 * @return The description for this DIT content rule, or {@code null} if 796 * there is no description defined. 797 */ 798 @Nullable() 799 public String getDescription() 800 { 801 return description; 802 } 803 804 805 806 /** 807 * Indicates whether this DIT content rule is declared obsolete. 808 * 809 * @return {@code true} if this DIT content rule is declared obsolete, or 810 * {@code false} if it is not. 811 */ 812 public boolean isObsolete() 813 { 814 return isObsolete; 815 } 816 817 818 819 /** 820 * Retrieves the names or OIDs of the auxiliary object classes that may be 821 * present in entries containing the structural class for this DIT content 822 * rule. 823 * 824 * @return The names or OIDs of the auxiliary object classes that may be 825 * present in entries containing the structural class for this DIT 826 * content rule. 827 */ 828 @NotNull() 829 public String[] getAuxiliaryClasses() 830 { 831 return auxiliaryClasses; 832 } 833 834 835 836 /** 837 * Retrieves the names or OIDs of the attributes that are required to be 838 * present in entries containing the structural object class for this DIT 839 * content rule. 840 * 841 * @return The names or OIDs of the attributes that are required to be 842 * present in entries containing the structural object class for this 843 * DIT content rule, or an empty array if there are no required 844 * attributes. 845 */ 846 @NotNull() 847 public String[] getRequiredAttributes() 848 { 849 return requiredAttributes; 850 } 851 852 853 854 /** 855 * Retrieves the names or OIDs of the attributes that are optionally allowed 856 * to be present in entries containing the structural object class for this 857 * DIT content rule. 858 * 859 * @return The names or OIDs of the attributes that are optionally allowed to 860 * be present in entries containing the structural object class for 861 * this DIT content rule, or an empty array if there are no required 862 * attributes. 863 */ 864 @NotNull() 865 public String[] getOptionalAttributes() 866 { 867 return optionalAttributes; 868 } 869 870 871 872 /** 873 * Retrieves the names or OIDs of the attributes that are not allowed to be 874 * present in entries containing the structural object class for this DIT 875 * content rule. 876 * 877 * @return The names or OIDs of the attributes that are not allowed to be 878 * present in entries containing the structural object class for this 879 * DIT content rule, or an empty array if there are no required 880 * attributes. 881 */ 882 @NotNull() 883 public String[] getProhibitedAttributes() 884 { 885 return prohibitedAttributes; 886 } 887 888 889 890 /** 891 * Retrieves the set of extensions for this DIT content rule. They will be 892 * mapped from the extension name (which should start with "X-") to the set of 893 * values for that extension. 894 * 895 * @return The set of extensions for this DIT content rule. 896 */ 897 @NotNull() 898 public Map<String,String[]> getExtensions() 899 { 900 return extensions; 901 } 902 903 904 905 /** 906 * {@inheritDoc} 907 */ 908 @Override() 909 @NotNull() 910 public SchemaElementType getSchemaElementType() 911 { 912 return SchemaElementType.DIT_CONTENT_RULE; 913 } 914 915 916 917 /** 918 * {@inheritDoc} 919 */ 920 @Override() 921 public int hashCode() 922 { 923 return oid.hashCode(); 924 } 925 926 927 928 /** 929 * {@inheritDoc} 930 */ 931 @Override() 932 public boolean equals(@Nullable final Object o) 933 { 934 if (o == null) 935 { 936 return false; 937 } 938 939 if (o == this) 940 { 941 return true; 942 } 943 944 if (! (o instanceof DITContentRuleDefinition)) 945 { 946 return false; 947 } 948 949 final DITContentRuleDefinition d = (DITContentRuleDefinition) o; 950 return (oid.equals(d.oid) && 951 StaticUtils.stringsEqualIgnoreCaseOrderIndependent(names, d.names) && 952 StaticUtils.stringsEqualIgnoreCaseOrderIndependent(auxiliaryClasses, 953 d.auxiliaryClasses) && 954 StaticUtils.stringsEqualIgnoreCaseOrderIndependent(requiredAttributes, 955 d.requiredAttributes) && 956 StaticUtils.stringsEqualIgnoreCaseOrderIndependent(optionalAttributes, 957 d.optionalAttributes) && 958 StaticUtils.stringsEqualIgnoreCaseOrderIndependent( 959 prohibitedAttributes, d.prohibitedAttributes) && 960 StaticUtils.bothNullOrEqualIgnoreCase(description, d.description) && 961 (isObsolete == d.isObsolete) && 962 extensionsEqual(extensions, d.extensions)); 963 } 964 965 966 967 /** 968 * Retrieves a string representation of this DIT content rule definition, in 969 * the format described in RFC 4512 section 4.1.6. 970 * 971 * @return A string representation of this DIT content rule definition. 972 */ 973 @Override() 974 @NotNull() 975 public String toString() 976 { 977 return ditContentRuleString; 978 } 979}