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