opends/src/server/org/opends/server/schema/AttributeTypeSyntax.java
@@ -55,6 +55,7 @@ import static org.opends.server.messages.MessageHandler.*; import static org.opends.server.messages.SchemaMessages.*; import static org.opends.server.schema.SchemaConstants.*; import static org.opends.server.util.ServerConstants.*; import static org.opends.server.util.StaticUtils.*; @@ -628,31 +629,6 @@ isNoUserModification = superiorType.isNoUserModification(); attributeUsage = superiorType.getUsage(); } else if (lowerTokenName.equals("approx") || lowerTokenName.equals("approximate")) { // This specifies the name or OID of the approximate matching rule to // use for this attribute type. StringBuilder woidBuffer = new StringBuilder(); pos = readWOID(lowerStr, woidBuffer, pos); ApproximateMatchingRule amr = schema.getApproximateMatchingRule(woidBuffer.toString()); if (amr == null) { // This is bad because we have no idea what the approximate matching // rule should be. Log a message and go with the default matching // rule for the associated syntax. int msgID = MSGID_ATTR_SYNTAX_ATTRTYPE_UNKNOWN_APPROXIMATE_MR; String message = getMessage(msgID, String.valueOf(oid), String.valueOf(woidBuffer)); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); } else { approximateMatchingRule = amr; } } else if (lowerTokenName.equals("equality")) { // This specifies the name or OID of the equality matching rule to use @@ -925,6 +901,30 @@ } } List<String> approxRules = extraProperties.get(SCHEMA_PROPERTY_APPROX_RULE); if ((approxRules != null) && (! approxRules.isEmpty())) { String ruleName = approxRules.get(0); String lowerName = toLowerCase(ruleName); ApproximateMatchingRule amr = schema.getApproximateMatchingRule(lowerName); if (amr == null) { // This is bad because we have no idea what the approximate matching // rule should be. Log a message and go with the default matching // rule for the associated syntax. int msgID = MSGID_ATTR_SYNTAX_ATTRTYPE_UNKNOWN_APPROXIMATE_MR; String message = getMessage(msgID, String.valueOf(oid), String.valueOf(ruleName)); logError(ErrorLogCategory.SCHEMA, ErrorLogSeverity.SEVERE_WARNING, message, msgID); } else { approximateMatchingRule = amr; } } return new AttributeType(value.stringValue(), primaryName, typeNames, oid, description, superiorType, syntax, opends/src/server/org/opends/server/util/ServerConstants.java
@@ -1909,6 +1909,14 @@ /** * The name of the schema extension that will be used to specify the * approximate matching rule that should be used for a given attribute type. */ public static final String SCHEMA_PROPERTY_APPROX_RULE = "X-APPROX"; /** * The name of the schema property that will be used to specify the path to * the schema file from which the schema element was loaded. */ opends/tests/unit-tests-testng/src/server/org/opends/server/schema/AttributeTypeSyntaxTest.java
@@ -26,8 +26,17 @@ */ package org.opends.server.schema; import org.opends.server.api.AttributeSyntax; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.opends.server.api.ApproximateMatchingRule; import org.opends.server.api.AttributeSyntax; import org.opends.server.core.DirectoryServer; import org.opends.server.types.AttributeType; import org.opends.server.types.ByteString; import org.opends.server.types.ByteStringFactory; import static org.testng.Assert.*; /** * Test the AttributeTypeSyntax. @@ -63,4 +72,51 @@ }; } /** * Tests the use of the "X-APPROX" extension to specify a particular * approximate matching rule. * * @throws Exception If an unexpected problem occurs. */ @Test() public void testXAPPROXExtension() throws Exception { // Create and register the approximate matching rule for testing purposes. EqualLengthApproximateMatchingRule testApproxRule = new EqualLengthApproximateMatchingRule(); testApproxRule.initializeMatchingRule(null); DirectoryServer.registerApproximateMatchingRule(testApproxRule, false); // Get a reference to the attribute type syntax implementation in the // server. AttributeTypeSyntax attrTypeSyntax = (AttributeTypeSyntax) DirectoryServer.getAttributeSyntax("1.3.6.1.4.1.1466.115.121.1.3", false); assertNotNull(attrTypeSyntax); // Create an attribute type definition and verify that it is acceptable. ByteString definition = ByteStringFactory.create( "( testxapproxtype-oid NAME 'testXApproxType' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 " + "X-APPROX 'equalLengthApproximateMatch' )"); StringBuilder invalidReason = new StringBuilder(); assertTrue(attrTypeSyntax.valueIsAcceptable(definition, invalidReason), invalidReason.toString()); // Verify that we can decode the attribute type and that it has the // correct approximate matching rule. AttributeType attrType = AttributeTypeSyntax.decodeAttributeType(definition, DirectoryServer.getSchema()); assertNotNull(attrType); assertNotNull(attrType.getApproximateMatchingRule()); assertEquals(attrType.getApproximateMatchingRule(), testApproxRule); } } opends/tests/unit-tests-testng/src/server/org/opends/server/schema/EqualLengthApproximateMatchingRule.java
New file @@ -0,0 +1,170 @@ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, * add the following below this CDDL HEADER, with the fields enclosed * by brackets "[]" replaced with your own identifying * information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * * Portions Copyright 2006 Sun Microsystems, Inc. */ package org.opends.server.schema; import org.opends.server.api.ApproximateMatchingRule; import org.opends.server.config.ConfigEntry; import org.opends.server.config.ConfigException; import org.opends.server.types.ByteString; import org.opends.server.types.ByteStringFactory; import org.opends.server.types.DirectoryException; import org.opends.server.types.InitializationException; import static org.opends.server.schema.SchemaConstants.*; /** * This class implements an extremely simple approximate matching rule that will * consider two values approximately equal only if they have the same length. * It is intended purely for testing purposes. */ public class EqualLengthApproximateMatchingRule extends ApproximateMatchingRule { /** * Creates a new instance of this equal length approximate matching rule. */ public EqualLengthApproximateMatchingRule() { super(); } /** * Initializes this matching rule based on the information in the provided * configuration entry. * * @param configEntry The configuration entry that contains the information * to use to initialize this matching rule. * * @throws ConfigException If an unrecoverable problem arises in the * process of performing the initialization. * * @throws InitializationException If a problem that is not * configuration-related occurs during * initialization. */ public void initializeMatchingRule(ConfigEntry configEntry) throws ConfigException, InitializationException { // No initialization is required. } /** * Retrieves the common name for this matching rule. * * @return The common name for this matching rule, or <CODE>null</CODE> if * it does not have a name. */ public String getName() { return "equalLengthApproximateMatch"; } /** * Retrieves the OID for this matching rule. * * @return The OID for this matching rule. */ public String getOID() { return "equallengthapproximatematch-oid"; } /** * Retrieves the description for this matching rule. * * @return The description for this matching rule, or <CODE>null</CODE> if * there is none. */ public String getDescription() { return null; } /** * Retrieves the OID of the syntax with which this matching rule is * associated. * * @return The OID of the syntax with which this matching rule is associated. */ public String getSyntaxOID() { return SYNTAX_DIRECTORY_STRING_OID; } /** * Retrieves the normalized form of the provided value, which is best suited * for efficiently performing matching operations on that value. * * @param value The value to be normalized. * * @return The normalized version of the provided value. * * @throws DirectoryException If the provided value is invalid according to * the associated attribute syntax. */ public ByteString normalizeValue(ByteString value) throws DirectoryException { // Any value is acceptable, so we can just return a copy of the // value. return ByteStringFactory.create(value.value()); } /** * Indicates whether the two provided normalized values are approximately * equal to each other. * * @param value1 The normalized form of the first value to compare. * @param value2 The normalized form of the second value to compare. * * @return <CODE>true</CODE> if the provided values are approximately equal, * or <CODE>false</CODE> if not. */ public boolean approximatelyMatch(ByteString value1, ByteString value2) { return (value1.value().length == value2.value().length); } }