All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.unboundid.ldap.matchingrules.MatchingRule Maven / Gradle / Ivy

/*
 * Copyright 2007-2017 UnboundID Corp.
 * All Rights Reserved.
 */
/*
 * Copyright (C) 2008-2017 UnboundID Corp.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License (GPLv2 only)
 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see .
 */
package com.unboundid.ldap.matchingrules;



import java.io.Serializable;
import java.lang.reflect.Method;

import com.unboundid.asn1.ASN1OctetString;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.schema.AttributeTypeDefinition;
import com.unboundid.ldap.sdk.schema.Schema;
import com.unboundid.util.Debug;
import com.unboundid.util.Extensible;
import com.unboundid.util.ThreadSafety;
import com.unboundid.util.ThreadSafetyLevel;

import static com.unboundid.util.StaticUtils.*;



/**
 * This class defines the API for an LDAP matching rule, which may be used to
 * determine whether two values are equal to each other, and to normalize values
 * so that they may be more easily compared.
 */
@Extensible()
@ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
public abstract class MatchingRule
       implements Serializable
{
  /**
   * The substring element type used for subInitial substring assertion
   * components.
   */
  public static final byte SUBSTRING_TYPE_SUBINITIAL = (byte) 0x80;



  /**
   * The substring element type used for subAny substring assertion components.
   */
  public static final byte SUBSTRING_TYPE_SUBANY = (byte) 0x81;



  /**
   * The substring element type used for subFinal substring assertion
   * components.
   */
  public static final byte SUBSTRING_TYPE_SUBFINAL = (byte) 0x82;



  /**
   * A reference to the jsonObjectExactMatch matching rule, if it has been
   * loaded.  This matching rule needs to be loaded via reflection because it's
   * only included in the Commercial Edition and isn't part of the Standard
   * Edition.
   */
  private static volatile MatchingRule jsonObjectExactMatchingRule = null;



  /**
   * The serial version UID for this serializable class.
   */
  private static final long serialVersionUID = 6050276733546358513L;



  /**
   * Creates a new instance of this matching rule.
   */
  protected MatchingRule()
  {
    // No implementation is required.
  }



  /**
   * Retrieves the name for this matching rule when used to perform equality
   * matching, if appropriate.
   *
   * @return  The name for this matching rule when used to perform equality
   *          matching, or {@code null} if this matching rule is not intended
   *          to be used for equality matching.
   */
  public abstract String getEqualityMatchingRuleName();



  /**
   * Retrieves the OID for this matching rule when used to perform equality
   * matching, if appropriate.
   *
   * @return  The OID for this matching rule when used to perform equality
   *          matching, or {@code null} if this matching rule is not intended
   *          to be used for equality matching.
   */
  public abstract String getEqualityMatchingRuleOID();



  /**
   * Retrieves the name for this matching rule when used to perform equality
   * matching if defined, or the OID if no name is available.
   *
   * @return  The name or OID for this matching rule when used to perform
   *          equality matching, or {@code null} if this matching rule cannot
   *          be used to perform equality matching.
   */
  public String getEqualityMatchingRuleNameOrOID()
  {
    final String name = getEqualityMatchingRuleName();
    if (name == null)
    {
      return getEqualityMatchingRuleOID();
    }
    else
    {
      return name;
    }
  }



  /**
   * Retrieves the name for this matching rule when used to perform ordering
   * matching, if appropriate.
   *
   * @return  The name for this matching rule when used to perform ordering
   *          matching, or {@code null} if this matching rule is not intended
   *          to be used for ordering matching.
   */
  public abstract String getOrderingMatchingRuleName();



  /**
   * Retrieves the OID for this matching rule when used to perform ordering
   * matching, if appropriate.
   *
   * @return  The OID for this matching rule when used to perform ordering
   *          matching, or {@code null} if this matching rule is not intended
   *          to be used for ordering matching.
   */
  public abstract String getOrderingMatchingRuleOID();



  /**
   * Retrieves the name for this matching rule when used to perform ordering
   * matching if defined, or the OID if no name is available.
   *
   * @return  The name or OID for this matching rule when used to perform
   *          ordering matching, or {@code null} if this matching rule cannot
   *          be used to perform equality matching.
   */
  public String getOrderingMatchingRuleNameOrOID()
  {
    final String name = getOrderingMatchingRuleName();
    if (name == null)
    {
      return getOrderingMatchingRuleOID();
    }
    else
    {
      return name;
    }
  }



  /**
   * Retrieves the name for this matching rule when used to perform substring
   * matching, if appropriate.
   *
   * @return  The name for this matching rule when used to perform substring
   *          matching, or {@code null} if this matching rule is not intended
   *          to be used for substring matching.
   */
  public abstract String getSubstringMatchingRuleName();



  /**
   * Retrieves the OID for this matching rule when used to perform substring
   * matching, if appropriate.
   *
   * @return  The OID for this matching rule when used to perform substring
   *          matching, or {@code null} if this matching rule is not intended
   *          to be used for substring matching.
   */
  public abstract String getSubstringMatchingRuleOID();



  /**
   * Retrieves the name for this matching rule when used to perform substring
   * matching if defined, or the OID if no name is available.
   *
   * @return  The name or OID for this matching rule when used to perform
   *          substring matching, or {@code null} if this matching rule cannot
   *          be used to perform equality matching.
   */
  public String getSubstringMatchingRuleNameOrOID()
  {
    final String name = getSubstringMatchingRuleName();
    if (name == null)
    {
      return getSubstringMatchingRuleOID();
    }
    else
    {
      return name;
    }
  }



  /**
   * Indicates whether the provided values are equal to each other, according to
   * the constraints of this matching rule.
   *
   * @param  value1  The first value for which to make the determination.
   * @param  value2  The second value for which to make the determination.
   *
   * @return  {@code true} if the provided values are considered equal, or
   *          {@code false} if not.
   *
   * @throws  LDAPException  If a problem occurs while making the determination,
   *                         or if this matching rule does not support equality
   *                         matching.
   */
  public abstract boolean valuesMatch(final ASN1OctetString value1,
                                      final ASN1OctetString value2)
         throws LDAPException;



  /**
   * Indicates whether the provided value matches the given substring assertion,
   * according to the constraints of this matching rule.
   *
   * @param  value       The value for which to make the determination.
   * @param  subInitial  The subInitial portion of the substring assertion, or
   *                     {@code null} if there is no subInitial element.
   * @param  subAny      The subAny elements of the substring assertion, or
   *                     {@code null} if there are no subAny elements.
   * @param  subFinal    The subFinal portion of the substring assertion, or
   *                     {@code null} if there is no subFinal element.
   *
   * @return  {@code true} if the provided value matches the substring
   *          assertion, or {@code false} if not.
   *
   * @throws  LDAPException  If a problem occurs while making the determination,
   *                         or if this matching rule does not support substring
   *                         matching.
   */
  public abstract boolean matchesSubstring(final ASN1OctetString value,
                                           final ASN1OctetString subInitial,
                                           final ASN1OctetString[] subAny,
                                           final ASN1OctetString subFinal)
         throws LDAPException;



  /**
   * Compares the provided values to determine their relative order in a sorted
   * list.
   *
   * @param  value1  The first value to compare.
   * @param  value2  The second value to compare.
   *
   * @return  A negative value if {@code value1} should come before
   *          {@code value2} in a sorted list, a positive value if
   *          {@code value1} should come after {@code value2} in a sorted list,
   *          or zero if the values are equal or there is no distinction between
   *          their orders in a sorted list.
   *
   * @throws  LDAPException  If a problem occurs while making the determination,
   *                         or if this matching rule does not support ordering
   *                         matching.
   */
  public abstract int compareValues(final ASN1OctetString value1,
                                    final ASN1OctetString value2)
         throws LDAPException;



  /**
   * Normalizes the provided value for easier matching.
   *
   * @param  value  The value to be normalized.
   *
   * @return  The normalized form of the provided value.
   *
   * @throws  LDAPException  If a problem occurs while normalizing the provided
   *                         value.
   */
  public abstract ASN1OctetString normalize(final ASN1OctetString value)
         throws LDAPException;



  /**
   * Normalizes the provided value for use as part of a substring assertion.
   *
   * @param  value          The value to be normalized for use as part of a
   *                        substring assertion.
   * @param  substringType  The substring assertion component type for the
   *                        provided value.  It should be one of
   *                        {@code SUBSTRING_TYPE_SUBINITIAL},
   *                        {@code SUBSTRING_TYPE_SUBANY}, or
   *                        {@code SUBSTRING_TYPE_SUBFINAL}.
   *
   * @return  The normalized form of the provided value.
   *
   * @throws  LDAPException  If a problem occurs while normalizing the provided
   *                         value.
   */
  public abstract ASN1OctetString normalizeSubstring(
                                       final ASN1OctetString value,
                                       final byte substringType)
         throws LDAPException;



  /**
   * Attempts to select the appropriate matching rule to use for equality
   * matching against the specified attribute.  If an appropriate matching rule
   * cannot be determined, then the default equality matching rule will be
   * selected.
   *
   * @param  attrName  The name of the attribute to examine in the provided
   *                   schema.
   * @param  schema    The schema to examine to make the appropriate
   *                   determination.  If this is {@code null}, then the default
   *                   equality matching rule will be selected.
   *
   * @return  The selected matching rule.
   */
  public static MatchingRule selectEqualityMatchingRule(final String attrName,
                                                        final Schema schema)
  {
    return selectEqualityMatchingRule(attrName, null, schema);
  }



  /**
   * Attempts to select the appropriate matching rule to use for equality
   * matching against the specified attribute.  If an appropriate matching rule
   * cannot be determined, then the default equality matching rule will be
   * selected.
   *
   * @param  attrName  The name of the attribute to examine in the provided
   *                   schema.  It may be {@code null} if the matching rule
   *                   should be selected using the matching rule ID.
   * @param  ruleID    The OID of the desired matching rule.  It may be
   *                   {@code null} if the matching rule should be selected only
   *                   using the attribute name.  If a rule ID is provided, then
   *                   it will be the only criteria used to select the matching
   *                   rule.
   * @param  schema    The schema to examine to make the appropriate
   *                   determination.  If this is {@code null} and no rule ID
   *                   was provided, then the default equality matching rule
   *                   will be selected.
   *
   * @return  The selected matching rule.
   */
  public static MatchingRule selectEqualityMatchingRule(final String attrName,
                                  final String ruleID, final Schema schema)
  {
    if (ruleID != null)
    {
      return selectEqualityMatchingRule(ruleID);
    }

    if ((attrName == null) || (schema == null))
    {
      return getDefaultEqualityMatchingRule();
    }

    final AttributeTypeDefinition attrType = schema.getAttributeType(attrName);
    if (attrType == null)
    {
      return getDefaultEqualityMatchingRule();
    }

    final String mrName = attrType.getEqualityMatchingRule(schema);
    if (mrName != null)
    {
      return selectEqualityMatchingRule(mrName);
    }

    final String syntaxOID = attrType.getBaseSyntaxOID(schema);
    if (syntaxOID != null)
    {
      return selectMatchingRuleForSyntax(syntaxOID);
    }

    return getDefaultEqualityMatchingRule();
  }



  /**
   * Attempts to select the appropriate matching rule to use for equality
   * matching using the specified matching rule.  If an appropriate matching
   * rule cannot be determined, then the default equality matching rule will be
   * selected.
   *
   * @param  ruleID  The name or OID of the desired matching rule.
   *
   * @return  The selected matching rule.
   */
  public static MatchingRule selectEqualityMatchingRule(final String ruleID)
  {
    if ((ruleID == null) || (ruleID.length() == 0))
    {
      return getDefaultEqualityMatchingRule();
    }

    final String lowerName = toLowerCase(ruleID);
    if (lowerName.equals(BooleanMatchingRule.LOWER_EQUALITY_RULE_NAME) ||
        lowerName.equals(BooleanMatchingRule.EQUALITY_RULE_OID))
    {
      return BooleanMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  CaseExactStringMatchingRule.LOWER_EQUALITY_RULE_NAME) ||
             lowerName.equals(CaseExactStringMatchingRule.EQUALITY_RULE_OID) ||
             lowerName.equals("caseexactia5match") ||
             lowerName.equals("1.3.6.1.4.1.1466.109.114.1"))
    {
      return CaseExactStringMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  CaseIgnoreListMatchingRule.LOWER_EQUALITY_RULE_NAME) ||
             lowerName.equals(CaseIgnoreListMatchingRule.EQUALITY_RULE_OID))
    {
      return CaseIgnoreListMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  CaseIgnoreStringMatchingRule.LOWER_EQUALITY_RULE_NAME) ||
             lowerName.equals(CaseIgnoreStringMatchingRule.EQUALITY_RULE_OID) ||
             lowerName.equals("caseignoreia5match") ||
             lowerName.equals("1.3.6.1.4.1.1466.109.114.2"))
    {
      return CaseIgnoreStringMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  DistinguishedNameMatchingRule.LOWER_EQUALITY_RULE_NAME) ||
             lowerName.equals(
                  DistinguishedNameMatchingRule.EQUALITY_RULE_OID) ||
             lowerName.equals("uniquemembermatch") ||
             lowerName.equals("2.5.13.23"))
    {
      // NOTE -- Technically uniqueMember should use a name and optional UID
      // matching rule, but the SDK doesn't currently provide one and the
      // distinguished name matching rule should be sufficient the vast
      // majority of the time.
      return DistinguishedNameMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  GeneralizedTimeMatchingRule.LOWER_EQUALITY_RULE_NAME) ||
             lowerName.equals(GeneralizedTimeMatchingRule.EQUALITY_RULE_OID))
    {
      return GeneralizedTimeMatchingRule.getInstance();
    }
    else if (lowerName.equals(IntegerMatchingRule.LOWER_EQUALITY_RULE_NAME) ||
             lowerName.equals(IntegerMatchingRule.EQUALITY_RULE_OID))
    {
      return IntegerMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  NumericStringMatchingRule.LOWER_EQUALITY_RULE_NAME) ||
             lowerName.equals(NumericStringMatchingRule.EQUALITY_RULE_OID))
    {
      return NumericStringMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  OctetStringMatchingRule.LOWER_EQUALITY_RULE_NAME) ||
             lowerName.equals(OctetStringMatchingRule.EQUALITY_RULE_OID))
    {
      return OctetStringMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  TelephoneNumberMatchingRule.LOWER_EQUALITY_RULE_NAME) ||
             lowerName.equals(TelephoneNumberMatchingRule.EQUALITY_RULE_OID))
    {
      return TelephoneNumberMatchingRule.getInstance();
    }
    else if (lowerName.equals("jsonobjectexactmatch") ||
             lowerName.equals("1.3.6.1.4.1.30221.2.4.12"))
    {
      return getJSONObjectExactMatchingRule();
    }
    else
    {
      return getDefaultEqualityMatchingRule();
    }
  }



  /**
   * Retrieves the default matching rule that will be used for equality matching
   * if no other matching rule is specified or available.  The rule returned
   * will perform case-ignore string matching.
   *
   * @return  The default matching rule that will be used for equality matching
   *          if no other matching rule is specified or available.
   */
  public static MatchingRule getDefaultEqualityMatchingRule()
  {
    return CaseIgnoreStringMatchingRule.getInstance();
  }



  /**
   * Attempts to select the appropriate matching rule to use for ordering
   * matching against the specified attribute.  If an appropriate matching rule
   * cannot be determined, then the default ordering matching rule will be
   * selected.
   *
   * @param  attrName  The name of the attribute to examine in the provided
   *                   schema.
   * @param  schema    The schema to examine to make the appropriate
   *                   determination.  If this is {@code null}, then the default
   *                   ordering matching rule will be selected.
   *
   * @return  The selected matching rule.
   */
  public static MatchingRule selectOrderingMatchingRule(final String attrName,
                                                        final Schema schema)
  {
    return selectOrderingMatchingRule(attrName, null, schema);
  }



  /**
   * Attempts to select the appropriate matching rule to use for ordering
   * matching against the specified attribute.  If an appropriate matching rule
   * cannot be determined, then the default ordering matching rule will be
   * selected.
   *
   * @param  attrName  The name of the attribute to examine in the provided
   *                   schema.  It may be {@code null} if the matching rule
   *                   should be selected using the matching rule ID.
   * @param  ruleID    The OID of the desired matching rule.  It may be
   *                   {@code null} if the matching rule should be selected only
   *                   using the attribute name.  If a rule ID is provided, then
   *                   it will be the only criteria used to select the matching
   *                   rule.
   * @param  schema    The schema to examine to make the appropriate
   *                   determination.  If this is {@code null} and no rule ID
   *                   was provided, then the default ordering matching rule
   *                   will be selected.
   *
   * @return  The selected matching rule.
   */
  public static MatchingRule selectOrderingMatchingRule(final String attrName,
                                                        final String ruleID,
                                                        final Schema schema)
  {
    if (ruleID != null)
    {
      return selectOrderingMatchingRule(ruleID);
    }

    if ((attrName == null) || (schema == null))
    {
      return getDefaultOrderingMatchingRule();
    }

    final AttributeTypeDefinition attrType = schema.getAttributeType(attrName);
    if (attrType == null)
    {
      return getDefaultOrderingMatchingRule();
    }

    final String mrName = attrType.getOrderingMatchingRule(schema);
    if (mrName != null)
    {
      return selectOrderingMatchingRule(mrName);
    }

    final String syntaxOID = attrType.getBaseSyntaxOID(schema);
    if (syntaxOID != null)
    {
      return selectMatchingRuleForSyntax(syntaxOID);
    }

    return getDefaultOrderingMatchingRule();
  }



  /**
   * Attempts to select the appropriate matching rule to use for ordering
   * matching using the specified matching rule.  If an appropriate matching
   * rule cannot be determined, then the default ordering matching rule will be
   * selected.
   *
   * @param  ruleID  The name or OID of the desired matching rule.
   *
   * @return  The selected matching rule.
   */
  public static MatchingRule selectOrderingMatchingRule(final String ruleID)
  {
    if ((ruleID == null) || (ruleID.length() == 0))
    {
      return getDefaultOrderingMatchingRule();
    }

    final String lowerName = toLowerCase(ruleID);
    if (lowerName.equals(
             CaseExactStringMatchingRule.LOWER_ORDERING_RULE_NAME) ||
        lowerName.equals(CaseExactStringMatchingRule.ORDERING_RULE_OID))
    {
      return CaseExactStringMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  CaseIgnoreStringMatchingRule.LOWER_ORDERING_RULE_NAME) ||
             lowerName.equals(CaseIgnoreStringMatchingRule.ORDERING_RULE_OID))
    {
      return CaseIgnoreStringMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  GeneralizedTimeMatchingRule.LOWER_ORDERING_RULE_NAME) ||
             lowerName.equals(GeneralizedTimeMatchingRule.ORDERING_RULE_OID))
    {
      return GeneralizedTimeMatchingRule.getInstance();
    }
    else if (lowerName.equals(IntegerMatchingRule.LOWER_ORDERING_RULE_NAME) ||
             lowerName.equals(IntegerMatchingRule.ORDERING_RULE_OID))
    {
      return IntegerMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  NumericStringMatchingRule.LOWER_ORDERING_RULE_NAME) ||
             lowerName.equals(NumericStringMatchingRule.ORDERING_RULE_OID))
    {
      return NumericStringMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  OctetStringMatchingRule.LOWER_ORDERING_RULE_NAME) ||
             lowerName.equals(OctetStringMatchingRule.ORDERING_RULE_OID))
    {
      return OctetStringMatchingRule.getInstance();
    }
    else
    {
      return getDefaultOrderingMatchingRule();
    }
  }



  /**
   * Retrieves the default matching rule that will be used for ordering matching
   * if no other matching rule is specified or available.  The rule returned
   * will perform case-ignore string matching.
   *
   * @return  The default matching rule that will be used for ordering matching
   *          if no other matching rule is specified or available.
   */
  public static MatchingRule getDefaultOrderingMatchingRule()
  {
    return CaseIgnoreStringMatchingRule.getInstance();
  }



  /**
   * Attempts to select the appropriate matching rule to use for substring
   * matching against the specified attribute.  If an appropriate matching rule
   * cannot be determined, then the default substring matching rule will be
   * selected.
   *
   * @param  attrName  The name of the attribute to examine in the provided
   *                   schema.
   * @param  schema    The schema to examine to make the appropriate
   *                   determination.  If this is {@code null}, then the default
   *                   substring matching rule will be selected.
   *
   * @return  The selected matching rule.
   */
  public static MatchingRule selectSubstringMatchingRule(final String attrName,
                                                         final Schema schema)
  {
    return selectSubstringMatchingRule(attrName, null, schema);
  }



  /**
   * Attempts to select the appropriate matching rule to use for substring
   * matching against the specified attribute.  If an appropriate matching rule
   * cannot be determined, then the default substring matching rule will be
   * selected.
   *
   * @param  attrName  The name of the attribute to examine in the provided
   *                   schema.  It may be {@code null} if the matching rule
   *                   should be selected using the matching rule ID.
   * @param  ruleID    The OID of the desired matching rule.  It may be
   *                   {@code null} if the matching rule should be selected only
   *                   using the attribute name.  If a rule ID is provided, then
   *                   it will be the only criteria used to select the matching
   *                   rule.
   * @param  schema    The schema to examine to make the appropriate
   *                   determination.  If this is {@code null} and no rule ID
   *                   was provided, then the default substring matching rule
   *                   will be selected.
   *
   * @return  The selected matching rule.
   */
  public static MatchingRule selectSubstringMatchingRule(final String attrName,
                                                         final String ruleID,
                                                         final Schema schema)
  {
    if (ruleID != null)
    {
      return selectSubstringMatchingRule(ruleID);
    }

    if ((attrName == null) || (schema == null))
    {
      return getDefaultSubstringMatchingRule();
    }

    final AttributeTypeDefinition attrType = schema.getAttributeType(attrName);
    if (attrType == null)
    {
      return getDefaultSubstringMatchingRule();
    }

    final String mrName = attrType.getSubstringMatchingRule(schema);
    if (mrName != null)
    {
      return selectSubstringMatchingRule(mrName);
    }

    final String syntaxOID = attrType.getBaseSyntaxOID(schema);
    if (syntaxOID != null)
    {
      return selectMatchingRuleForSyntax(syntaxOID);
    }

    return getDefaultSubstringMatchingRule();
  }



  /**
   * Attempts to select the appropriate matching rule to use for substring
   * matching using the specified matching rule.  If an appropriate matching
   * rule cannot be determined, then the default substring matching rule will be
   * selected.
   *
   * @param  ruleID  The name or OID of the desired matching rule.
   *
   * @return  The selected matching rule.
   */
  public static MatchingRule selectSubstringMatchingRule(final String ruleID)
  {
    if ((ruleID == null) || (ruleID.length() == 0))
    {
      return getDefaultSubstringMatchingRule();
    }

    final String lowerName = toLowerCase(ruleID);
    if (lowerName.equals(
             CaseExactStringMatchingRule.LOWER_SUBSTRING_RULE_NAME) ||
        lowerName.equals(CaseExactStringMatchingRule.SUBSTRING_RULE_OID) ||
        lowerName.equals("caseexactia5substringsmatch"))
    {
      return CaseExactStringMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  CaseIgnoreListMatchingRule.LOWER_SUBSTRING_RULE_NAME) ||
             lowerName.equals(CaseIgnoreListMatchingRule.SUBSTRING_RULE_OID))
    {
      return CaseIgnoreListMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  CaseIgnoreStringMatchingRule.LOWER_SUBSTRING_RULE_NAME) ||
             lowerName.equals(
                  CaseIgnoreStringMatchingRule.SUBSTRING_RULE_OID) ||
             lowerName.equals("caseignoreia5substringsmatch") ||
             lowerName.equals("1.3.6.1.4.1.1466.109.114.3"))
    {
      return CaseIgnoreStringMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  NumericStringMatchingRule.LOWER_SUBSTRING_RULE_NAME) ||
             lowerName.equals(NumericStringMatchingRule.SUBSTRING_RULE_OID))
    {
      return NumericStringMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  OctetStringMatchingRule.LOWER_SUBSTRING_RULE_NAME) ||
             lowerName.equals(OctetStringMatchingRule.SUBSTRING_RULE_OID))
    {
      return OctetStringMatchingRule.getInstance();
    }
    else if (lowerName.equals(
                  TelephoneNumberMatchingRule.LOWER_SUBSTRING_RULE_NAME) ||
             lowerName.equals(TelephoneNumberMatchingRule.SUBSTRING_RULE_OID))
    {
      return TelephoneNumberMatchingRule.getInstance();
    }
    else
    {
      return getDefaultSubstringMatchingRule();
    }
  }



  /**
   * Retrieves the default matching rule that will be used for substring
   * matching if no other matching rule is specified or available.  The rule
   * returned will perform case-ignore string matching.
   *
   * @return  The default matching rule that will be used for substring matching
   *          if no other matching rule is specified or available.
   */
  public static MatchingRule getDefaultSubstringMatchingRule()
  {
    return CaseIgnoreStringMatchingRule.getInstance();
  }



  /**
   * Attempts to select the appropriate matching rule for use with the syntax
   * with the specified OID.  If an appropriate matching rule cannot be
   * determined, then the case-ignore string matching rule will be selected.
   *
   * @param  syntaxOID  The OID of the attribute syntax for which to make the
   *                    determination.
   *
   * @return  The selected matching rule.
   */
  public static MatchingRule selectMatchingRuleForSyntax(final String syntaxOID)
  {
    if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.7"))
    {
      return BooleanMatchingRule.getInstance();
    }
    else if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.41")) // Postal addr.
    {
      return CaseIgnoreListMatchingRule.getInstance();
    }
    else if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.12") ||
         syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.34")) // name&optional UID
    {
      return DistinguishedNameMatchingRule.getInstance();
    }
    else if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.24") ||
         syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.53")) // UTC time
    {
      return GeneralizedTimeMatchingRule.getInstance();
    }
    else if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.27"))
    {
      return IntegerMatchingRule.getInstance();
    }
    else if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.36"))
    {
      return NumericStringMatchingRule.getInstance();
    }
    else if (syntaxOID.equals("1.3.6.1.4.1.4203.1.1.2") || // auth password
         syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.5") || // binary
         syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.8") || // certificate
         syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.9") || // cert list
         syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.10") || // cert pair
         syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.28") || // JPEG
         syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.40")) // octet string
    {
      return OctetStringMatchingRule.getInstance();
    }
    else if (syntaxOID.equals("1.3.6.1.4.1.1466.115.121.1.50"))
    {
      return TelephoneNumberMatchingRule.getInstance();
    }
    else if (syntaxOID.equals("1.3.6.1.4.1.30221.2.3.4")) // JSON object
    {
      return getJSONObjectExactMatchingRule();
    }
    else
    {
      return CaseIgnoreStringMatchingRule.getInstance();
    }
  }



  /**
   * Retrieves the matching rule that should be used for JSON object exact
   * matching.  Ideally, we will use the jsonObjectExactMatch matching rule,
   * but that's only available in the Commercial Edition of the LDAP SDK, so
   * it's not available in the Standard (or Minimal) Edition.  If we haven't
   * loaded this matching rule yet, then try to use reflection to get the
   * jsonObjectExactMatch instance if it's available, and otherwise fall back
   * to using the caseIgnoreString matching rule.  Either way, cache the result
   * so that we don't need to use reflection on subsequent calls.
   *
   * @return  The matching rule that should be used for JSON object exact
   *          matching.
   */
  private static MatchingRule getJSONObjectExactMatchingRule()
  {
    if (jsonObjectExactMatchingRule == null)
    {
      try
      {
        final Class c = Class.forName("com.unboundid.ldap.sdk.unboundidds." +
             "jsonfilter.JSONObjectExactMatchingRule");
        final Method m = c.getMethod("getInstance");
        jsonObjectExactMatchingRule = (MatchingRule) m.invoke(null);
      }
      catch (final Exception e)
      {
        Debug.debugException(e);

        // We must be using the Standard Edition, which doesn't support the
        // jsonObjectExactMatch matching rule.  Use the caseIgnoreString
        // matching rule instead.
        jsonObjectExactMatchingRule =
             CaseIgnoreStringMatchingRule.getInstance();
      }
    }

    return jsonObjectExactMatchingRule;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy