001/* 002 * Copyright 2007-2017 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2008-2017 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.matchingrules; 022 023 024 025import java.io.Serializable; 026 027import com.unboundid.asn1.ASN1OctetString; 028import com.unboundid.ldap.sdk.LDAPException; 029import com.unboundid.ldap.sdk.schema.AttributeTypeDefinition; 030import com.unboundid.ldap.sdk.schema.Schema; 031import com.unboundid.ldap.sdk.unboundidds.jsonfilter. 032 JSONObjectExactMatchingRule; 033import com.unboundid.util.Extensible; 034import com.unboundid.util.ThreadSafety; 035import com.unboundid.util.ThreadSafetyLevel; 036 037import static com.unboundid.util.StaticUtils.*; 038 039 040 041/** 042 * This class defines the API for an LDAP matching rule, which may be used to 043 * determine whether two values are equal to each other, and to normalize values 044 * so that they may be more easily compared. 045 */ 046@Extensible() 047@ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE) 048public abstract class MatchingRule 049 implements Serializable 050{ 051 /** 052 * The substring element type used for subInitial substring assertion 053 * components. 054 */ 055 public static final byte SUBSTRING_TYPE_SUBINITIAL = (byte) 0x80; 056 057 058 059 /** 060 * The substring element type used for subAny substring assertion components. 061 */ 062 public static final byte SUBSTRING_TYPE_SUBANY = (byte) 0x81; 063 064 065 066 /** 067 * The substring element type used for subFinal substring assertion 068 * components. 069 */ 070 public static final byte SUBSTRING_TYPE_SUBFINAL = (byte) 0x82; 071 072 073 074 /** 075 * The serial version UID for this serializable class. 076 */ 077 private static final long serialVersionUID = 6050276733546358513L; 078 079 080 081 /** 082 * Creates a new instance of this matching rule. 083 */ 084 protected MatchingRule() 085 { 086 // No implementation is required. 087 } 088 089 090 091 /** 092 * Retrieves the name for this matching rule when used to perform equality 093 * matching, if appropriate. 094 * 095 * @return The name for this matching rule when used to perform equality 096 * matching, or {@code null} if this matching rule is not intended 097 * to be used for equality matching. 098 */ 099 public abstract String getEqualityMatchingRuleName(); 100 101 102 103 /** 104 * Retrieves the OID for this matching rule when used to perform equality 105 * matching, if appropriate. 106 * 107 * @return The OID for this matching rule when used to perform equality 108 * matching, or {@code null} if this matching rule is not intended 109 * to be used for equality matching. 110 */ 111 public abstract String getEqualityMatchingRuleOID(); 112 113 114 115 /** 116 * Retrieves the name for this matching rule when used to perform equality 117 * matching if defined, or the OID if no name is available. 118 * 119 * @return The name or OID for this matching rule when used to perform 120 * equality matching, or {@code null} if this matching rule cannot 121 * be used to perform equality matching. 122 */ 123 public String getEqualityMatchingRuleNameOrOID() 124 { 125 final String name = getEqualityMatchingRuleName(); 126 if (name == null) 127 { 128 return getEqualityMatchingRuleOID(); 129 } 130 else 131 { 132 return name; 133 } 134 } 135 136 137 138 /** 139 * Retrieves the name for this matching rule when used to perform ordering 140 * matching, if appropriate. 141 * 142 * @return The name for this matching rule when used to perform ordering 143 * matching, or {@code null} if this matching rule is not intended 144 * to be used for ordering matching. 145 */ 146 public abstract String getOrderingMatchingRuleName(); 147 148 149 150 /** 151 * Retrieves the OID for this matching rule when used to perform ordering 152 * matching, if appropriate. 153 * 154 * @return The OID for this matching rule when used to perform ordering 155 * matching, or {@code null} if this matching rule is not intended 156 * to be used for ordering matching. 157 */ 158 public abstract String getOrderingMatchingRuleOID(); 159 160 161 162 /** 163 * Retrieves the name for this matching rule when used to perform ordering 164 * matching if defined, or the OID if no name is available. 165 * 166 * @return The name or OID for this matching rule when used to perform 167 * ordering matching, or {@code null} if this matching rule cannot 168 * be used to perform equality matching. 169 */ 170 public String getOrderingMatchingRuleNameOrOID() 171 { 172 final String name = getOrderingMatchingRuleName(); 173 if (name == null) 174 { 175 return getOrderingMatchingRuleOID(); 176 } 177 else 178 { 179 return name; 180 } 181 } 182 183 184 185 /** 186 * Retrieves the name for this matching rule when used to perform substring 187 * matching, if appropriate. 188 * 189 * @return The name for this matching rule when used to perform substring 190 * matching, or {@code null} if this matching rule is not intended 191 * to be used for substring matching. 192 */ 193 public abstract String getSubstringMatchingRuleName(); 194 195 196 197 /** 198 * Retrieves the OID for this matching rule when used to perform substring 199 * matching, if appropriate. 200 * 201 * @return The OID for this matching rule when used to perform substring 202 * matching, or {@code null} if this matching rule is not intended 203 * to be used for substring matching. 204 */ 205 public abstract String getSubstringMatchingRuleOID(); 206 207 208 209 /** 210 * Retrieves the name for this matching rule when used to perform substring 211 * matching if defined, or the OID if no name is available. 212 * 213 * @return The name or OID for this matching rule when used to perform 214 * substring matching, or {@code null} if this matching rule cannot 215 * be used to perform equality matching. 216 */ 217 public String getSubstringMatchingRuleNameOrOID() 218 { 219 final String name = getSubstringMatchingRuleName(); 220 if (name == null) 221 { 222 return getSubstringMatchingRuleOID(); 223 } 224 else 225 { 226 return name; 227 } 228 } 229 230 231 232 /** 233 * Indicates whether the provided values are equal to each other, according to 234 * the constraints of this matching rule. 235 * 236 * @param value1 The first value for which to make the determination. 237 * @param value2 The second value for which to make the determination. 238 * 239 * @return {@code true} if the provided values are considered equal, or 240 * {@code false} if not. 241 * 242 * @throws LDAPException If a problem occurs while making the determination, 243 * or if this matching rule does not support equality 244 * matching. 245 */ 246 public abstract boolean valuesMatch(ASN1OctetString value1, 247 ASN1OctetString value2) 248 throws LDAPException; 249 250 251 252 /** 253 * Indicates whether the provided value matches the given substring assertion, 254 * according to the constraints of this matching rule. 255 * 256 * @param value The value for which to make the determination. 257 * @param subInitial The subInitial portion of the substring assertion, or 258 * {@code null} if there is no subInitial element. 259 * @param subAny The subAny elements of the substring assertion, or 260 * {@code null} if there are no subAny elements. 261 * @param subFinal The subFinal portion of the substring assertion, or 262 * {@code null} if there is no subFinal element. 263 * 264 * @return {@code true} if the provided value matches the substring 265 * assertion, or {@code false} if not. 266 * 267 * @throws LDAPException If a problem occurs while making the determination, 268 * or if this matching rule does not support substring 269 * matching. 270 */ 271 public abstract boolean matchesSubstring(ASN1OctetString value, 272 ASN1OctetString subInitial, 273 ASN1OctetString[] subAny, 274 ASN1OctetString subFinal) 275 throws LDAPException; 276 277 278 279 /** 280 * Compares the provided values to determine their relative order in a sorted 281 * list. 282 * 283 * @param value1 The first value to compare. 284 * @param value2 The second value to compare. 285 * 286 * @return A negative value if {@code value1} should come before 287 * {@code value2} in a sorted list, a positive value if 288 * {@code value1} should come after {@code value2} in a sorted list, 289 * or zero if the values are equal or there is no distinction between 290 * their orders in a sorted list. 291 * 292 * @throws LDAPException If a problem occurs while making the determination, 293 * or if this matching rule does not support ordering 294 * matching. 295 */ 296 public abstract int compareValues(ASN1OctetString value1, 297 ASN1OctetString value2) 298 throws LDAPException; 299 300 301 302 /** 303 * Normalizes the provided value for easier matching. 304 * 305 * @param value The value to be normalized. 306 * 307 * @return The normalized form of the provided value. 308 * 309 * @throws LDAPException If a problem occurs while normalizing the provided 310 * value. 311 */ 312 public abstract ASN1OctetString normalize(ASN1OctetString value) 313 throws LDAPException; 314 315 316 317 /** 318 * Normalizes the provided value for use as part of a substring assertion. 319 * 320 * @param value The value to be normalized for use as part of a 321 * substring assertion. 322 * @param substringType The substring assertion component type for the 323 * provided value. It should be one of 324 * {@code SUBSTRING_TYPE_SUBINITIAL}, 325 * {@code SUBSTRING_TYPE_SUBANY}, or 326 * {@code SUBSTRING_TYPE_SUBFINAL}. 327 * 328 * @return The normalized form of the provided value. 329 * 330 * @throws LDAPException If a problem occurs while normalizing the provided 331 * value. 332 */ 333 public abstract ASN1OctetString normalizeSubstring(ASN1OctetString value, 334 byte substringType) 335 throws LDAPException; 336 337 338 339 /** 340 * Attempts to select the appropriate matching rule to use for equality 341 * matching against the specified attribute. If an appropriate matching rule 342 * cannot be determined, then the default equality matching rule will be 343 * selected. 344 * 345 * @param attrName The name of the attribute to examine in the provided 346 * schema. 347 * @param schema The schema to examine to make the appropriate 348 * determination. If this is {@code null}, then the default 349 * equality matching rule will be selected. 350 * 351 * @return The selected matching rule. 352 */ 353 public static MatchingRule selectEqualityMatchingRule(final String attrName, 354 final Schema schema) 355 { 356 return selectEqualityMatchingRule(attrName, null, schema); 357 } 358 359 360 361 /** 362 * Attempts to select the appropriate matching rule to use for equality 363 * matching against the specified attribute. If an appropriate matching rule 364 * cannot be determined, then the default equality matching rule will be 365 * selected. 366 * 367 * @param attrName The name of the attribute to examine in the provided 368 * schema. It may be {@code null} if the matching rule 369 * should be selected using the matching rule ID. 370 * @param ruleID The OID of the desired matching rule. It may be 371 * {@code null} if the matching rule should be selected only 372 * using the attribute name. If a rule ID is provided, then 373 * it will be the only criteria used to select the matching 374 * rule. 375 * @param schema The schema to examine to make the appropriate 376 * determination. If this is {@code null} and no rule ID 377 * was provided, then the default equality matching rule 378 * will be selected. 379 * 380 * @return The selected matching rule. 381 */ 382 public static MatchingRule selectEqualityMatchingRule(final String attrName, 383 final String ruleID, final Schema schema) 384 { 385 if (ruleID != null) 386 { 387 return selectEqualityMatchingRule(ruleID); 388 } 389 390 if ((attrName == null) || (schema == null)) 391 { 392 return getDefaultEqualityMatchingRule(); 393 } 394 395 final AttributeTypeDefinition attrType = schema.getAttributeType(attrName); 396 if (attrType == null) 397 { 398 return getDefaultEqualityMatchingRule(); 399 } 400 401 final String mrName = attrType.getEqualityMatchingRule(schema); 402 if (mrName != null) 403 { 404 return selectEqualityMatchingRule(mrName); 405 } 406 407 final String syntaxOID = attrType.getBaseSyntaxOID(schema); 408 if (syntaxOID != null) 409 { 410 return selectMatchingRuleForSyntax(syntaxOID); 411 } 412 413 return getDefaultEqualityMatchingRule(); 414 } 415 416 417 418 /** 419 * Attempts to select the appropriate matching rule to use for equality 420 * matching using the specified matching rule. If an appropriate matching 421 * rule cannot be determined, then the default equality matching rule will be 422 * selected. 423 * 424 * @param ruleID The name or OID of the desired matching rule. 425 * 426 * @return The selected matching rule. 427 */ 428 public static MatchingRule selectEqualityMatchingRule(final String ruleID) 429 { 430 if ((ruleID == null) || (ruleID.length() == 0)) 431 { 432 return getDefaultEqualityMatchingRule(); 433 } 434 435 final String lowerName = toLowerCase(ruleID); 436 if (lowerName.equals(BooleanMatchingRule.LOWER_EQUALITY_RULE_NAME) || 437 lowerName.equals(BooleanMatchingRule.EQUALITY_RULE_OID)) 438 { 439 return BooleanMatchingRule.getInstance(); 440 } 441 else if (lowerName.equals( 442 CaseExactStringMatchingRule.LOWER_EQUALITY_RULE_NAME) || 443 lowerName.equals(CaseExactStringMatchingRule.EQUALITY_RULE_OID) || 444 lowerName.equals("caseexactia5match") || 445 lowerName.equals("1.3.6.1.4.1.1466.109.114.1")) 446 { 447 return CaseExactStringMatchingRule.getInstance(); 448 } 449 else if (lowerName.equals( 450 CaseIgnoreListMatchingRule.LOWER_EQUALITY_RULE_NAME) || 451 lowerName.equals(CaseIgnoreListMatchingRule.EQUALITY_RULE_OID)) 452 { 453 return CaseIgnoreListMatchingRule.getInstance(); 454 } 455 else if (lowerName.equals( 456 CaseIgnoreStringMatchingRule.LOWER_EQUALITY_RULE_NAME) || 457 lowerName.equals(CaseIgnoreStringMatchingRule.EQUALITY_RULE_OID) || 458 lowerName.equals("caseignoreia5match") || 459 lowerName.equals("1.3.6.1.4.1.1466.109.114.2")) 460 { 461 return CaseIgnoreStringMatchingRule.getInstance(); 462 } 463 else if (lowerName.equals( 464 DistinguishedNameMatchingRule.LOWER_EQUALITY_RULE_NAME) || 465 lowerName.equals( 466 DistinguishedNameMatchingRule.EQUALITY_RULE_OID) || 467 lowerName.equals("uniquemembermatch") || 468 lowerName.equals("2.5.13.23")) 469 { 470 // NOTE -- Technically uniqueMember should use a name and optional UID 471 // matching rule, but the SDK doesn't currently provide one and the 472 // distinguished name matching rule should be sufficient the vast 473 // majority of the time. 474 return DistinguishedNameMatchingRule.getInstance(); 475 } 476 else if (lowerName.equals( 477 GeneralizedTimeMatchingRule.LOWER_EQUALITY_RULE_NAME) || 478 lowerName.equals(GeneralizedTimeMatchingRule.EQUALITY_RULE_OID)) 479 { 480 return GeneralizedTimeMatchingRule.getInstance(); 481 } 482 else if (lowerName.equals(IntegerMatchingRule.LOWER_EQUALITY_RULE_NAME) || 483 lowerName.equals(IntegerMatchingRule.EQUALITY_RULE_OID)) 484 { 485 return IntegerMatchingRule.getInstance(); 486 } 487 else if (lowerName.equals( 488 NumericStringMatchingRule.LOWER_EQUALITY_RULE_NAME) || 489 lowerName.equals(NumericStringMatchingRule.EQUALITY_RULE_OID)) 490 { 491 return NumericStringMatchingRule.getInstance(); 492 } 493 else if (lowerName.equals( 494 OctetStringMatchingRule.LOWER_EQUALITY_RULE_NAME) || 495 lowerName.equals(OctetStringMatchingRule.EQUALITY_RULE_OID)) 496 { 497 return OctetStringMatchingRule.getInstance(); 498 } 499 else if (lowerName.equals( 500 TelephoneNumberMatchingRule.LOWER_EQUALITY_RULE_NAME) || 501 lowerName.equals(TelephoneNumberMatchingRule.EQUALITY_RULE_OID)) 502 { 503 return TelephoneNumberMatchingRule.getInstance(); 504 } 505 else if (lowerName.equals("jsonobjectexactmatch") || 506 lowerName.equals("1.3.6.1.4.1.30221.2.4.12")) 507 { 508 return JSONObjectExactMatchingRule.getInstance(); 509 } 510 else 511 { 512 return getDefaultEqualityMatchingRule(); 513 } 514 } 515 516 517 518 /** 519 * Retrieves the default matching rule that will be used for equality matching 520 * if no other matching rule is specified or available. The rule returned 521 * will perform case-ignore string matching. 522 * 523 * @return The default matching rule that will be used for equality matching 524 * if no other matching rule is specified or available. 525 */ 526 public static MatchingRule getDefaultEqualityMatchingRule() 527 { 528 return CaseIgnoreStringMatchingRule.getInstance(); 529 } 530 531 532 533 /** 534 * Attempts to select the appropriate matching rule to use for ordering 535 * matching against the specified attribute. If an appropriate matching rule 536 * cannot be determined, then the default ordering matching rule will be 537 * selected. 538 * 539 * @param attrName The name of the attribute to examine in the provided 540 * schema. 541 * @param schema The schema to examine to make the appropriate 542 * determination. If this is {@code null}, then the default 543 * ordering matching rule will be selected. 544 * 545 * @return The selected matching rule. 546 */ 547 public static MatchingRule selectOrderingMatchingRule(final String attrName, 548 final Schema schema) 549 { 550 return selectOrderingMatchingRule(attrName, null, schema); 551 } 552 553 554 555 /** 556 * Attempts to select the appropriate matching rule to use for ordering 557 * matching against the specified attribute. If an appropriate matching rule 558 * cannot be determined, then the default ordering matching rule will be 559 * selected. 560 * 561 * @param attrName The name of the attribute to examine in the provided 562 * schema. It may be {@code null} if the matching rule 563 * should be selected using the matching rule ID. 564 * @param ruleID The OID of the desired matching rule. It may be 565 * {@code null} if the matching rule should be selected only 566 * using the attribute name. If a rule ID is provided, then 567 * it will be the only criteria used to select the matching 568 * rule. 569 * @param schema The schema to examine to make the appropriate 570 * determination. If this is {@code null} and no rule ID 571 * was provided, then the default ordering matching rule 572 * will be selected. 573 * 574 * @return The selected matching rule. 575 */ 576 public static MatchingRule selectOrderingMatchingRule(final String attrName, 577 final String ruleID, 578 final Schema schema) 579 { 580 if (ruleID != null) 581 { 582 return selectOrderingMatchingRule(ruleID); 583 } 584 585 if ((attrName == null) || (schema == null)) 586 { 587 return getDefaultOrderingMatchingRule(); 588 } 589 590 final AttributeTypeDefinition attrType = schema.getAttributeType(attrName); 591 if (attrType == null) 592 { 593 return getDefaultOrderingMatchingRule(); 594 } 595 596 final String mrName = attrType.getOrderingMatchingRule(schema); 597 if (mrName != null) 598 { 599 return selectOrderingMatchingRule(mrName); 600 } 601 602 final String syntaxOID = attrType.getBaseSyntaxOID(schema); 603 if (syntaxOID != null) 604 { 605 return selectMatchingRuleForSyntax(syntaxOID); 606 } 607 608 return getDefaultOrderingMatchingRule(); 609 } 610 611 612 613 /** 614 * Attempts to select the appropriate matching rule to use for ordering 615 * matching using the specified matching rule. If an appropriate matching 616 * rule cannot be determined, then the default ordering matching rule will be 617 * selected. 618 * 619 * @param ruleID The name or OID of the desired matching rule. 620 * 621 * @return The selected matching rule. 622 */ 623 public static MatchingRule selectOrderingMatchingRule(final String ruleID) 624 { 625 if ((ruleID == null) || (ruleID.length() == 0)) 626 { 627 return getDefaultOrderingMatchingRule(); 628 } 629 630 final String lowerName = toLowerCase(ruleID); 631 if (lowerName.equals( 632 CaseExactStringMatchingRule.LOWER_ORDERING_RULE_NAME) || 633 lowerName.equals(CaseExactStringMatchingRule.ORDERING_RULE_OID)) 634 { 635 return CaseExactStringMatchingRule.getInstance(); 636 } 637 else if (lowerName.equals( 638 CaseIgnoreStringMatchingRule.LOWER_ORDERING_RULE_NAME) || 639 lowerName.equals(CaseIgnoreStringMatchingRule.ORDERING_RULE_OID)) 640 { 641 return CaseIgnoreStringMatchingRule.getInstance(); 642 } 643 else if (lowerName.equals( 644 GeneralizedTimeMatchingRule.LOWER_ORDERING_RULE_NAME) || 645 lowerName.equals(GeneralizedTimeMatchingRule.ORDERING_RULE_OID)) 646 { 647 return GeneralizedTimeMatchingRule.getInstance(); 648 } 649 else if (lowerName.equals(IntegerMatchingRule.LOWER_ORDERING_RULE_NAME) || 650 lowerName.equals(IntegerMatchingRule.ORDERING_RULE_OID)) 651 { 652 return IntegerMatchingRule.getInstance(); 653 } 654 else if (lowerName.equals( 655 NumericStringMatchingRule.LOWER_ORDERING_RULE_NAME) || 656 lowerName.equals(NumericStringMatchingRule.ORDERING_RULE_OID)) 657 { 658 return NumericStringMatchingRule.getInstance(); 659 } 660 else if (lowerName.equals( 661 OctetStringMatchingRule.LOWER_ORDERING_RULE_NAME) || 662 lowerName.equals(OctetStringMatchingRule.ORDERING_RULE_OID)) 663 { 664 return OctetStringMatchingRule.getInstance(); 665 } 666 else 667 { 668 return getDefaultOrderingMatchingRule(); 669 } 670 } 671 672 673 674 /** 675 * Retrieves the default matching rule that will be used for ordering matching 676 * if no other matching rule is specified or available. The rule returned 677 * will perform case-ignore string matching. 678 * 679 * @return The default matching rule that will be used for ordering matching 680 * if no other matching rule is specified or available. 681 */ 682 public static MatchingRule getDefaultOrderingMatchingRule() 683 { 684 return CaseIgnoreStringMatchingRule.getInstance(); 685 } 686 687 688 689 /** 690 * Attempts to select the appropriate matching rule to use for substring 691 * matching against the specified attribute. If an appropriate matching rule 692 * cannot be determined, then the default substring matching rule will be 693 * selected. 694 * 695 * @param attrName The name of the attribute to examine in the provided 696 * schema. 697 * @param schema The schema to examine to make the appropriate 698 * determination. If this is {@code null}, then the default 699 * substring matching rule will be selected. 700 * 701 * @return The selected matching rule. 702 */ 703 public static MatchingRule selectSubstringMatchingRule(final String attrName, 704 final Schema schema) 705 { 706 return selectSubstringMatchingRule(attrName, null, schema); 707 } 708 709 710 711 /** 712 * Attempts to select the appropriate matching rule to use for substring 713 * matching against the specified attribute. If an appropriate matching rule 714 * cannot be determined, then the default substring matching rule will be 715 * selected. 716 * 717 * @param attrName The name of the attribute to examine in the provided 718 * schema. It may be {@code null} if the matching rule 719 * should be selected using the matching rule ID. 720 * @param ruleID The OID of the desired matching rule. It may be 721 * {@code null} if the matching rule should be selected only 722 * using the attribute name. If a rule ID is provided, then 723 * it will be the only criteria used to select the matching 724 * rule. 725 * @param schema The schema to examine to make the appropriate 726 * determination. If this is {@code null} and no rule ID 727 * was provided, then the default substring matching rule 728 * will be selected. 729 * 730 * @return The selected matching rule. 731 */ 732 public static MatchingRule selectSubstringMatchingRule(final String attrName, 733 final String ruleID, 734 final Schema schema) 735 { 736 if (ruleID != null) 737 { 738 return selectSubstringMatchingRule(ruleID); 739 } 740 741 if ((attrName == null) || (schema == null)) 742 { 743 return getDefaultSubstringMatchingRule(); 744 } 745 746 final AttributeTypeDefinition attrType = schema.getAttributeType(attrName); 747 if (attrType == null) 748 { 749 return getDefaultSubstringMatchingRule(); 750 } 751 752 final String mrName = attrType.getSubstringMatchingRule(schema); 753 if (mrName != null) 754 { 755 return selectSubstringMatchingRule(mrName); 756 } 757 758 final String syntaxOID = attrType.getBaseSyntaxOID(schema); 759 if (syntaxOID != null) 760 { 761 return selectMatchingRuleForSyntax(syntaxOID); 762 } 763 764 return getDefaultSubstringMatchingRule(); 765 } 766 767 768 769 /** 770 * Attempts to select the appropriate matching rule to use for substring 771 * matching using the specified matching rule. If an appropriate matching 772 * rule cannot be determined, then the default substring matching rule will be 773 * selected. 774 * 775 * @param ruleID The name or OID of the desired matching rule. 776 * 777 * @return The selected matching rule. 778 */ 779 public static MatchingRule selectSubstringMatchingRule(final String ruleID) 780 { 781 if ((ruleID == null) || (ruleID.length() == 0)) 782 { 783 return getDefaultSubstringMatchingRule(); 784 } 785 786 final String lowerName = toLowerCase(ruleID); 787 if (lowerName.equals( 788 CaseExactStringMatchingRule.LOWER_SUBSTRING_RULE_NAME) || 789 lowerName.equals(CaseExactStringMatchingRule.SUBSTRING_RULE_OID) || 790 lowerName.equals("caseexactia5substringsmatch")) 791 { 792 return CaseExactStringMatchingRule.getInstance(); 793 } 794 else if (lowerName.equals( 795 CaseIgnoreListMatchingRule.LOWER_SUBSTRING_RULE_NAME) || 796 lowerName.equals(CaseIgnoreListMatchingRule.SUBSTRING_RULE_OID)) 797 { 798 return CaseIgnoreListMatchingRule.getInstance(); 799 } 800 else if (lowerName.equals( 801 CaseIgnoreStringMatchingRule.LOWER_SUBSTRING_RULE_NAME) || 802 lowerName.equals( 803 CaseIgnoreStringMatchingRule.SUBSTRING_RULE_OID) || 804 lowerName.equals("caseignoreia5substringsmatch") || 805 lowerName.equals("1.3.6.1.4.1.1466.109.114.3")) 806 { 807 return CaseIgnoreStringMatchingRule.getInstance(); 808 } 809 else if (lowerName.equals( 810 NumericStringMatchingRule.LOWER_SUBSTRING_RULE_NAME) || 811 lowerName.equals(NumericStringMatchingRule.SUBSTRING_RULE_OID)) 812 { 813 return NumericStringMatchingRule.getInstance(); 814 } 815 else if (lowerName.equals( 816 OctetStringMatchingRule.LOWER_SUBSTRING_RULE_NAME) || 817 lowerName.equals(OctetStringMatchingRule.SUBSTRING_RULE_OID)) 818 { 819 return OctetStringMatchingRule.getInstance(); 820 } 821 else if (lowerName.equals( 822 TelephoneNumberMatchingRule.LOWER_SUBSTRING_RULE_NAME) || 823 lowerName.equals(TelephoneNumberMatchingRule.SUBSTRING_RULE_OID)) 824 { 825 return TelephoneNumberMatchingRule.getInstance(); 826 } 827 else 828 { 829 return getDefaultSubstringMatchingRule(); 830 } 831 } 832 833 834 835 /** 836 * Retrieves the default matching rule that will be used for substring 837 * matching if no other matching rule is specified or available. The rule 838 * returned will perform case-ignore string matching. 839 * 840 * @return The default matching rule that will be used for substring matching 841 * if no other matching rule is specified or available. 842 */ 843 public static MatchingRule getDefaultSubstringMatchingRule() 844 { 845 return CaseIgnoreStringMatchingRule.getInstance(); 846 } 847 848 849 850 /** 851 * Attempts to select the appropriate matching rule for use with the syntax 852 * with the specified OID. If an appropriate matching rule cannot be 853 * determined, then the case-ignore string matching rule will be selected. 854 * 855 * @param syntaxOID The OID of the attribute syntax for which to make the 856 * determination. 857 * 858 * @return The selected matching rule. 859 */ 860 public static MatchingRule selectMatchingRuleForSyntax(final String syntaxOID) 861 { 862 if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.7")) 863 { 864 return BooleanMatchingRule.getInstance(); 865 } 866 else if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.41")) // Postal addr. 867 { 868 return CaseIgnoreListMatchingRule.getInstance(); 869 } 870 else if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.12") || 871 syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.34")) // name&optional UID 872 { 873 return DistinguishedNameMatchingRule.getInstance(); 874 } 875 else if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.24") || 876 syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.53")) // UTC time 877 { 878 return GeneralizedTimeMatchingRule.getInstance(); 879 } 880 else if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.27")) 881 { 882 return IntegerMatchingRule.getInstance(); 883 } 884 else if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.36")) 885 { 886 return NumericStringMatchingRule.getInstance(); 887 } 888 else if (syntaxOID.equals("1.3.6.1.4.1.4203.1.1.2") || // auth password 889 syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.5") || // binary 890 syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.8") || // certificate 891 syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.9") || // cert list 892 syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.10") || // cert pair 893 syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.28") || // JPEG 894 syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.40")) // octet string 895 { 896 return OctetStringMatchingRule.getInstance(); 897 } 898 else if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.50")) 899 { 900 return TelephoneNumberMatchingRule.getInstance(); 901 } 902 else if (syntaxOID.equals("1.3.6.1.4.1.30221.2.3.4")) // JSON object exact 903 { 904 return JSONObjectExactMatchingRule.getInstance(); 905 } 906 else 907 { 908 return CaseIgnoreStringMatchingRule.getInstance(); 909 } 910 } 911}