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