From 3dc3f07607a5c720a1452cc75701554a9f3ad715 Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Mon, 24 Mar 2014 09:45:42 +0000
Subject: [PATCH] Checkpoint commit for OPENDJ-1308 Migrate schema support
---
opendj3-server-dev/src/server/org/opends/server/api/VirtualAttributeProvider.java | 87 ----
opendj3-server-dev/src/server/org/opends/server/api/MatchingRule.java | 22 +
opendj3-server-dev/src/server/org/opends/server/types/AttributeBuilder.java | 81 ----
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseExactIA5SubstringMatchingRuleTest.java | 33 +
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/SubstringMatchingRuleTest.java | 35 +
opendj3-server-dev/src/server/org/opends/server/api/AbstractMatchingRule.java | 11
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseExactSubstringMatchingRuleTest.java | 33 +
opendj3-server-dev/src/server/org/opends/server/types/SearchFilter.java | 258 ++++---------
opendj3-server-dev/build.xml | 2
opendj3-server-dev/src/server/org/opends/server/controls/MatchedValuesFilter.java | 157 +-------
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseIgnoreSubstringMatchingRuleTest.java | 33 +
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java | 33 +
opendj3-server-dev/src/server/org/opends/server/api/SubstringMatchingRule.java | 260 ++++++++++++++
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/NumericStringSubstringMatchingRuleTest.java | 25 +
14 files changed, 603 insertions(+), 467 deletions(-)
diff --git a/opendj3-server-dev/build.xml b/opendj3-server-dev/build.xml
index ed15780..b32cb07 100644
--- a/opendj3-server-dev/build.xml
+++ b/opendj3-server-dev/build.xml
@@ -35,6 +35,7 @@
<!-- Build JVM properties -->
<property name="MEM" value="512M"/>
+ <property name="PERMSIZE" value="128M"/>
<!-- Build OpenDMK properties -->
<property file="build.properties"/>
@@ -2403,6 +2404,7 @@
<jvmarg value="-Dtest.progress=${test.progress}" />
<jvmarg value="-Xms${MEM}" />
<jvmarg value="-Xmx${MEM}" />
+ <jvmarg value="-XX:MaxPermSize=${PERMSIZE}" />
<jvmarg value="${jvm.debug.arg1}" />
<jvmarg value="${jvm.debug.arg2}" />
<jvmarg value="${jvm.debug.arg3}" />
diff --git a/opendj3-server-dev/src/server/org/opends/server/api/AbstractMatchingRule.java b/opendj3-server-dev/src/server/org/opends/server/api/AbstractMatchingRule.java
index 5a1605d..c377a94 100644
--- a/opendj3-server-dev/src/server/org/opends/server/api/AbstractMatchingRule.java
+++ b/opendj3-server-dev/src/server/org/opends/server/api/AbstractMatchingRule.java
@@ -28,6 +28,7 @@
import java.util.Collection;
import java.util.Comparator;
+import java.util.List;
import org.forgerock.opendj.ldap.Assertion;
import org.forgerock.opendj.ldap.ByteSequence;
@@ -148,6 +149,16 @@
/** {@inheritDoc} */
@Override
+ public Assertion getSubstringAssertion(ByteSequence subInitial,
+ List<? extends ByteSequence> subAnyElements, ByteSequence subFinal) throws DecodeException
+ {
+ return UNDEFINED_ASSERTION;
+ }
+
+
+
+ /** {@inheritDoc} */
+ @Override
public boolean isObsolete()
{
return false;
diff --git a/opendj3-server-dev/src/server/org/opends/server/api/MatchingRule.java b/opendj3-server-dev/src/server/org/opends/server/api/MatchingRule.java
index be53226..0d3c9ee 100644
--- a/opendj3-server-dev/src/server/org/opends/server/api/MatchingRule.java
+++ b/opendj3-server-dev/src/server/org/opends/server/api/MatchingRule.java
@@ -28,6 +28,7 @@
import java.util.Collection;
import java.util.Comparator;
+import java.util.List;
import org.forgerock.opendj.ldap.Assertion;
import org.forgerock.opendj.ldap.ByteSequence;
@@ -148,6 +149,27 @@
public Assertion getLessOrEqualAssertion(final ByteSequence assertionValue) throws DecodeException;
/**
+ * Returns the normalized form of the provided assertion substring values,
+ * which is best suited for efficiently performing matching operations on
+ * that value.
+ *
+ * @param subInitial
+ * The normalized substring value fragment that should appear at
+ * the beginning of the target value.
+ * @param subAnyElements
+ * The normalized substring value fragments that should appear in
+ * the middle of the target value.
+ * @param subFinal
+ * The normalized substring value fragment that should appear at
+ * the end of the target value.
+ * @return The normalized version of the provided assertion value.
+ * @throws DecodeException
+ * if the syntax of the value is not valid.
+ */
+ public Assertion getSubstringAssertion(final ByteSequence subInitial,
+ final List<? extends ByteSequence> subAnyElements, final ByteSequence subFinal) throws DecodeException;
+
+ /**
* Indicates whether this matching rule is declared "OBSOLETE". The
* default implementation will always return {@code false}. If that
* is not acceptable for a particular matching rule implementation,
diff --git a/opendj3-server-dev/src/server/org/opends/server/api/SubstringMatchingRule.java b/opendj3-server-dev/src/server/org/opends/server/api/SubstringMatchingRule.java
index 7984df1..b3d84fb 100644
--- a/opendj3-server-dev/src/server/org/opends/server/api/SubstringMatchingRule.java
+++ b/opendj3-server-dev/src/server/org/opends/server/api/SubstringMatchingRule.java
@@ -26,11 +26,18 @@
*/
package org.opends.server.api;
+import java.util.Collection;
+import java.util.LinkedList;
import java.util.List;
+import java.util.TreeSet;
+import org.forgerock.opendj.ldap.Assertion;
import org.forgerock.opendj.ldap.ByteSequence;
import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.ByteStringBuilder;
+import org.forgerock.opendj.ldap.ConditionResult;
import org.forgerock.opendj.ldap.DecodeException;
+import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
/**
* This class defines the set of methods and structures that must be
@@ -175,5 +182,258 @@
return true;
}
+
+ /**
+ * Default assertion implementation for substring matching rules.
+ * For example, with the assertion value "initial*any1*any2*any3*final",
+ * the assertion will be decomposed like this:
+ * <ul>
+ * <li>normInitial will contain "initial"</li>
+ * <li>normAnys will contain [ "any1", "any2", "any3" ]</li>
+ * <li>normFinal will contain "final"</li>
+ * </ul>
+ */
+ static final class DefaultSubstringAssertion implements Assertion {
+ /** Normalized substring for the text before the first '*' character. */
+ private final ByteString normInitial;
+ /** Normalized substrings for all text chunks in between '*' characters. */
+ private final ByteString[] normAnys;
+ /** Normalized substring for the text after the last '*' character. */
+ private final ByteString normFinal;
+
+ private DefaultSubstringAssertion(final ByteString normInitial,
+ final ByteString[] normAnys, final ByteString normFinal) {
+ this.normInitial = normInitial;
+ this.normAnys = normAnys;
+ this.normFinal = normFinal;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ConditionResult matches(final ByteSequence normalizedAttributeValue) {
+ final int valueLength = normalizedAttributeValue.length();
+
+ int pos = 0;
+ if (normInitial != null) {
+ final int initialLength = normInitial.length();
+ if (initialLength > valueLength) {
+ return ConditionResult.FALSE;
+ }
+
+ for (; pos < initialLength; pos++) {
+ if (normInitial.byteAt(pos) != normalizedAttributeValue.byteAt(pos)) {
+ return ConditionResult.FALSE;
+ }
+ }
+ }
+
+ if (normAnys != null) {
+ matchEachSubstring:
+ for (final ByteSequence element : normAnys) {
+ final int anyLength = element.length();
+ final int end = valueLength - anyLength;
+ matchCurrentSubstring:
+ for (; pos <= end; pos++) {
+ // Try to match all characters from the substring
+ for (int i = 0; i < anyLength; i++) {
+ if (element.byteAt(i) != normalizedAttributeValue.byteAt(pos + i)) {
+ // not a match,
+ // try to find a match in the rest of this value
+ continue matchCurrentSubstring;
+ }
+ }
+ // we just matched current substring,
+ // go try to match the next substring
+ pos += anyLength;
+ continue matchEachSubstring;
+ }
+ // Could not match current substring
+ return ConditionResult.FALSE;
+ }
+ }
+
+ if (normFinal != null) {
+ final int finalLength = normFinal.length();
+
+ if (valueLength - finalLength < pos) {
+ return ConditionResult.FALSE;
+ }
+
+ pos = valueLength - finalLength;
+ for (int i = 0; i < finalLength; i++, pos++) {
+ if (normFinal.byteAt(i) != normalizedAttributeValue.byteAt(pos)) {
+ return ConditionResult.FALSE;
+ }
+ }
+ }
+
+ return ConditionResult.TRUE;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public <T> T createIndexQuery(IndexQueryFactory<T> factory) throws DecodeException {
+ final Collection<T> subqueries = new LinkedList<T>();
+ if (normInitial != null) {
+ // relies on the fact that equality indexes are also ordered
+ subqueries.add(rangeMatch(factory, "equality", normInitial));
+ }
+ if (normAnys != null) {
+ for (ByteString normAny : normAnys) {
+ substringMatch(factory, normAny, subqueries);
+ }
+ }
+ if (normFinal != null) {
+ substringMatch(factory, normFinal, subqueries);
+ }
+ if (normInitial != null) {
+ // Add this one last to minimize the risk to run the same search twice
+ // (possible overlapping with the use of equality index at the start of this method)
+ substringMatch(factory, normInitial, subqueries);
+ }
+ return factory.createIntersectionQuery(subqueries);
+ }
+
+ private <T> T rangeMatch(IndexQueryFactory<T> factory, String indexID, ByteSequence lower) {
+ // Iterate through all the keys that have this value as the prefix.
+
+ // Set the upper bound for a range search.
+ // We need a key for the upper bound that is of equal length
+ // but slightly greater than the lower bound.
+ final ByteStringBuilder upper = new ByteStringBuilder(lower);
+
+ for (int i = upper.length() - 1; i >= 0; i--) {
+ if (upper.byteAt(i) == (byte) 0xFF) {
+ // We have to carry the overflow to the more significant byte.
+ upper.setByte(i, (byte) 0);
+ } else {
+ // No overflow, we can stop.
+ upper.setByte(i, (byte) (upper.byteAt(i) + 1));
+ break;
+ }
+ }
+
+ // Read the range: lower <= keys < upper.
+ return factory.createRangeMatchQuery(indexID, lower, upper, true, false);
+ }
+
+ private <T> void substringMatch(final IndexQueryFactory<T> factory, final ByteString normSubstring,
+ final Collection<T> subqueries) {
+ int substrLength = factory.getIndexingOptions().substringKeySize();
+
+ // There are two cases, depending on whether the user-provided
+ // substring is smaller than the configured index substring length or not.
+ if (normSubstring.length() < substrLength) {
+ subqueries.add(rangeMatch(factory, "substring", normSubstring));
+ } else {
+ // Break the value up into fragments of length equal to the
+ // index substring length, and read those keys.
+
+ // Eliminate duplicates by putting the keys into a set.
+ final TreeSet<ByteSequence> substringKeys = new TreeSet<ByteSequence>();
+
+ // Example: The value is ABCDE and the substring length is 3.
+ // We produce the keys ABC BCD CDE.
+ for (int first = 0, last = substrLength;
+ last <= normSubstring.length(); first++, last++) {
+ substringKeys.add(normSubstring.subSequence(first, first + substrLength));
+ }
+
+ for (ByteSequence key : substringKeys) {
+ subqueries.add(factory.createExactMatchQuery("substring", key));
+ }
+ }
+ }
+
+ // TODO : reminder : should add this method in the SDK
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode()
+ {
+ int hashCode = 0;
+ if (normInitial != null)
+ {
+ hashCode += normInitial.hashCode();
+ }
+ if (normAnys != null)
+ {
+ for (ByteString any : normAnys)
+ {
+ hashCode += any.hashCode();
+ }
+ }
+ if (normFinal != null)
+ {
+ hashCode += normFinal.hashCode();
+ }
+ return hashCode;
+ }
+
+ // TODO : reminder : should add this method in the SDK
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == this)
+ {
+ return true;
+ }
+ if (! (obj instanceof DefaultSubstringAssertion))
+ {
+ return false;
+ }
+ DefaultSubstringAssertion other = (DefaultSubstringAssertion) obj;
+ boolean initialCheck = normInitial == null ? other.normInitial == null : normInitial.equals(other.normInitial);
+ if (!initialCheck)
+ {
+ return false;
+ }
+ boolean finalCheck = normFinal == null ? other.normFinal == null : normFinal.equals(other.normFinal);
+ if (!finalCheck)
+ {
+ return false;
+ }
+ boolean anyCheck = normAnys == null ? other.normAnys == null : normAnys.length == other.normAnys.length;
+ if (!anyCheck)
+ {
+ return false;
+ }
+ if (normAnys != null)
+ {
+ for (int i = 0; i < normAnys.length; i++)
+ {
+ if (! normAnys[i].equals(other.normAnys[i]))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Assertion getSubstringAssertion(ByteSequence subInitial,
+ List<? extends ByteSequence> subAnyElements, ByteSequence subFinal)
+ throws DecodeException
+ {
+ final ByteString normInitial = subInitial == null ? null : normalizeSubstring(subInitial);
+
+ ByteString[] normAnys = null;
+ if (subAnyElements != null && !subAnyElements.isEmpty())
+ {
+ normAnys = new ByteString[subAnyElements.size()];
+ for (int i = 0; i < subAnyElements.size(); i++)
+ {
+ normAnys[i] = normalizeSubstring(subAnyElements.get(i));
+ }
+ }
+ final ByteString normFinal = subFinal == null ? null : normalizeSubstring(subFinal);
+
+ return new DefaultSubstringAssertion(normInitial, normAnys, normFinal);
+ }
+
}
diff --git a/opendj3-server-dev/src/server/org/opends/server/api/VirtualAttributeProvider.java b/opendj3-server-dev/src/server/org/opends/server/api/VirtualAttributeProvider.java
index 1a83583..4822fff 100644
--- a/opendj3-server-dev/src/server/org/opends/server/api/VirtualAttributeProvider.java
+++ b/opendj3-server-dev/src/server/org/opends/server/api/VirtualAttributeProvider.java
@@ -26,7 +26,6 @@
*/
package org.opends.server.api;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -34,9 +33,9 @@
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.Assertion;
-import org.forgerock.opendj.ldap.ByteSequence;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConditionResult;
+import org.forgerock.opendj.ldap.DecodeException;
import org.opends.server.admin.std.server.VirtualAttributeCfg;
import org.opends.server.core.SearchOperation;
import org.opends.server.types.Attribute;
@@ -261,96 +260,28 @@
List<ByteString> subAny,
ByteString subFinal)
{
- SubstringMatchingRule matchingRule =
- rule.getAttributeType().getSubstringMatchingRule();
+ MatchingRule matchingRule = rule.getAttributeType().getSubstringMatchingRule();
if (matchingRule == null)
{
return ConditionResult.UNDEFINED;
}
-
- ByteString normalizedSubInitial;
- if (subInitial == null)
+ Assertion assertion;
+ try
{
- normalizedSubInitial = null;
+ assertion = matchingRule.getSubstringAssertion(subInitial, subAny, subFinal);
}
- else
- {
- try
- {
- normalizedSubInitial =
- matchingRule.normalizeSubstring(subInitial);
- }
- catch (Exception e)
- {
- logger.traceException(e);
-
- // The substring couldn't be normalized => return "undefined".
- return ConditionResult.UNDEFINED;
- }
+ catch(DecodeException e) {
+ logger.traceException(e);
+ return ConditionResult.UNDEFINED;
}
-
- ArrayList<ByteSequence> normalizedSubAny;
- if (subAny == null)
- {
- normalizedSubAny = null;
- }
- else
- {
- normalizedSubAny =
- new ArrayList<ByteSequence>(subAny.size());
- for (ByteString subAnyElement : subAny)
- {
- try
- {
- normalizedSubAny.add(matchingRule.normalizeSubstring(
- subAnyElement));
- }
- catch (Exception e)
- {
- logger.traceException(e);
-
- // The substring couldn't be normalized => return "undefined".
- return ConditionResult.UNDEFINED;
- }
- }
- }
-
-
- ByteString normalizedSubFinal;
- if (subFinal == null)
- {
- normalizedSubFinal = null;
- }
- else
- {
- try
- {
- normalizedSubFinal =
- matchingRule.normalizeSubstring(subFinal);
- }
- catch (Exception e)
- {
- logger.traceException(e);
-
- // The substring couldn't be normalized => return "undefined".
- return ConditionResult.UNDEFINED;
- }
- }
-
-
ConditionResult result = ConditionResult.FALSE;
for (ByteString value : getValues(entry, rule))
{
try
{
- ByteString nv = matchingRule.normalizeAttributeValue(value);
- if (matchingRule.valueMatchesSubstring(
- nv,
- normalizedSubInitial,
- normalizedSubAny,
- normalizedSubFinal))
+ if (assertion.matches(matchingRule.normalizeAttributeValue(value)).toBoolean())
{
return ConditionResult.TRUE;
}
diff --git a/opendj3-server-dev/src/server/org/opends/server/controls/MatchedValuesFilter.java b/opendj3-server-dev/src/server/org/opends/server/controls/MatchedValuesFilter.java
index 9732d95..318f005 100644
--- a/opendj3-server-dev/src/server/org/opends/server/controls/MatchedValuesFilter.java
+++ b/opendj3-server-dev/src/server/org/opends/server/controls/MatchedValuesFilter.java
@@ -36,7 +36,6 @@
import org.forgerock.opendj.io.ASN1Reader;
import org.forgerock.opendj.io.ASN1Writer;
import org.forgerock.opendj.ldap.Assertion;
-import org.forgerock.opendj.ldap.ByteSequence;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DecodeException;
import org.forgerock.util.Reject;
@@ -117,12 +116,6 @@
// The approximate matching rule for this matched values filter.
private MatchingRule approximateMatchingRule;
- // The normalized subFinal value for this matched values filter.
- private ByteString normalizedSubFinal;
-
- // The normalized subInitial value for this matched values filter.
- private ByteString normalizedSubInitial;
-
// The raw, unprocessed assertion value for this matched values filter.
private final ByteString rawAssertionValue;
@@ -148,9 +141,6 @@
// The equality matching rule for this matched values filter.
private MatchingRule equalityMatchingRule;
- // The set of normalized subAny values for this matched values filter.
- private List<ByteString> normalizedSubAny;
-
// The set of subAny values for this matched values filter.
private final List<ByteString> subAny;
@@ -169,7 +159,11 @@
// The substring matching rule for this matched values filter.
private SubstringMatchingRule substringMatchingRule;
-
+ /**
+ * The assertion created from substring matching rule using values of this
+ * filter.
+ */
+ private Assertion substringAssertion;
/**
* Creates a new matched values filter with the provided information.
@@ -194,18 +188,6 @@
this.subAny = subAny;
this.subFinal = subFinal;
this.matchingRuleID = matchingRuleID;
-
- decoded = false;
- attributeType = null;
- assertionValue = null;
- matchingRule = null;
- normalizedSubInitial = null;
- normalizedSubAny = null;
- normalizedSubFinal = null;
- approximateMatchingRule = null;
- equalityMatchingRule = null;
- orderingMatchingRule = null;
- substringMatchingRule = null;
}
@@ -972,37 +954,20 @@
return subInitial;
}
-
-
-
-
-
-
- /**
- * Retrieves the normalized form of the subInitial element.
- *
- * @return The normalized form of the subInitial element, or
- * <CODE>null</CODE> if there is none.
- */
- public ByteString getNormalizedSubInitialElement()
- {
- if (normalizedSubInitial == null)
+ private Assertion getSubstringAssertion() {
+ if (substringAssertion == null)
{
- if ((subInitial != null) && (getSubstringMatchingRule() != null))
+ try
{
- try
- {
- normalizedSubInitial =
- getSubstringMatchingRule().normalizeSubstring(subInitial);
- }
- catch (Exception e)
- {
- logger.traceException(e);
- }
+ substringAssertion =
+ getSubstringMatchingRule().getSubstringAssertion(subInitial, subAny, subFinal);
+ }
+ catch (DecodeException e)
+ {
+ logger.traceException(e);
}
}
-
- return normalizedSubInitial;
+ return substringAssertion;
}
@@ -1019,55 +984,6 @@
return subAny;
}
-
-
- /**
- * Retrieves the set of normalized subAny elements for this matched values
- * filter.
- *
- * @return The set of subAny elements for this matched values filter. If
- * there are none, then an empty list will be returned. If a
- * problem occurs while attempting to perform the normalization, then
- * <CODE>null</CODE> will be returned.
- */
- public List<ByteString> getNormalizedSubAnyElements()
- {
- if (normalizedSubAny == null)
- {
- if ((subAny == null) || (subAny.isEmpty()))
- {
- normalizedSubAny = new ArrayList<ByteString>(0);
- }
- else
- {
- if (getSubstringMatchingRule() == null)
- {
- return null;
- }
-
- normalizedSubAny = new ArrayList<ByteString>();
- try
- {
- for (ByteString s : subAny)
- {
- normalizedSubAny.add(
- substringMatchingRule.normalizeSubstring(s));
- }
- }
- catch (Exception e)
- {
- logger.traceException(e);
-
- normalizedSubAny = null;
- }
- }
- }
-
- return normalizedSubAny;
- }
-
-
-
/**
* Retrieves the subFinal element for this matched values filter.
*
@@ -1079,37 +995,6 @@
return subFinal;
}
-
-
- /**
- * Retrieves the normalized form of the subFinal element.
- *
- * @return The normalized form of the subFinal element, or <CODE>null</CODE>
- * if there is none.
- */
- public ByteString getNormalizedSubFinalElement()
- {
- if (normalizedSubFinal == null)
- {
- if ((subFinal != null) && (getSubstringMatchingRule() != null))
- {
- try
- {
- normalizedSubFinal =
- getSubstringMatchingRule().normalizeSubstring(subFinal);
- }
- catch (Exception e)
- {
- logger.traceException(e);
- }
- }
- }
-
- return normalizedSubFinal;
- }
-
-
-
/**
* Retrieves the matching rule ID for this matched values filter.
*
@@ -1247,9 +1132,7 @@
{
getAttributeType();
getAssertionValue();
- getNormalizedSubInitialElement();
- getNormalizedSubAnyElements();
- getNormalizedSubFinalElement();
+ getSubstringAssertion();
getMatchingRule();
getApproximateMatchingRule();
getEqualityMatchingRule();
@@ -1303,15 +1186,11 @@
case SUBSTRINGS_TYPE:
if (attributeType != null
&& attributeType.equals(type)
- && substringMatchingRule != null)
+ && substringAssertion != null)
{
try
{
- ArrayList<ByteSequence> normalizedSubAnyBS =
- new ArrayList<ByteSequence>(normalizedSubAny);
- return substringMatchingRule.valueMatchesSubstring(
- substringMatchingRule.normalizeAttributeValue(value),
- normalizedSubInitial, normalizedSubAnyBS, normalizedSubFinal);
+ return substringAssertion.matches(substringMatchingRule.normalizeAttributeValue(value)).toBoolean();
}
catch (Exception e)
{
diff --git a/opendj3-server-dev/src/server/org/opends/server/types/AttributeBuilder.java b/opendj3-server-dev/src/server/org/opends/server/types/AttributeBuilder.java
index 515cf56..a35bd5f 100644
--- a/opendj3-server-dev/src/server/org/opends/server/types/AttributeBuilder.java
+++ b/opendj3-server-dev/src/server/org/opends/server/types/AttributeBuilder.java
@@ -27,7 +27,6 @@
package org.opends.server.types;
import java.util.AbstractSet;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
@@ -42,7 +41,6 @@
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.Assertion;
-import org.forgerock.opendj.ldap.ByteSequence;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConditionResult;
import org.forgerock.opendj.ldap.DecodeException;
@@ -381,81 +379,22 @@
ByteString subInitial,
List<ByteString> subAny, ByteString subFinal)
{
- SubstringMatchingRule matchingRule = attributeType
- .getSubstringMatchingRule();
+ SubstringMatchingRule matchingRule = attributeType.getSubstringMatchingRule();
if (matchingRule == null)
{
return ConditionResult.UNDEFINED;
}
- ByteString normalizedSubInitial;
- if (subInitial == null)
- {
- normalizedSubInitial = null;
- }
- else
- {
- try
- {
- normalizedSubInitial =
- matchingRule.normalizeSubstring(subInitial);
- }
- catch (Exception e)
- {
- logger.traceException(e);
- // The substring couldn't be normalized. We have to return
- // "undefined".
- return ConditionResult.UNDEFINED;
- }
- }
-
- ArrayList<ByteSequence> normalizedSubAny;
- if (subAny == null)
+ Assertion assertion;
+ try
{
- normalizedSubAny = null;
+ assertion = matchingRule.getSubstringAssertion(subInitial, subAny, subFinal);
}
- else
+ catch (DecodeException e)
{
- normalizedSubAny = new ArrayList<ByteSequence>(subAny.size());
- for (ByteString subAnyElement : subAny)
- {
- try
- {
- normalizedSubAny
- .add(matchingRule.normalizeSubstring(subAnyElement));
- }
- catch (Exception e)
- {
- logger.traceException(e);
-
- // The substring couldn't be normalized. We have to return
- // "undefined".
- return ConditionResult.UNDEFINED;
- }
- }
- }
-
- ByteString normalizedSubFinal;
- if (subFinal == null)
- {
- normalizedSubFinal = null;
- }
- else
- {
- try
- {
- normalizedSubFinal =
- matchingRule.normalizeSubstring(subFinal);
- }
- catch (Exception e)
- {
- logger.traceException(e);
-
- // The substring couldn't be normalized. We have to return
- // "undefined".
- return ConditionResult.UNDEFINED;
- }
+ logger.traceException(e);
+ return ConditionResult.UNDEFINED;
}
ConditionResult result = ConditionResult.FALSE;
@@ -463,11 +402,7 @@
{
try
{
- if (matchingRule.valueMatchesSubstring(
- matchingRule.normalizeAttributeValue(value),
- normalizedSubInitial,
- normalizedSubAny,
- normalizedSubFinal))
+ if (assertion.matches(matchingRule.normalizeAttributeValue(value)).toBoolean())
{
return ConditionResult.TRUE;
}
diff --git a/opendj3-server-dev/src/server/org/opends/server/types/SearchFilter.java b/opendj3-server-dev/src/server/org/opends/server/types/SearchFilter.java
index d3a5406..c7c4f52 100644
--- a/opendj3-server-dev/src/server/org/opends/server/types/SearchFilter.java
+++ b/opendj3-server-dev/src/server/org/opends/server/types/SearchFilter.java
@@ -3593,30 +3593,13 @@
{
case AND:
case OR:
- if (filterComponents.size() != f.filterComponents.size())
- {
- return false;
- }
-
-outerComponentLoop:
- for (SearchFilter outerFilter : filterComponents)
- {
- for (SearchFilter innerFilter : f.filterComponents)
- {
- if (outerFilter.equals(innerFilter))
- {
- continue outerComponentLoop;
- }
- }
- return false;
- }
- return true;
+ return andOrEqual(f);
case NOT:
return notComponent.equals(f.notComponent);
case EQUALITY:
return typeAndOptionsAndAssertionEqual(f);
case SUBSTRING:
- return equalsSubstring(f);
+ return substringEqual(f);
case GREATER_OR_EQUAL:
return typeAndOptionsAndAssertionEqual(f);
case LESS_OR_EQUAL:
@@ -3633,6 +3616,28 @@
}
}
+ private boolean andOrEqual(SearchFilter f)
+ {
+ if (filterComponents.size() != f.filterComponents.size())
+ {
+ return false;
+ }
+
+outerComponentLoop:
+ for (SearchFilter outerFilter : filterComponents)
+ {
+ for (SearchFilter innerFilter : f.filterComponents)
+ {
+ if (outerFilter.equals(innerFilter))
+ {
+ continue outerComponentLoop;
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
private boolean typeAndOptionsAndAssertionEqual(SearchFilter f)
{
@@ -3650,113 +3655,28 @@
}
- private boolean equalsSubstring(SearchFilter f)
+ private boolean substringEqual(SearchFilter f)
{
if (! attributeType.equals(f.attributeType))
{
return false;
}
- SubstringMatchingRule smr =
- attributeType.getSubstringMatchingRule();
- if (smr == null)
+ SubstringMatchingRule rule = attributeType.getSubstringMatchingRule();
+ if (rule == null)
{
return false;
}
-
- if (! optionsEqual(attributeOptions, f.attributeOptions))
+ try
+ {
+ Assertion thisAssertion = rule.getSubstringAssertion(subInitialElement, subAnyElements, subFinalElement);
+ Assertion thatAssertion = rule.getSubstringAssertion(f.subInitialElement, f.subAnyElements, f.subFinalElement);
+ return thisAssertion.equals(thatAssertion);
+ }
+ catch (DecodeException e)
{
return false;
}
-
- if (subInitialElement == null)
- {
- if (f.subInitialElement != null)
- {
- return false;
- }
- }
- else
- {
- if (f.subInitialElement == null)
- {
- return false;
- }
- try
- {
- ByteString nSI1 =
- smr.normalizeSubstring(subInitialElement);
- ByteString nSI2 =
- smr.normalizeSubstring(f.subInitialElement);
-
- if (! nSI1.equals(nSI2))
- {
- return false;
- }
- }
- catch (Exception e)
- {
- return false;
- }
- }
-
- if (subFinalElement == null)
- {
- if (f.subFinalElement != null)
- {
- return false;
- }
- }
- else
- {
- if (f.subFinalElement == null)
- {
- return false;
- }
- try
- {
- ByteString nSF1 =
- smr.normalizeSubstring(subFinalElement);
- ByteString nSF2 =
- smr.normalizeSubstring(f.subFinalElement);
-
- if (! nSF1.equals(nSF2))
- {
- return false;
- }
- }
- catch (Exception e)
- {
- return false;
- }
- }
-
- if (subAnyElements.size() != f.subAnyElements.size())
- {
- return false;
- }
-
- for (int i = 0; i < subAnyElements.size(); i++)
- {
- try
- {
- ByteString nSA1 =
- smr.normalizeSubstring(subAnyElements.get(i));
- ByteString nSA2 =
- smr.normalizeSubstring(f.subAnyElements.get(i));
-
- if (! nSA1.equals(nSA2))
- {
- return false;
- }
- }
- catch (Exception e)
- {
- return false;
- }
- }
-
- return true;
}
@@ -3820,10 +3740,8 @@
}
else
{
- MatchingRule mr =
- DirectoryServer.getMatchingRule(
- toLowerCase(matchingRuleID));
- if (mr == null)
+ MatchingRule mrule = DirectoryServer.getMatchingRule(toLowerCase(matchingRuleID));
+ if (mrule == null)
{
return false;
}
@@ -3831,8 +3749,8 @@
{
try
{
- Assertion assertion = mr.getAssertion(f.assertionValue);
- return assertion.matches(mr.normalizeAttributeValue(assertionValue)).toBoolean();
+ Assertion assertion = mrule.getAssertion(f.assertionValue);
+ return assertion.matches(mrule.normalizeAttributeValue(assertionValue)).toBoolean();
}
catch (Exception e)
{
@@ -3921,24 +3839,7 @@
case EQUALITY:
return typeAndAssertionHashCode();
case SUBSTRING:
- hashCode = attributeType.hashCode();
-
- SubstringMatchingRule smr =
- attributeType.getSubstringMatchingRule();
-
- hashCode = hashCode(hashCode, smr, subInitialElement);
-
- if (subAnyElements != null)
- {
- for (ByteString e : subAnyElements)
- {
- hashCode = hashCode(hashCode, smr, e);
- }
- }
-
- hashCode = hashCode(hashCode, smr, subFinalElement);
-
- return hashCode;
+ return substringHashCode();
case GREATER_OR_EQUAL:
return typeAndAssertionHashCode();
case LESS_OR_EQUAL:
@@ -3948,35 +3849,41 @@
case APPROXIMATE_MATCH:
return typeAndAssertionHashCode();
case EXTENSIBLE_MATCH:
- hashCode = 0;
-
- if (attributeType != null)
- {
- hashCode += attributeType.hashCode();
- }
-
- if (dnAttributes)
- {
- hashCode++;
- }
-
- if (matchingRuleID != null)
- {
- hashCode += matchingRuleID.hashCode();
- }
-
- if (assertionValue != null)
- {
- hashCode += assertionValue.hashCode();
- }
-
- return hashCode;
+ return extensibleHashCode();
default:
return 1;
}
}
+ /** Returns the hash code for extensible filter. */
+ private int extensibleHashCode()
+ {
+ int hashCode = 0;
+
+ if (attributeType != null)
+ {
+ hashCode += attributeType.hashCode();
+ }
+
+ if (dnAttributes)
+ {
+ hashCode++;
+ }
+
+ if (matchingRuleID != null)
+ {
+ hashCode += matchingRuleID.hashCode();
+ }
+
+ if (assertionValue != null)
+ {
+ hashCode += assertionValue.hashCode();
+ }
+ return hashCode;
+ }
+
+
private int typeAndAssertionHashCode()
{
final int hashCode = attributeType.hashCode();
@@ -3990,25 +3897,30 @@
}
}
-
- private int hashCode(int hashCode, SubstringMatchingRule smr,
- ByteString subElem)
+ /** Returns hash code to use for substring filter. */
+ private int substringHashCode()
{
- if (subElem != null)
+ int hashCode = attributeType.hashCode();
+ final MatchingRule rule = attributeType.getSubstringMatchingRule();
+ if (rule != null)
{
- if (smr == null)
+ try
{
- hashCode += subElem.hashCode();
+ return hashCode + rule.getSubstringAssertion(subInitialElement, subAnyElements, subFinalElement).hashCode();
}
- else
+ catch (DecodeException e)
{
- try
- {
- hashCode += smr.normalizeSubstring(subElem).hashCode();
- }
- catch (Exception e) {}
+ logger.traceException(e);
}
}
+
+ // Fallback to hash code based on elements
+ hashCode += subInitialElement.hashCode();
+ for (ByteString e : subAnyElements)
+ {
+ hashCode += e.hashCode();
+ }
+ hashCode += subFinalElement.hashCode();
return hashCode;
}
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseExactIA5SubstringMatchingRuleTest.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseExactIA5SubstringMatchingRuleTest.java
index a3cd75e..c3b8577 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseExactIA5SubstringMatchingRuleTest.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseExactIA5SubstringMatchingRuleTest.java
@@ -22,6 +22,7 @@
*
*
* Copyright 2006-2008 Sun Microsystems, Inc.
+ * Portions Copyright 2014 ForgeRock AS
*/
package org.opends.server.schema;
@@ -35,6 +36,38 @@
SubstringMatchingRuleTest
{
+ /** {@inheritDoc} */
+ @Override
+ @DataProvider(name="substringMatchData")
+ public Object[][] createSubstringMatchData()
+ {
+ return new Object[][] {
+ {"this is a value", "", new String[] {"this"}, "", true },
+ {"this is a value", "", new String[] {"is"}, "", true },
+ {"this is a value", "th", new String[] {"is"}, "", true },
+ {"this is a value", "this", new String[] {"is"}, "", true },
+ {"this is a value", "this", new String[] {"is"}, "value", true },
+ {"this is a value", "this", new String[] {"is"}, "ue", true },
+ {"this is a value", "this", new String[] {"is"}, "e", true },
+ {"this is a value", "this", new String[] {"is"}, "valu", false },
+ {"this is a value", "THIS", new String[] {"is"}, "", false },
+ {"this is a value", "h", new String[] {"is"}, "", false },
+ {"this is a value", "", new String[] {"a"}, "", true },
+ {"this is a value", "", new String[] {"value"}, "", true },
+ {"this is a value", "", new String[] {" "}, "", true },
+ {"this is a value", "", new String[] {"this", "is", "a", "value"}, "", true },
+ // The matching rule requires ordered non overlapping substrings
+ // Issue #730 was not valid.
+ {"this is a value", "", new String[] {"value", "this"}, "", false },
+ {"this is a value", "", new String[] {"this", "this is"}, "", false },
+ {"this is a value", "", new String[] {"his is", "a val",}, "", true },
+ {"this is a value", "", new String[] {"not",}, "", false },
+ {"this is a value", "", new String[] {"THIS",}, "", false },
+ {"this is a value", "", new String[] {"this", "not"}, "", false },
+ {"this is a value", "", new String[] {" "}, "", true },
+ };
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseExactSubstringMatchingRuleTest.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseExactSubstringMatchingRuleTest.java
index cc1bc60..f09c098 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseExactSubstringMatchingRuleTest.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseExactSubstringMatchingRuleTest.java
@@ -22,6 +22,7 @@
*
*
* Copyright 2006-2008 Sun Microsystems, Inc.
+ * Portions Copyright 2014 ForgeRock AS
*/
package org.opends.server.schema;
@@ -35,6 +36,38 @@
SubstringMatchingRuleTest
{
+ /** {@inheritDoc} */
+ @Override
+ @DataProvider(name="substringMatchData")
+ public Object[][] createSubstringMatchData()
+ {
+ return new Object[][] {
+ {"this is a value", "", new String[] {"this"}, "", true },
+ {"this is a value", "", new String[] {"is"}, "", true },
+ {"this is a value", "th", new String[] {"is"}, "", true },
+ {"this is a value", "this", new String[] {"is"}, "", true },
+ {"this is a value", "this", new String[] {"is"}, "value", true },
+ {"this is a value", "this", new String[] {"is"}, "ue", true },
+ {"this is a value", "this", new String[] {"is"}, "e", true },
+ {"this is a value", "this", new String[] {"is"}, "valu", false },
+ {"this is a value", "THIS", new String[] {"is"}, "", false },
+ {"this is a value", "h", new String[] {"is"}, "", false },
+ {"this is a value", "", new String[] {"a"}, "", true },
+ {"this is a value", "", new String[] {"value"}, "", true },
+ {"this is a value", "", new String[] {" "}, "", true },
+ {"this is a value", "", new String[] {"this", "is", "a", "value"}, "", true },
+ // The matching rule requires ordered non overlapping substrings
+ // Issue #730 was not valid.
+ {"this is a value", "", new String[] {"value", "this"}, "", false },
+ {"this is a value", "", new String[] {"this", "this is"}, "", false },
+ {"this is a value", "", new String[] {"his is", "a val",}, "", true },
+ {"this is a value", "", new String[] {"not",}, "", false },
+ {"this is a value", "", new String[] {"THIS",}, "", false },
+ {"this is a value", "", new String[] {"this", "not"}, "", false },
+ {"this is a value", "", new String[] {" "}, "", true },
+ };
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java
index 2681108..8c57b96 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java
@@ -22,6 +22,7 @@
*
*
* Copyright 2006-2008 Sun Microsystems, Inc.
+ * Portions Copyright 2014 ForgeRock AS
*/
package org.opends.server.schema;
@@ -35,6 +36,38 @@
SubstringMatchingRuleTest
{
+ /** {@inheritDoc} */
+ @Override
+ @DataProvider(name="substringMatchData")
+ public Object[][] createSubstringMatchData()
+ {
+ return new Object[][] {
+ {"this is a value", "", new String[] {"this"}, "", true },
+ {"this is a value", "", new String[] {"is"}, "", true },
+ {"this is a value", "th", new String[] {"is"}, "", true },
+ {"this is a value", "this", new String[] {"is"}, "", true },
+ {"this is a value", "this", new String[] {"is"}, "value", true },
+ {"this is a value", "this", new String[] {"is"}, "ue", true },
+ {"this is a value", "this", new String[] {"is"}, "e", true },
+ {"this is a value", "this", new String[] {"is"}, "valu", false },
+ {"this is a value", "THIS", new String[] {"is"}, "", true },
+ {"this is a value", "h", new String[] {"is"}, "", false },
+ {"this is a value", "", new String[] {"a"}, "", true },
+ {"this is a value", "", new String[] {"value"}, "", true },
+ {"this is a value", "", new String[] {" "}, "", true },
+ {"this is a value", "", new String[] {"this", "is", "a", "value"}, "", true },
+ // The matching rule requires ordered non overlapping substrings
+ // Issue #730 was not valid.
+ {"this is a value", "", new String[] {"value", "this"}, "", false },
+ {"this is a value", "", new String[] {"this", "this is"}, "", false },
+ {"this is a value", "", new String[] {"his is", "a val",}, "", true },
+ {"this is a value", "", new String[] {"not",}, "", false },
+ {"this is a value", "", new String[] {"THIS",}, "", true },
+ {"this is a value", "", new String[] {"this", "not"}, "", false },
+ {"this is a value", "", new String[] {" "}, "", true },
+ };
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseIgnoreSubstringMatchingRuleTest.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseIgnoreSubstringMatchingRuleTest.java
index 07eaabe..e3dabde 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseIgnoreSubstringMatchingRuleTest.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/CaseIgnoreSubstringMatchingRuleTest.java
@@ -22,6 +22,7 @@
*
*
* Copyright 2006-2008 Sun Microsystems, Inc.
+ * Portions Copyright 2014 ForgeRock AS
*/
package org.opends.server.schema;
@@ -35,6 +36,38 @@
SubstringMatchingRuleTest
{
+ /** {@inheritDoc} */
+ @Override
+ @DataProvider(name="substringMatchData")
+ public Object[][] createSubstringMatchData()
+ {
+ return new Object[][] {
+ {"this is a value", "", new String[] {"this"}, "", true },
+ {"this is a value", "", new String[] {"is"}, "", true },
+ {"this is a value", "th", new String[] {"is"}, "", true },
+ {"this is a value", "this", new String[] {"is"}, "", true },
+ {"this is a value", "this", new String[] {"is"}, "value", true },
+ {"this is a value", "this", new String[] {"is"}, "ue", true },
+ {"this is a value", "this", new String[] {"is"}, "e", true },
+ {"this is a value", "this", new String[] {"is"}, "valu", false },
+ {"this is a value", "THIS", new String[] {"is"}, "", true },
+ {"this is a value", "h", new String[] {"is"}, "", false },
+ {"this is a value", "", new String[] {"a"}, "", true },
+ {"this is a value", "", new String[] {"value"}, "", true },
+ {"this is a value", "", new String[] {" "}, "", true },
+ {"this is a value", "", new String[] {"this", "is", "a", "value"}, "", true },
+ // The matching rule requires ordered non overlapping substrings
+ // Issue #730 was not valid.
+ {"this is a value", "", new String[] {"value", "this"}, "", false },
+ {"this is a value", "", new String[] {"this", "this is"}, "", false },
+ {"this is a value", "", new String[] {"his is", "a val",}, "", true },
+ {"this is a value", "", new String[] {"not",}, "", false },
+ {"this is a value", "", new String[] {"THIS",}, "", true },
+ {"this is a value", "", new String[] {"this", "not"}, "", false },
+ {"this is a value", "", new String[] {" "}, "", true },
+ };
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/NumericStringSubstringMatchingRuleTest.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/NumericStringSubstringMatchingRuleTest.java
index 90f9c53..2bf0243 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/NumericStringSubstringMatchingRuleTest.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/NumericStringSubstringMatchingRuleTest.java
@@ -22,6 +22,7 @@
*
*
* Copyright 2006-2008 Sun Microsystems, Inc.
+ * Portions Copyright 2014 ForgeRock AS
*/
package org.opends.server.schema;
@@ -35,6 +36,30 @@
SubstringMatchingRuleTest
{
+ /** {@inheritDoc} */
+ @Override
+ @DataProvider(name="substringMatchData")
+ public Object[][] createSubstringMatchData()
+ {
+ return new Object[][] {
+ // The matching rule requires ordered non overlapping substrings.
+ // Issue #730 was not valid.
+ {"123456789", "", new String[] {"123", "234", "567", "789"}, "", false },
+ {"123456789", "", new String[] {"123", "234"}, "", false },
+ {"123456789", "", new String[] {"567", "234"}, "", false },
+ {"123456789", "", new String[] {"123", "456"}, "", true },
+ {"123456789", "", new String[] {"123"}, "", true },
+ {"123456789", "", new String[] {"456"}, "", true },
+ {"123456789", "", new String[] {"789"}, "", true },
+ {"123456789", "", new String[] {"123456789"}, "", true },
+ {"123456789", "", new String[] {"1234567890"}, "", false },
+ {"123456789", "", new String[] {"9"}, "", true },
+ {"123456789", "", new String[] {"1"}, "", true },
+ {"123456789", "", new String[] {"0"}, "", false },
+ {"123456789", "", new String[] {" "}, "", true },
+ {"123456789", "", new String[] {"0123"}, "", false },
+ };
+ }
/**
* {@inheritDoc}
*/
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/SubstringMatchingRuleTest.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/SubstringMatchingRuleTest.java
index 8c28ce1..106255c 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/SubstringMatchingRuleTest.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/schema/SubstringMatchingRuleTest.java
@@ -30,6 +30,7 @@
import java.util.List;
import org.opends.server.api.SubstringMatchingRule;
+import org.forgerock.opendj.ldap.Assertion;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ByteSequence;
import org.testng.annotations.DataProvider;
@@ -42,9 +43,16 @@
* This class is intended to be extended by one class for each substring
* matching rules.
*/
+@SuppressWarnings("javadoc")
public abstract class SubstringMatchingRuleTest extends SchemaTestCase
{
/**
+ * Generate data for the test of the assertion match.
+ */
+ @DataProvider(name="substringMatchData")
+ public abstract Object[][] createSubstringMatchData();
+
+ /**
* Generate data for the test of the middle string match.
*
* @return the data for the test of the middle string match.
@@ -114,8 +122,7 @@
* Test the normalization and the initial substring match.
*/
@Test(dataProvider= "substringInitialMatchData")
- public void initialMatchingRules(
- String value, String initial, Boolean result) throws Exception
+ public void initialMatchingRules(String value, String initial, Boolean result) throws Exception
{
SubstringMatchingRule rule = getRule();
@@ -140,8 +147,7 @@
* Test the normalization and the final substring match.
*/
@Test(dataProvider= "substringFinalMatchData")
- public void finalMatchingRules(
- String value, String finalValue, Boolean result) throws Exception
+ public void finalMatchingRules(String value, String finalValue, Boolean result) throws Exception
{
SubstringMatchingRule rule = getRule();
@@ -160,4 +166,25 @@
value + " and " + finalValue);
}
}
+
+ @Test(dataProvider= "substringMatchData")
+ public void testSubstringAssertion(String value, String initialSub, String[] middleSubs, String finalSub,
+ Boolean expectedResult) throws Exception
+ {
+ SubstringMatchingRule rule = getRule();
+ ByteString normalizedValue = rule.normalizeAttributeValue(ByteString.valueOf(value));
+ ArrayList<ByteSequence> anySubs = new ArrayList<ByteSequence>(middleSubs.length);
+ for (String sub : middleSubs)
+ {
+ anySubs.add(ByteString.valueOf(sub));
+ }
+ Assertion assertion = rule.getSubstringAssertion(
+ ByteString.valueOf(initialSub),
+ anySubs,
+ ByteString.valueOf(finalSub));
+
+ Boolean result = assertion.matches(normalizedValue).toBoolean();
+ assertEquals(result, expectedResult);
+
+ }
}
--
Gitblit v1.10.0