From c430f8b3da724d0a117eadd172b92179b9a0b5a9 Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Fri, 21 Mar 2014 11:59:48 +0000
Subject: [PATCH] OPENDJ-1368 (CR-3232) Remove AttributeValue
---
opendj3-server-dev/src/server/org/opends/server/api/VirtualAttributeProvider.java | 39 +
opendj3-server-dev/src/server/org/opends/server/types/Attribute.java | 34
opendj3-server-dev/src/server/org/opends/server/admin/server/ServerManagementContext.java | 14
opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java | 24
opendj3-server-dev/src/server/org/opends/server/types/AttributeBuilder.java | 67 +
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java | 6
opendj3-server-dev/src/guitools/org/opends/guitools/controlpanel/task/ModifyEntryTask.java | 5
opendj3-server-dev/src/server/org/opends/server/types/SmallMap.java | 257 ++++++++
opendj3-server-dev/src/server/org/opends/server/types/CollectiveVirtualAttribute.java | 19
opendj3-server-dev/src/server/org/opends/server/backends/jeb/JebFormat.java | 31
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/TestEntry.java | 8
opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVIndex.java | 449 ++++-----------
/dev/null | 198 ------
opendj3-server-dev/src/server/org/opends/server/authorization/dseecompat/UserDN.java | 8
opendj3-server-dev/src/server/org/opends/server/types/SearchFilter.java | 35
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SearchFilterTests.java | 141 +--
opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVKeyComparator.java | 35
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SmallMapTest.java | 249 ++++++++
opendj3-server-dev/src/server/org/opends/server/types/AbstractAttribute.java | 23
opendj3-server-dev/src/server/org/opends/server/types/VirtualAttribute.java | 41 -
opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValuesSet.java | 14
21 files changed, 900 insertions(+), 797 deletions(-)
diff --git a/opendj3-server-dev/src/guitools/org/opends/guitools/controlpanel/task/ModifyEntryTask.java b/opendj3-server-dev/src/guitools/org/opends/guitools/controlpanel/task/ModifyEntryTask.java
index 28cf7f9..6822449 100644
--- a/opendj3-server-dev/src/guitools/org/opends/guitools/controlpanel/task/ModifyEntryTask.java
+++ b/opendj3-server-dev/src/guitools/org/opends/guitools/controlpanel/task/ModifyEntryTask.java
@@ -690,10 +690,9 @@
}
/**
- * Creates an ByteString for an attribute and a value (the one we got
- * using JNDI).
+ * Creates a ByteString for an attribute and a value (the one we got using JNDI).
* @param value the value found using JNDI.
- * @return an ByteString object.
+ * @return a ByteString object.
*/
private static ByteString createAttributeValue(Object value)
{
diff --git a/opendj3-server-dev/src/server/org/opends/server/admin/server/ServerManagementContext.java b/opendj3-server-dev/src/server/org/opends/server/admin/server/ServerManagementContext.java
index e8dd49d..f29d94b 100644
--- a/opendj3-server-dev/src/server/org/opends/server/admin/server/ServerManagementContext.java
+++ b/opendj3-server-dev/src/server/org/opends/server/admin/server/ServerManagementContext.java
@@ -24,11 +24,8 @@
* Copyright 2009 Sun Microsystems, Inc.
* Portions Copyright 2014 ForgeRock AS
*/
-
package org.opends.server.admin.server;
-
-
import static org.opends.messages.AdminMessages.*;
import static org.opends.server.admin.PropertyException.*;
import static org.opends.server.util.StaticUtils.*;
@@ -77,7 +74,6 @@
import org.opends.server.config.ConfigEntry;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeValueIterable;
import org.opends.server.types.AttributeType;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.types.DN;
@@ -905,9 +901,15 @@
List<Attribute> attributes = configEntry.getEntry().getAttribute(type, true);
List<ByteString> results = new LinkedList<ByteString>();
- for (ByteString v : new AttributeValueIterable(attributes))
+ if (attributes != null)
{
- results.add(v);
+ for (Attribute a : attributes)
+ {
+ for (ByteString v : a)
+ {
+ results.add(v);
+ }
+ }
}
return results;
}
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 8a33e70..1a83583 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
@@ -190,6 +190,26 @@
return getValues(entry, rule).contains(value);
}
+ /**
+ * Indicates whether this virtual attribute provider matches the assertion
+ * value.
+ *
+ * @param entry
+ * The entry for which to make the determination.
+ * @param rule
+ * The virtual attribute rule which defines the constraints for the
+ * virtual attribute.
+ * @param assertionValue
+ * The assertion value for which to make the determination.
+ * @return {@code true} if this virtual attribute provider matches the
+ * specified assertion value for the provided entry, or {@code false}
+ * if not.
+ */
+ public ConditionResult matchesEqualityAssertion(Entry entry,
+ VirtualAttributeRule rule, ByteString assertionValue)
+ {
+ return getValues(entry, rule).matchesEqualityAssertion(assertionValue);
+ }
/**
@@ -359,12 +379,12 @@
* The virtual attribute rule which defines the constraints for the
* virtual attribute.
* @param assertionValue
- * The value for which to make the determination.
+ * The assertion value for which to make the determination.
* @return {@code UNDEFINED} if the associated attribute type does not have an
* ordering matching rule, {@code TRUE} if at least one of the
* generated values will be greater than or equal to the specified
- * value, or {@code FALSE} if none of the generated values will be
- * greater than or equal to the specified value.
+ * assertion value, or {@code FALSE} if none of the generated values
+ * will be greater than or equal to the specified value.
*/
public ConditionResult greaterThanOrEqualTo(Entry entry,
VirtualAttributeRule rule,
@@ -421,12 +441,12 @@
* The virtual attribute rule which defines the constraints for the
* virtual attribute.
* @param assertionValue
- * The value for which to make the determination.
+ * The assertion value for which to make the determination.
* @return {@code UNDEFINED} if the associated attribute type does not have an
* ordering matching rule, {@code TRUE} if at least one of the
- * generated values will be less than or equal to the specified value,
- * or {@code FALSE} if none of the generated values will be greater
- * than or equal to the specified value.
+ * generated values will be less than or equal to the specified
+ * assertion value, or {@code FALSE} if none of the generated values
+ * will be greater than or equal to the specified value.
*/
public ConditionResult lessThanOrEqualTo(Entry entry,
VirtualAttributeRule rule,
@@ -482,14 +502,15 @@
* @param entry The entry for which to make the determination.
* @param rule The virtual attribute rule which defines the
* constraints for the virtual attribute.
- * @param assertionValue The value for which to make the determination.
+ * @param assertionValue
+ * The assertion value for which to make the determination.
*
* @return {@code UNDEFINED} if the associated attribute type does
* not have an approximate matching rule, {@code TRUE} if at
* least one of the generated values will be approximately
* equal to the specified value, or {@code FALSE} if none
* of the generated values will be approximately equal to
- * the specified value.
+ * the specified assertion value.
*/
public ConditionResult approximatelyEqualTo(Entry entry,
VirtualAttributeRule rule,
diff --git a/opendj3-server-dev/src/server/org/opends/server/authorization/dseecompat/UserDN.java b/opendj3-server-dev/src/server/org/opends/server/authorization/dseecompat/UserDN.java
index e299cc8..a3d78b1 100644
--- a/opendj3-server-dev/src/server/org/opends/server/authorization/dseecompat/UserDN.java
+++ b/opendj3-server-dev/src/server/org/opends/server/authorization/dseecompat/UserDN.java
@@ -346,10 +346,10 @@
/*
* TODO Evaluate making this method more efficient.
*
- * The evalDNEntryAttr method isn't as efficient as it could be. It would
- * probably be faster to to convert the clientDN to an ByteString and
- * see if the entry has that value than to decode each value as a DN and
- * see if it matches the clientDN.
+ * The evalDNEntryAttr method isn't as efficient as it could be.
+ * It would probably be faster to to convert the clientDN to a ByteString
+ * and see if the entry has that value than to decode each value as a DN
+ * and see if it matches the clientDN.
*/
/**
* This method searches an entry for an attribute value that is
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
index 6d0874d..d9b9f34 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
@@ -32,6 +32,7 @@
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DecodeException;
import org.forgerock.opendj.ldap.ResultCode;
@@ -42,7 +43,6 @@
import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn;
import org.opends.server.admin.std.server.LocalDBIndexCfg;
import org.opends.server.api.*;
-import org.forgerock.opendj.config.server.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.monitors.DatabaseEnvironmentMonitor;
import org.opends.server.types.*;
@@ -975,10 +975,8 @@
try
{
// Use the ordering matching rule to normalize the value.
- MatchingRule orderingRule =
- filter.getAttributeType().getOrderingMatchingRule();
- // FIXME JNR this looks wrong, it should use normalizeAssertionValue()
- byte[] normalizedValue = orderingRule.normalizeAttributeValue(
+ MatchingRule orderingRule = filter.getAttributeType().getOrderingMatchingRule();
+ byte[] normalizedValue = orderingRule.normalizeAssertionValue(
filter.getAssertionValue()).toByteArray();
// Set the lower and upper bounds for a range search.
@@ -1229,8 +1227,8 @@
* equal to the lower bound value, and less than or equal to the
* upper bound value.
*
- * @param lowerValue The lower bound value
- * @param upperValue The upper bound value
+ * @param lowerValue The lower bound assertion value
+ * @param upperValue The upper bound assertion value
* @return The candidate entry IDs.
*/
public EntryIDSet evaluateBoundedRange(ByteString lowerValue, ByteString upperValue)
@@ -1242,13 +1240,10 @@
try
{
- // Use the ordering matching rule to normalize the values.
- MatchingRule orderingRule =
- getAttributeType().getOrderingMatchingRule();
-
// Set the lower and upper bounds for a range search.
- byte[] lower = orderingRule.normalizeAttributeValue(lowerValue).toByteArray();
- byte[] upper = orderingRule.normalizeAttributeValue(upperValue).toByteArray();
+ MatchingRule orderingRule = getAttributeType().getOrderingMatchingRule();
+ byte[] lower = orderingRule.normalizeAssertionValue(lowerValue).toByteArray();
+ byte[] upper = orderingRule.normalizeAssertionValue(upperValue).toByteArray();
// Read the range: lower <= keys <= upper.
return orderingIndex.readRange(lower, upper, true, true);
@@ -1392,8 +1387,7 @@
MatchingRule approximateMatchingRule =
approximateFilter.getAttributeType().getApproximateMatchingRule();
// Make a key from the normalized assertion value.
- // FIXME JNR this looks wrong, it should use normalizeAssertionValue()
- byte[] keyBytes = approximateMatchingRule.normalizeAttributeValue(
+ byte[] keyBytes = approximateMatchingRule.normalizeAssertionValue(
approximateFilter.getAssertionValue()).toByteArray();
DatabaseEntry key = new DatabaseEntry(keyBytes);
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/JebFormat.java b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/JebFormat.java
index 458df29..9813c65 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/JebFormat.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/JebFormat.java
@@ -66,8 +66,28 @@
*/
public static long entryIDFromDatabase(byte[] bytes)
{
+ return toLong(bytes, 0, 8);
+ }
+
+ /**
+ * Decode a long from a byte array, starting at start index and ending at end
+ * index.
+ *
+ * @param bytes
+ * The bytes value of the long.
+ * @param start
+ * the array index where to start computing the long
+ * @param end
+ * the array index exclusive where to end computing the long
+ * @return the long representation of the read bytes.
+ * @throws ArrayIndexOutOfBoundsException
+ * if the bytes array length is less than end.
+ */
+ public static long toLong(byte[] bytes, int start, int end)
+ throws ArrayIndexOutOfBoundsException
+ {
long v = 0;
- for (int i = 0; i < 8; i++)
+ for (int i = start; i < end; i++)
{
v <<= 8;
v |= (bytes[i] & 0xFF);
@@ -90,14 +110,7 @@
if(bytes.length == 8)
{
- long v = 0;
- v |= (bytes[0] & 0x7F);
- for (int i = 1; i < 8; i++)
- {
- v <<= 8;
- v |= (bytes[i] & 0xFF);
- }
- return v;
+ return entryIDFromDatabase(bytes);
}
return Long.MAX_VALUE;
}
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValuesSet.java b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValuesSet.java
index cd04d26..4e9432f 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValuesSet.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/SortValuesSet.java
@@ -125,7 +125,7 @@
return true;
}
if (vlvIndex.comparator.compare(
- this, entryIDs.length - 1, entryID, values, types) < 0)
+ this, entryIDs.length - 1, entryID, values) < 0)
{
long[] updatedEntryIDs = new long[entryIDs.length + 1];
System.arraycopy(entryIDs, 0, updatedEntryIDs, 0, entryIDs.length);
@@ -157,7 +157,7 @@
}
else
{
- int pos = binarySearch(entryID, values, types);
+ int pos = binarySearch(entryID, values);
if(pos >= 0)
{
if(entryIDs[pos] == entryID)
@@ -220,13 +220,12 @@
*
* @param entryID The entry ID to remove.
* @param values The values to remove.
- * @param types The types of the values to remove.
* @return True if the information was successfully removed or False
* otherwise.
* @throws DirectoryException If a Directory Server error occurs.
* @throws DatabaseException If an error occurs in the JE database.
*/
- public boolean remove(long entryID, ByteString[] values, AttributeType[] types)
+ public boolean remove(long entryID, ByteString[] values)
throws DatabaseException, DirectoryException
{
if(entryIDs == null || entryIDs.length == 0)
@@ -239,7 +238,7 @@
updateValuesBytesOffsets();
}
- int pos = binarySearch(entryID, values, types);
+ int pos = binarySearch(entryID, values);
if(pos < 0)
{
// Not found.
@@ -413,13 +412,12 @@
*
* @param entryID The entry ID to match or -1 if not matching on entry ID.
* @param values The values to match.
- * @param types The types of the values to match.
* @return Index of the entry matching the values and optionally the entry ID
* if it is found or a negative index if its not found.
* @throws DirectoryException If a Directory Server error occurs.
* @throws DatabaseException If an error occurs in the JE database.
*/
- int binarySearch(long entryID, ByteString[] values, AttributeType[] types)
+ int binarySearch(long entryID, ByteString... values)
throws DatabaseException, DirectoryException
{
if(entryIDs == null || entryIDs.length == 0)
@@ -431,7 +429,7 @@
for(int j = entryIDs.length - 1; i <= j;)
{
int k = i + j >> 1;
- int l = vlvIndex.comparator.compare(this, k, entryID, values, types);
+ int l = vlvIndex.comparator.compare(this, k, entryID, values);
if (l < 0)
{
i = k + 1;
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVIndex.java b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVIndex.java
index cc8038e..1f90e1a 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVIndex.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVIndex.java
@@ -149,8 +149,7 @@
try
{
- this.filter =
- SearchFilter.createFilterFromString(config.getFilter());
+ this.filter = SearchFilter.createFilterFromString(config.getFilter());
}
catch(Exception e)
{
@@ -161,8 +160,7 @@
String[] sortAttrs = config.getSortOrder().split(" ");
SortKey[] sortKeys = new SortKey[sortAttrs.length];
- MatchingRule[] orderingRules =
- new MatchingRule[sortAttrs.length];
+ MatchingRule[] orderingRules = new MatchingRule[sortAttrs.length];
boolean[] ascending = new boolean[sortAttrs.length];
for(int i = 0; i < sortAttrs.length; i++)
{
@@ -666,53 +664,45 @@
ByteString[] values, AttributeType[] types) throws DatabaseException,
DirectoryException
{
- SortValuesSet sortValuesSet = null;
DatabaseEntry key = new DatabaseEntry();
- OperationStatus status;
- LockMode lockMode = LockMode.DEFAULT;
DatabaseEntry data = new DatabaseEntry();
+ key.setData(encodeKey(entryID, values, types));
+ return getSortValuesSet(txn, key, data, LockMode.DEFAULT);
+ }
- Cursor cursor = openCursor(txn, CursorConfig.READ_COMMITTED);
-
- try
+ private SortValuesSet getSortValuesSet(Transaction txn, DatabaseEntry key,
+ DatabaseEntry data, LockMode lockMode)
+ {
+ OperationStatus status = getSearchKeyRange(txn, key, data, lockMode);
+ if (status != OperationStatus.SUCCESS)
{
- key.setData(encodeKey(entryID, values, types));
- status = cursor.getSearchKeyRange(key, data,lockMode);
-
- if(status != OperationStatus.SUCCESS)
+ // There are no records in the database
+ if (logger.isTraceEnabled())
{
- // There are no records in the database
- if(logger.isTraceEnabled())
- {
- logger.trace("No sort values set exist in VLV vlvIndex %s. " +
- "Creating unbound set.", config.getName());
- }
- sortValuesSet = new SortValuesSet(this);
+ logger.trace("No sort values set exist in VLV vlvIndex %s. "
+ + "Creating unbound set.", config.getName());
}
- else
- {
- if(logger.isTraceEnabled())
- {
- StringBuilder searchKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(searchKeyHex, key.getData(), 4);
- StringBuilder foundKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(foundKeyHex, key.getData(), 4);
- logger.trace("Retrieved a sort values set in VLV vlvIndex " +
- "%s\nSearch Key:%s\nFound Key:%s\n",
- config.getName(),
- searchKeyHex,
- foundKeyHex);
- }
- sortValuesSet = new SortValuesSet(key.getData(), data.getData(),
- this);
- }
- }
- finally
- {
- cursor.close();
+ // this could not be found, so clean the key for later reuse
+ key.setData(new byte[0]);
+ return new SortValuesSet(this);
}
- return sortValuesSet;
+ if (logger.isTraceEnabled())
+ {
+ logSearchKeyResult(key);
+ }
+ return new SortValuesSet(key.getData(), data.getData(), this);
+ }
+
+ private void logSearchKeyResult(DatabaseEntry key)
+ {
+ StringBuilder searchKeyHex = new StringBuilder();
+ StaticUtils.byteArrayToHexPlusAscii(searchKeyHex, key.getData(), 4);
+ StringBuilder foundKeyHex = new StringBuilder();
+ StaticUtils.byteArrayToHexPlusAscii(foundKeyHex, key.getData(), 4);
+ logger.trace("Retrieved a sort values set in VLV vlvIndex %s\n" +
+ "Search Key:%s\nFound Key:%s\n",
+ config.getName(), searchKeyHex, foundKeyHex);
}
/**
@@ -736,7 +726,7 @@
DatabaseException, DirectoryException
{
SortValuesSet valuesSet = getSortValuesSet(txn, entryID, values, types);
- int pos = valuesSet.binarySearch(entryID, values, types);
+ int pos = valuesSet.binarySearch(entryID, values);
return pos >= 0;
}
@@ -746,68 +736,19 @@
ByteString[] values = getSortValues(entry);
AttributeType[] types = getSortTypes();
DatabaseEntry key = new DatabaseEntry();
- OperationStatus status;
- LockMode lockMode = LockMode.RMW;
DatabaseEntry data = new DatabaseEntry();
- Cursor cursor = openCursor(txn, CursorConfig.READ_COMMITTED);
- try
- {
- key.setData(encodeKey(entryID, values, types));
- status = cursor.getSearchKeyRange(key, data,lockMode);
- }
- finally
- {
- cursor.close();
- }
-
- SortValuesSet sortValuesSet;
- if(status != OperationStatus.SUCCESS)
- {
- // There are no records in the database
- if(logger.isTraceEnabled())
- {
- logger.trace("No sort values set exist in VLV vlvIndex %s. " +
- "Creating unbound set.", config.getName());
- }
- sortValuesSet = new SortValuesSet(this);
- key.setData(new byte[0]);
- }
- else
- {
- if(logger.isTraceEnabled())
- {
- StringBuilder searchKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(searchKeyHex, key.getData(), 4);
- StringBuilder foundKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(foundKeyHex, key.getData(), 4);
- logger.trace("Retrieved a sort values set in VLV vlvIndex " +
- "%s\nSearch Key:%s\nFound Key:%s\n",
- config.getName(),
- searchKeyHex,
- foundKeyHex);
- }
- sortValuesSet = new SortValuesSet(key.getData(), data.getData(),
- this);
- }
-
-
-
-
+ key.setData(encodeKey(entryID, values, types));
+ SortValuesSet sortValuesSet =
+ getSortValuesSet(txn, key, data, LockMode.RMW);
boolean success = sortValuesSet.add(entryID, values, types);
int newSize = sortValuesSet.size();
if(newSize >= sortedSetCapacity)
{
SortValuesSet splitSortValuesSet = sortValuesSet.split(newSize / 2);
- byte[] splitAfter = splitSortValuesSet.toDatabase();
- key.setData(splitSortValuesSet.getKeyBytes());
- data.setData(splitAfter);
- put(txn, key, data);
- byte[] after = sortValuesSet.toDatabase();
- key.setData(sortValuesSet.getKeyBytes());
- data.setData(after);
- put(txn, key, data);
+ put(txn, key, data, splitSortValuesSet); // splitAfter
+ put(txn, key, data, sortValuesSet); // after
if(logger.isTraceEnabled())
{
@@ -820,8 +761,7 @@
}
else
{
- byte[] after = sortValuesSet.toDatabase();
- data.setData(after);
+ data.setData(sortValuesSet.toDatabase()); // after
put(txn, key, data);
// TODO: What about phantoms?
}
@@ -834,6 +774,14 @@
return success;
}
+ private void put(Transaction txn, DatabaseEntry key, DatabaseEntry data,
+ SortValuesSet set) throws DirectoryException
+ {
+ key.setData(set.getKeyBytes());
+ data.setData(set.toDatabase());
+ put(txn, key, data);
+ }
+
/**
* Gets the types of the attribute values to sort.
*
@@ -845,8 +793,7 @@
AttributeType[] types = new AttributeType[sortKeys.length];
for (int i = 0; i < sortKeys.length; i++)
{
- SortKey sortKey = sortKeys[i];
- types[i] = sortKey.getAttributeType();
+ types[i] = sortKeys[i].getAttributeType();
}
return types;
}
@@ -857,38 +804,18 @@
ByteString[] values = getSortValues(entry);
AttributeType[] types = getSortTypes();
DatabaseEntry key = new DatabaseEntry();
- OperationStatus status;
- LockMode lockMode = LockMode.RMW;
DatabaseEntry data = new DatabaseEntry();
- Cursor cursor = openCursor(txn, CursorConfig.READ_COMMITTED);
-
- try
- {
- key.setData(encodeKey(entryID, values, types));
- status = cursor.getSearchKeyRange(key, data,lockMode);
- }
- finally
- {
- cursor.close();
- }
-
+ key.setData(encodeKey(entryID, values, types));
+ OperationStatus status = getSearchKeyRange(txn, key, data, LockMode.RMW);
if(status == OperationStatus.SUCCESS)
{
if(logger.isTraceEnabled())
{
- StringBuilder searchKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(searchKeyHex, key.getData(), 4);
- StringBuilder foundKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(foundKeyHex, key.getData(), 4);
- logger.trace("Retrieved a sort values set in VLV vlvIndex " +
- "%s\nSearch Key:%s\nFound Key:%s\n",
- config.getName(),
- searchKeyHex,
- foundKeyHex);
+ logSearchKeyResult(key);
}
SortValuesSet sortValuesSet = new SortValuesSet(key.getData(), data.getData(), this);
- boolean success = sortValuesSet.remove(entryID, values, types);
+ boolean success = sortValuesSet.remove(entryID, values);
byte[] after = sortValuesSet.toDatabase();
if(after == null)
@@ -911,6 +838,20 @@
return false;
}
+ private OperationStatus getSearchKeyRange(Transaction txn, DatabaseEntry key,
+ DatabaseEntry data, LockMode lockMode)
+ {
+ Cursor cursor = openCursor(txn, CursorConfig.READ_COMMITTED);
+ try
+ {
+ return cursor.getSearchKeyRange(key, data, lockMode);
+ }
+ finally
+ {
+ cursor.close();
+ }
+ }
+
/**
* Update the vlvIndex with the specified values to add and delete.
*
@@ -935,10 +876,7 @@
}
DatabaseEntry key = new DatabaseEntry();
- OperationStatus status;
- LockMode lockMode = LockMode.RMW;
DatabaseEntry data = new DatabaseEntry();
- SortValuesSet sortValuesSet;
Iterator<SortValues> aValues = null;
Iterator<SortValues> dValues = null;
SortValues av = null;
@@ -985,46 +923,7 @@
break;
}
- Cursor cursor = openCursor(txn, CursorConfig.READ_COMMITTED);
-
- try
- {
- status = cursor.getSearchKeyRange(key, data,lockMode);
- }
- finally
- {
- cursor.close();
- }
-
- if(status != OperationStatus.SUCCESS)
- {
- // There are no records in the database
- if(logger.isTraceEnabled())
- {
- logger.trace("No sort values set exist in VLV vlvIndex %s. " +
- "Creating unbound set.", config.getName());
- }
- sortValuesSet = new SortValuesSet(this);
- key.setData(new byte[0]);
- }
- else
- {
- if(logger.isTraceEnabled())
- {
- StringBuilder searchKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(searchKeyHex, key.getData(), 4);
- StringBuilder foundKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(foundKeyHex, key.getData(), 4);
- logger.trace("Retrieved a sort values set in VLV vlvIndex " +
- "%s\nSearch Key:%s\nFound Key:%s\n",
- config.getName(),
- searchKeyHex,
- foundKeyHex);
- }
- sortValuesSet = new SortValuesSet(key.getData(), data.getData(),
- this);
- }
-
+ final SortValuesSet sortValuesSet = getSortValuesSet(txn, data, data, LockMode.RMW);
int oldSize = sortValuesSet.size();
if(key.getData().length == 0)
{
@@ -1032,29 +931,13 @@
while(av != null)
{
sortValuesSet.add(av.getEntryID(), av.getValues(), av.getTypes());
- aValues.remove();
- if(aValues.hasNext())
- {
- av = aValues.next();
- }
- else
- {
- av = null;
- }
+ av = moveToNextSortValues(aValues);
}
while(dv != null)
{
- sortValuesSet.remove(dv.getEntryID(), dv.getValues(), dv.getTypes());
- dValues.remove();
- if(dValues.hasNext())
- {
- dv = dValues.next();
- }
- else
- {
- dv = null;
- }
+ sortValuesSet.remove(dv.getEntryID(), dv.getValues());
+ dv = moveToNextSortValues(dValues);
}
}
else
@@ -1064,29 +947,13 @@
while(av != null && av.compareTo(maxValues) <= 0)
{
sortValuesSet.add(av.getEntryID(), av.getValues(), av.getTypes());
- aValues.remove();
- if(aValues.hasNext())
- {
- av = aValues.next();
- }
- else
- {
- av = null;
- }
+ av = moveToNextSortValues(aValues);
}
while(dv != null && dv.compareTo(maxValues) <= 0)
{
- sortValuesSet.remove(dv.getEntryID(), dv.getValues(), dv.getTypes());
- dValues.remove();
- if(dValues.hasNext())
- {
- dv = dValues.next();
- }
- else
- {
- dv = null;
- }
+ sortValuesSet.remove(dv.getEntryID(), dv.getValues());
+ dv = moveToNextSortValues(dValues);
}
}
@@ -1094,14 +961,8 @@
if(newSize >= sortedSetCapacity)
{
SortValuesSet splitSortValuesSet = sortValuesSet.split(newSize / 2);
- byte[] splitAfter = splitSortValuesSet.toDatabase();
- key.setData(splitSortValuesSet.getKeyBytes());
- data.setData(splitAfter);
- put(txn, key, data);
- byte[] after = sortValuesSet.toDatabase();
- key.setData(sortValuesSet.getKeyBytes());
- data.setData(after);
- put(txn, key, data);
+ put(txn, key, data, splitSortValuesSet); // splitAfter
+ put(txn, key, data, sortValuesSet); // after
if(logger.isTraceEnabled())
{
@@ -1127,6 +988,16 @@
}
}
+ private SortValues moveToNextSortValues(Iterator<SortValues> sortValues)
+ {
+ sortValues.remove();
+ if (sortValues.hasNext())
+ {
+ return sortValues.next();
+ }
+ return null;
+ }
+
private byte[] encodeKey(SortValues sv) throws DirectoryException
{
return encodeKey(sv.getEntryID(), sv.getValues(), sv.getTypes());
@@ -1156,23 +1027,11 @@
StringBuilder debugBuilder)
throws DirectoryException, DatabaseException
{
- if(!trusted || rebuildRunning)
- {
- return null;
- }
- if(!searchOperation.getBaseDN().equals(baseDN))
- {
- return null;
- }
- if(!searchOperation.getScope().equals(scope))
- {
- return null;
- }
- if(!searchOperation.getFilter().equals(filter))
- {
- return null;
- }
- if(!sortControl.getSortOrder().equals(this.sortOrder))
+ if (!trusted || rebuildRunning
+ || !searchOperation.getBaseDN().equals(baseDN)
+ || !searchOperation.getScope().equals(scope)
+ || !searchOperation.getFilter().equals(filter)
+ || !sortControl.getSortOrder().equals(sortOrder))
{
return null;
}
@@ -1241,34 +1100,21 @@
int count = 1 + beforeCount + afterCount;
selectedIDs = new long[count];
- DatabaseEntry key = new DatabaseEntry();
- OperationStatus status;
- LockMode lockMode = LockMode.DEFAULT;
- DatabaseEntry data = new DatabaseEntry();
-
Cursor cursor = openCursor(txn, CursorConfig.READ_COMMITTED);
-
try
{
+ DatabaseEntry key = new DatabaseEntry();
+ DatabaseEntry data = new DatabaseEntry();
+ LockMode lockMode = LockMode.DEFAULT;
//Locate the set that contains the target entry.
int cursorCount = 0;
int selectedPos = 0;
- status = cursor.getFirst(key, data,lockMode);
+ OperationStatus status = cursor.getFirst(key, data, lockMode);
while(status == OperationStatus.SUCCESS)
{
if(logger.isTraceEnabled())
{
- StringBuilder searchKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(searchKeyHex, key.getData(),
- 4);
- StringBuilder foundKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(foundKeyHex, key.getData(),
- 4);
- logger.trace("Retrieved a sort values set in VLV " +
- "vlvIndex %s\nSearch Key:%s\nFound Key:%s\n",
- config.getName(),
- searchKeyHex,
- foundKeyHex);
+ logSearchKeyResult(key);
}
long[] IDs = SortValuesSet.getEncodedIDs(data.getData(), 0);
for(int i = startPos + selectedPos - cursorCount;
@@ -1313,14 +1159,12 @@
int includedAfterCount = 0;
LinkedList<EntryID> idList = new LinkedList<EntryID>();
DatabaseEntry key = new DatabaseEntry();
- OperationStatus status;
- LockMode lockMode = LockMode.DEFAULT;
DatabaseEntry data = new DatabaseEntry();
Cursor cursor = openCursor(txn, CursorConfig.READ_COMMITTED);
-
try
{
+ LockMode lockMode = LockMode.DEFAULT;
ByteSequence vBytes = vlvRequest.getGreaterThanOrEqualAssertion();
ByteStringBuilder keyBytes =
new ByteStringBuilder(vBytes.length() + 4);
@@ -1328,34 +1172,18 @@
vBytes.copyTo(keyBytes);
key.setData(keyBytes.getBackingArray(), 0, keyBytes.length());
- status = cursor.getSearchKeyRange(key, data, lockMode);
+ OperationStatus status = cursor.getSearchKeyRange(key, data, lockMode);
if(status == OperationStatus.SUCCESS)
{
if(logger.isTraceEnabled())
{
- StringBuilder searchKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(searchKeyHex, key.getData(),
- 4);
- StringBuilder foundKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(foundKeyHex, key.getData(),
- 4);
- logger.trace("Retrieved a sort values set in VLV " +
- "vlvIndex %s\nSearch Key:%s\nFound Key:%s\n",
- config.getName(),
- searchKeyHex,
- foundKeyHex);
+ logSearchKeyResult(key);
}
SortValuesSet sortValuesSet =
new SortValuesSet(key.getData(), data.getData(), this);
- ByteString[] assertionValue = new ByteString[] {
- vlvRequest.getGreaterThanOrEqualAssertion()
- };
- AttributeType[] assertionType = new AttributeType[] {
- sortOrder.getSortKeys()[0].getAttributeType()
- };
- int adjustedTargetOffset =
- sortValuesSet.binarySearch(-1, assertionValue, assertionType);
+ int adjustedTargetOffset = sortValuesSet.binarySearch(
+ -1, vlvRequest.getGreaterThanOrEqualAssertion());
if(adjustedTargetOffset < 0)
{
// For a negative return value r, the vlvIndex -(r+1) gives the
@@ -1379,7 +1207,6 @@
}
status = cursor.getPrev(key, data, lockMode);
-
if(status != OperationStatus.SUCCESS)
{
break;
@@ -1387,8 +1214,7 @@
if(includedBeforeCount < beforeCount)
{
- lastIDs =
- SortValuesSet.getEncodedIDs(data.getData(), 0);
+ lastIDs = SortValuesSet.getEncodedIDs(data.getData(), 0);
lastOffset = lastIDs.length - 1;
targetOffset += lastIDs.length;
}
@@ -1423,14 +1249,12 @@
}
status = cursor.getNext(key, data, lockMode);
-
if(status != OperationStatus.SUCCESS)
{
break;
}
- lastIDs =
- SortValuesSet.getEncodedIDs(data.getData(), 0);
+ lastIDs = SortValuesSet.getEncodedIDs(data.getData(), 0);
lastOffset = 0;
afterIDCount += lastIDs.length;
}
@@ -1465,28 +1289,18 @@
LinkedList<long[]> idSets = new LinkedList<long[]>();
int currentCount = 0;
DatabaseEntry key = new DatabaseEntry();
- OperationStatus status;
- LockMode lockMode = LockMode.RMW;
DatabaseEntry data = new DatabaseEntry();
Cursor cursor = openCursor(txn, CursorConfig.READ_COMMITTED);
-
try
{
- status = cursor.getFirst(key, data, lockMode);
+ LockMode lockMode = LockMode.RMW;
+ OperationStatus status = cursor.getFirst(key, data, lockMode);
while(status == OperationStatus.SUCCESS)
{
if(logger.isTraceEnabled())
{
- StringBuilder searchKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(searchKeyHex, key.getData(), 4);
- StringBuilder foundKeyHex = new StringBuilder();
- StaticUtils.byteArrayToHexPlusAscii(foundKeyHex, key.getData(), 4);
- logger.trace("Retrieved a sort values set in VLV vlvIndex " +
- "%s\nSearch Key:%s\nFound Key:%s\n",
- config.getName(),
- searchKeyHex,
- foundKeyHex);
+ logSearchKeyResult(key);
}
long[] ids = SortValuesSet.getEncodedIDs(data.getData(), 0);
idSets.add(ids);
@@ -1563,12 +1377,9 @@
for (int i=0; i < sortKeys.length; i++)
{
SortKey sortKey = sortKeys[i];
- AttributeType attrType = sortKey.getAttributeType();
- List<Attribute> attrList = entry.getAttribute(attrType);
+ List<Attribute> attrList = entry.getAttribute(sortKey.getAttributeType());
if (attrList != null)
{
- ByteString sortValue = null;
-
// There may be multiple versions of this attribute in the target entry
// (e.g., with different sets of options), and it may also be a
// multivalued attribute. In that case, we need to find the value that
@@ -1576,15 +1387,12 @@
// in ascending order, we want to find the lowest value; for sorting in
// descending order, we want to find the highest value). This is
// handled by the SortKey.compareValues method.
+ ByteString sortValue = null;
for (Attribute a : attrList)
{
for (ByteString v : a)
{
- if (sortValue == null)
- {
- sortValue = v;
- }
- else if (sortKey.compareValues(v, sortValue) < 0)
+ if (sortValue == null || sortKey.compareValues(v, sortValue) < 0)
{
sortValue = v;
}
@@ -1647,8 +1455,7 @@
* @return The sort values represented by the key bytes.
* @throws DirectoryException If a Directory Server error occurs.
*/
- SortValues decodeKey(byte[] keyBytes)
- throws DirectoryException
+ SortValues decodeKey(byte[] keyBytes) throws DirectoryException
{
if(keyBytes == null || keyBytes.length == 0)
{
@@ -1685,16 +1492,8 @@
vBytesPos += valueLength;
}
- // FIXME: Should pos+offset method for decoding IDs be added to
- // JebFormat?
- long v = 0;
- for (int i = vBytesPos; i < keyBytes.length; i++)
- {
- v <<= 8;
- v |= (keyBytes[i] & 0xFF);
- }
-
- return new SortValues(new EntryID(v), attributeValues, sortOrder);
+ final long id = JebFormat.toLong(keyBytes, vBytesPos, keyBytes.length);
+ return new SortValues(new EntryID(id), attributeValues, sortOrder);
}
/**
@@ -1732,8 +1531,7 @@
{
try
{
- this.filter =
- SearchFilter.createFilterFromString(cfg.getFilter());
+ this.filter = SearchFilter.createFilterFromString(cfg.getFilter());
}
catch(Exception e)
{
@@ -1746,8 +1544,7 @@
String[] sortAttrs = cfg.getSortOrder().split(" ");
SortKey[] sortKeys = new SortKey[sortAttrs.length];
- MatchingRule[] orderingRules =
- new MatchingRule[sortAttrs.length];
+ MatchingRule[] orderingRules = new MatchingRule[sortAttrs.length];
boolean[] ascending = new boolean[sortAttrs.length];
for(int i = 0; i < sortAttrs.length; i++)
{
@@ -1815,15 +1612,13 @@
}
// Update sort set capacity only if changed.
- if(config.getMaxBlockSize() !=
- cfg.getMaxBlockSize())
+ if (config.getMaxBlockSize() != cfg.getMaxBlockSize())
{
this.sortedSetCapacity = cfg.getMaxBlockSize();
// Require admin action only if the new capacity is larger. Otherwise,
// we will lazyly update the sorted sets.
- if(config.getMaxBlockSize() <
- cfg.getMaxBlockSize())
+ if (config.getMaxBlockSize() < cfg.getMaxBlockSize())
{
adminActionRequired = true;
}
@@ -1834,8 +1629,7 @@
{
try
{
- this.filter =
- SearchFilter.createFilterFromString(cfg.getFilter());
+ this.filter = SearchFilter.createFilterFromString(cfg.getFilter());
adminActionRequired = true;
}
catch(Exception e)
@@ -1852,13 +1646,11 @@
}
// Update the sort order only if changed.
- if(!config.getSortOrder().equals(
- cfg.getSortOrder()))
+ if (!config.getSortOrder().equals(cfg.getSortOrder()))
{
String[] sortAttrs = cfg.getSortOrder().split(" ");
SortKey[] sortKeys = new SortKey[sortAttrs.length];
- MatchingRule[] orderingRules =
- new MatchingRule[sortAttrs.length];
+ MatchingRule[] orderingRules = new MatchingRule[sortAttrs.length];
boolean[] ascending = new boolean[sortAttrs.length];
for(int i = 0; i < sortAttrs.length; i++)
{
@@ -1935,8 +1727,7 @@
if(adminActionRequired)
{
trusted = false;
- LocalizableMessage message = NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(name);
- messages.add(message);
+ messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(name));
try
{
state.putIndexTrustState(null, this, false);
diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVKeyComparator.java b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVKeyComparator.java
index c3a61db..6fd1ec4 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVKeyComparator.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/VLVKeyComparator.java
@@ -34,7 +34,6 @@
import org.forgerock.opendj.ldap.DecodeException;
import org.forgerock.opendj.ldap.ResultCode;
import org.opends.server.api.MatchingRule;
-import org.opends.server.types.AttributeType;
import org.opends.server.types.DirectoryException;
import com.sleepycat.je.DatabaseException;
@@ -66,8 +65,7 @@
* @param ascending The array of booleans indicating the ordering for
* each value.
*/
- public VLVKeyComparator(MatchingRule[] orderingRules,
- boolean[] ascending)
+ public VLVKeyComparator(MatchingRule[] orderingRules, boolean[] ascending)
{
this.orderingRules = orderingRules;
this.ascending = ascending;
@@ -205,19 +203,8 @@
if(b1Pos + 8 <= b1.length && b2Pos + 8 <= b2.length)
{
- long b1ID = 0;
- for (int i = b1Pos; i < b1Pos + 8; i++)
- {
- b1ID <<= 8;
- b1ID |= (b1[i] & 0xFF);
- }
-
- long b2ID = 0;
- for (int i = b2Pos; i < b2Pos + 8; i++)
- {
- b2ID <<= 8;
- b2ID |= (b2[i] & 0xFF);
- }
+ long b1ID = JebFormat.toLong(b1, b1Pos, b1Pos + 8);
+ long b2ID = JebFormat.toLong(b2, b2Pos, b2Pos + 8);
long idDifference = (b1ID - b2ID);
if (idDifference < 0)
@@ -235,10 +222,8 @@
}
// If we've gotten here, then we can't tell the difference between the sets
- // of available values and entry IDs are not all available, so just return
- // 0
+ // of available values and entry IDs are not all available, so just return 0
return 0;
-
}
/**
@@ -256,10 +241,8 @@
*
* @param set The sort values set to containing the values.
* @param index The index of the values in the set.
- * @param entryID The entry ID to use in the comparasion.
- * @param values The values to use in the comparasion.
- * @param types The types of the values to use in the comparasion.
- *
+ * @param entryID The entry ID to use in the comparison.
+ * @param values The values to use in the comparison.
* @return A negative integer if the values in the set should come before
* the given values in ascending order, a positive integer if
* the values in the set should come after the given values in
@@ -273,8 +256,7 @@
* associated equality matching rule).
*/
public int compare(SortValuesSet set, int index, long entryID,
- ByteString[] values, AttributeType[] types) throws DatabaseException,
- DirectoryException
+ ByteString[] values) throws DatabaseException, DirectoryException
{
for (int j=0; j < orderingRules.length; j++)
{
@@ -290,8 +272,7 @@
{
try
{
- final MatchingRule eqRule = types[j].getEqualityMatchingRule();
- b2Bytes = eqRule.normalizeAttributeValue(values[j]);
+ b2Bytes = orderingRules[j].normalizeAttributeValue(values[j]);
}
catch (DecodeException e)
{
diff --git a/opendj3-server-dev/src/server/org/opends/server/types/AbstractAttribute.java b/opendj3-server-dev/src/server/org/opends/server/types/AbstractAttribute.java
index 1ec9b2a..265ce82 100644
--- a/opendj3-server-dev/src/server/org/opends/server/types/AbstractAttribute.java
+++ b/opendj3-server-dev/src/server/org/opends/server/types/AbstractAttribute.java
@@ -30,6 +30,8 @@
import java.util.Set;
import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.DecodeException;
+import org.opends.server.api.MatchingRule;
import static org.opends.server.util.StaticUtils.*;
@@ -201,16 +203,22 @@
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
@Override
public int hashCode()
{
int hashCode = getAttributeType().hashCode();
for (ByteString value : this)
{
- hashCode += value.hashCode();
+ try
+ {
+ MatchingRule eqRule = getAttributeType().getEqualityMatchingRule();
+ hashCode += eqRule.normalizeAttributeValue(value).hashCode();
+ }
+ catch (DecodeException e)
+ {
+ hashCode += value.hashCode();
+ }
}
return hashCode;
}
@@ -231,8 +239,7 @@
{
String noption = toLowerCase(option);
- // Cannot use Set.contains() because the options are not
- // normalized.
+ // Cannot use Set.contains() because the options are not normalized.
for (String o : getOptions())
{
String no = toLowerCase(o);
@@ -299,8 +306,7 @@
return false;
}
- // Cannot use Set.containsAll() because the set of options are
- // not normalized.
+ // Cannot use Set.containsAll() because the set of options are not normalized.
for (String option : options)
{
if (!hasOption(option))
@@ -308,7 +314,6 @@
return false;
}
}
-
return true;
}
diff --git a/opendj3-server-dev/src/server/org/opends/server/types/Attribute.java b/opendj3-server-dev/src/server/org/opends/server/types/Attribute.java
index db29e7f..29369d4 100644
--- a/opendj3-server-dev/src/server/org/opends/server/types/Attribute.java
+++ b/opendj3-server-dev/src/server/org/opends/server/types/Attribute.java
@@ -62,14 +62,14 @@
* Indicates whether this attribute has any value(s) that are
* approximately equal to the provided value.
*
- * @param value
- * The value for which to make the determination.
+ * @param assertionValue
+ * The assertion value for which to make the determination.
* @return <CODE>UNDEFINED</CODE> if this attribute does not have
* an approximate matching rule, <CODE>TRUE</CODE> if at
* least one value is approximately equal to the provided
* value, or <CODE>false</CODE> otherwise.
*/
- ConditionResult approximatelyEqualTo(ByteString value);
+ ConditionResult approximatelyEqualTo(ByteString assertionValue);
@@ -100,6 +100,18 @@
/**
+ * Indicates whether this attribute matches the specified assertion value.
+ *
+ * @param assertionValue
+ * The assertion value for which to make the determination.
+ * @return <CODE>true</CODE> if this attribute matches the specified assertion
+ * value, or <CODE>false</CODE> if not.
+ */
+ ConditionResult matchesEqualityAssertion(ByteString assertionValue);
+
+
+
+ /**
* Indicates whether the provided object is an attribute that is
* equal to this attribute. It will be considered equal if the
* attribute type, set of values, and set of options are equal.
@@ -159,14 +171,14 @@
* Indicates whether this attribute has any value(s) that are
* greater than or equal to the provided value.
*
- * @param value
- * The value for which to make the determination.
+ * @param assertionValue
+ * The assertion value for which to make the determination.
* @return <CODE>UNDEFINED</CODE> if this attribute does not have
* an ordering matching rule, <CODE>TRUE</CODE> if at
* least one value is greater than or equal to the provided
- * value, or <CODE>false</CODE> otherwise.
+ * assertion value, or <CODE>false</CODE> otherwise.
*/
- ConditionResult greaterThanOrEqualTo(ByteString value);
+ ConditionResult greaterThanOrEqualTo(ByteString assertionValue);
@@ -257,14 +269,14 @@
* Indicates whether this attribute has any value(s) that are less
* than or equal to the provided value.
*
- * @param value
- * The value for which to make the determination.
+ * @param assertionValue
+ * The assertion value for which to make the determination.
* @return <CODE>UNDEFINED</CODE> if this attribute does not have
* an ordering matching rule, <CODE>TRUE</CODE> if at
* least one value is less than or equal to the provided
- * value, or <CODE>false</CODE> otherwise.
+ * assertion value, or <CODE>false</CODE> otherwise.
*/
- ConditionResult lessThanOrEqualTo(ByteString value);
+ ConditionResult lessThanOrEqualTo(ByteString assertionValue);
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 8c38d96..515cf56 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
@@ -32,7 +32,6 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -128,7 +127,11 @@
// The name of this attribute as provided by the end user.
private final String name;
- // The unmodifiable set of values for this attribute.
+ /**
+ * The unmodifiable map of values for this attribute. The key is the
+ * attribute value normalized according to the equality matching rule and
+ * the value is the non normalized value.
+ */
private final Map<ByteString, ByteString> values;
@@ -158,7 +161,7 @@
* {@inheritDoc}
*/
@Override
- public final ConditionResult approximatelyEqualTo(ByteString value)
+ public final ConditionResult approximatelyEqualTo(ByteString assertionValue)
{
MatchingRule matchingRule = attributeType.getApproximateMatchingRule();
if (matchingRule == null)
@@ -169,7 +172,7 @@
Assertion assertion = null;
try
{
- assertion = matchingRule.getAssertion(value);
+ assertion = matchingRule.getAssertion(assertionValue);
}
catch (Exception e)
{
@@ -208,6 +211,28 @@
return values.containsKey(normalize(attributeType, value));
}
+ /** {@inheritDoc} */
+ @Override
+ public ConditionResult matchesEqualityAssertion(ByteString assertionValue)
+ {
+ try
+ {
+ MatchingRule eqRule = getAttributeType().getEqualityMatchingRule();
+ final Assertion assertion = eqRule.getAssertion(assertionValue);
+ for (ByteString normalizedValue : values.keySet())
+ {
+ if (assertion.matches(normalizedValue).toBoolean())
+ {
+ return ConditionResult.TRUE;
+ }
+ }
+ return ConditionResult.FALSE;
+ }
+ catch (DecodeException e)
+ {
+ return ConditionResult.UNDEFINED;
+ }
+ }
/**
* {@inheritDoc}
@@ -235,7 +260,7 @@
* {@inheritDoc}
*/
@Override
- public final ConditionResult greaterThanOrEqualTo(ByteString value)
+ public final ConditionResult greaterThanOrEqualTo(ByteString assertionValue)
{
MatchingRule matchingRule = attributeType.getOrderingMatchingRule();
if (matchingRule == null)
@@ -246,7 +271,7 @@
Assertion assertion;
try
{
- assertion = matchingRule.getGreaterOrEqualAssertion(value);
+ assertion = matchingRule.getGreaterOrEqualAssertion(assertionValue);
}
catch (DecodeException e)
{
@@ -268,8 +293,7 @@
{
logger.traceException(e);
// We couldn't normalize one of the attribute values. If we
- // can't find a definite match, then we should return
- // "undefined".
+ // can't find a definite match, then we should return "undefined".
result = ConditionResult.UNDEFINED;
}
}
@@ -305,7 +329,7 @@
* {@inheritDoc}
*/
@Override
- public final ConditionResult lessThanOrEqualTo(ByteString value)
+ public final ConditionResult lessThanOrEqualTo(ByteString assertionValue)
{
MatchingRule matchingRule = attributeType.getOrderingMatchingRule();
if (matchingRule == null)
@@ -316,7 +340,7 @@
Assertion assertion;
try
{
- assertion = matchingRule.getLessOrEqualAssertion(value);
+ assertion = matchingRule.getLessOrEqualAssertion(assertionValue);
}
catch (DecodeException e)
{
@@ -1076,8 +1100,8 @@
private final SmallSet<String> options = new SmallSet<String>();
/** The map of normalized values => values for this attribute. */
- private LinkedHashMap<ByteString, ByteString> values =
- new LinkedHashMap<ByteString, ByteString>();
+ private Map<ByteString, ByteString> values =
+ new SmallMap<ByteString, ByteString>();
@@ -1213,37 +1237,38 @@
* Adds the specified attribute value to this attribute builder if it is not
* already present.
*
- * @param value
+ * @param attributeValue
* The {@link ByteString} representation of the attribute value to be
* added to this attribute builder.
* @return <code>true</code> if this attribute builder did not already contain
* the specified attribute value.
*/
- public boolean add(ByteString value)
+ public boolean add(ByteString attributeValue)
{
- return values.put(normalize(value), value) == null;
+ return values.put(normalize(attributeValue), attributeValue) == null;
}
- private ByteString normalize(ByteString value)
+ private ByteString normalize(ByteString attributeValue)
{
- return normalize(attributeType, value);
+ return normalize(attributeType, attributeValue);
}
- private static ByteString normalize(AttributeType attributeType, ByteString value)
+ private static ByteString normalize(AttributeType attributeType,
+ ByteString attributeValue)
{
try
{
if (attributeType != null)
{
final MatchingRule eqRule = attributeType.getEqualityMatchingRule();
- return eqRule.normalizeAttributeValue(value);
+ return eqRule.normalizeAttributeValue(attributeValue);
}
}
catch (DecodeException e)
{
// nothing to do here
}
- return value;
+ return attributeValue;
}
/**
@@ -1765,7 +1790,7 @@
else
{
newValues = Collections.unmodifiableMap(values);
- values = new LinkedHashMap<ByteString, ByteString>();
+ values = new SmallMap<ByteString, ByteString>();
}
// Now create the appropriate attribute based on the options.
diff --git a/opendj3-server-dev/src/server/org/opends/server/types/AttributeValueIterable.java b/opendj3-server-dev/src/server/org/opends/server/types/AttributeValueIterable.java
deleted file mode 100644
index 73f59df..0000000
--- a/opendj3-server-dev/src/server/org/opends/server/types/AttributeValueIterable.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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 legal-notices/CDDLv1_0.txt
- * or http://forgerock.org/license/CDDLv1.0.html.
- * 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 legal-notices/CDDLv1_0.txt.
- * 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
- *
- *
- * Copyright 2006-2008 Sun Microsystems, Inc.
- * Portions Copyright 2014 ForgeRock AS
- */
-package org.opends.server.types;
-
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-import org.forgerock.opendj.ldap.ByteString;
-
-/**
- * An iterable read-only view of of a set of attribute values returned
- * from methods such as
- * {@link org.opends.server.types.Entry#getAttribute(AttributeType)}.
- * <p>
- * Using instances of this class it is possible to filter out
- * attribute values which do not have the correct options set. This is
- * achieved without having to duplicate the set of attributes.
- */
-@org.opends.server.types.PublicAPI(
- stability=org.opends.server.types.StabilityLevel.VOLATILE,
- mayInstantiate=false,
- mayExtend=false,
- mayInvoke=true)
-public final class AttributeValueIterable implements Iterable<ByteString> {
-
- // The set of attributes having the same type and options.
- private Iterable<Attribute> attributes;
-
- // The set of options which all values must contain.
- private HashSet<String> options;
-
-
-
- /**
- * Create a new attribute value iterable object.
- *
- * @param attributes The set of attributes having the same type.
- * Can be {@code null}.
- */
- public AttributeValueIterable(Iterable<Attribute> attributes) {
- this(attributes, null);
-
- }
-
- /**
- * Create a new attribute value iterable object.
- *
- * @param attributes The set of attributes having the same type.
- * Can be {@code null}.
- * @param options The set of options which all values must
- * contain, or {@code null} if no options are
- * required.
- */
- public AttributeValueIterable(Iterable<Attribute> attributes,
- HashSet<String> options) {
-
- this.attributes = attributes;
- this.options = options;
- }
-
- /**
- * Retrieves an iterator that can be used to cursor through the set
- * of attribute values.
- *
- * @return An iterator that can be used to cursor through the set
- * of attribute values.
- */
- public Iterator<ByteString> iterator() {
- return new AttributeValueIterator();
- }
-
- /**
- * Private iterator implementation.
- */
- private class AttributeValueIterator implements Iterator<ByteString> {
- // Flag indicating whether iteration can proceed.
- private boolean hasNext;
-
- // The current attribute iterator.
- private Iterator<Attribute> attributeIterator;
-
- // The current value iterator.
- private Iterator<ByteString> valueIterator;
-
- /**
- * Create a new attribute value iterator over the attribute set.
- */
- private AttributeValueIterator() {
-
- this.valueIterator = null;
-
- if (attributes != null) {
- this.attributeIterator = attributes.iterator();
- this.hasNext = skipNonMatchingAttributes();
- } else {
- this.attributeIterator = null;
- this.hasNext = false;
- }
- }
-
- /**
- * Indicates whether there are more attribute values to return.
- *
- * @return {@code true} if there are more attribute values to
- * return, or {@code false} if not.
- */
- public boolean hasNext() {
- return hasNext;
- }
-
- /**
- * Retrieves the next attribute value in the set.
- *
- * @return The next attribute value in the set.
- *
- * @throws NoSuchElementException If there are no more values to
- * return.
- */
- public ByteString next() throws NoSuchElementException
- {
- if (hasNext == false) {
- throw new NoSuchElementException();
- }
-
- ByteString value = valueIterator.next();
-
- // We've reached the end of this array list, so skip to the next
- // non-empty one.
- if (valueIterator.hasNext() == false) {
- hasNext = skipNonMatchingAttributes();
- }
-
- return value;
- }
-
- /**
- * Removes the last attribute value retrieved from the set. Note
- * that this operation is not supported and will always cause an
- * {@code UnsupportedOperationException} to be thrown.
- *
- * @throws UnsupportedOperationException If the last value
- * cannot be removed.
- */
- public void remove() throws UnsupportedOperationException
- {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Skip past any empty attributes or attributes that do not have
- * the correct set of options until we find one that contains some
- * values.
- *
- * @return {@code true} if iteration can continue, or
- * {@code false} if not.
- */
- private boolean skipNonMatchingAttributes() {
-
- while (attributeIterator.hasNext()) {
- Attribute attribute = attributeIterator.next();
-
- if (attribute.hasAllOptions(options)) {
- valueIterator = attribute.iterator();
- if (valueIterator.hasNext()) {
- return true;
- }
- }
- }
-
- return false;
- }
- }
-}
diff --git a/opendj3-server-dev/src/server/org/opends/server/types/CollectiveVirtualAttribute.java b/opendj3-server-dev/src/server/org/opends/server/types/CollectiveVirtualAttribute.java
index 5c7b99b..e1929bc 100644
--- a/opendj3-server-dev/src/server/org/opends/server/types/CollectiveVirtualAttribute.java
+++ b/opendj3-server-dev/src/server/org/opends/server/types/CollectiveVirtualAttribute.java
@@ -58,8 +58,8 @@
* {@inheritDoc}
*/
@Override
- public ConditionResult approximatelyEqualTo(ByteString value) {
- return attribute.approximatelyEqualTo(value);
+ public ConditionResult approximatelyEqualTo(ByteString assertionValue) {
+ return attribute.approximatelyEqualTo(assertionValue);
}
/**
@@ -70,6 +70,13 @@
return attribute.contains(value);
}
+ /** {@inheritDoc} */
+ @Override
+ public ConditionResult matchesEqualityAssertion(ByteString assertionValue)
+ {
+ return attribute.matchesEqualityAssertion(assertionValue);
+ }
+
/**
* {@inheritDoc}
*/
@@ -90,8 +97,8 @@
* {@inheritDoc}
*/
@Override
- public ConditionResult greaterThanOrEqualTo(ByteString value) {
- return attribute.greaterThanOrEqualTo(value);
+ public ConditionResult greaterThanOrEqualTo(ByteString assertionValue) {
+ return attribute.greaterThanOrEqualTo(assertionValue);
}
/**
@@ -114,8 +121,8 @@
* {@inheritDoc}
*/
@Override
- public ConditionResult lessThanOrEqualTo(ByteString value) {
- return attribute.lessThanOrEqualTo(value);
+ public ConditionResult lessThanOrEqualTo(ByteString assertionValue) {
+ return attribute.lessThanOrEqualTo(assertionValue);
}
/**
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 e19558d..d3a5406 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
@@ -2723,44 +2723,35 @@
return ConditionResult.UNDEFINED;
}
- ByteString normAssertionValue;
- try
- {
- normAssertionValue = matchingRule.normalizeAssertionValue(assertionValue);
- }
- catch (Exception e)
- {
- logger.traceException(e);
-
- // We can't normalize the assertion value, so the result must be
- // undefined.
- return ConditionResult.UNDEFINED;
- }
-
// Iterate through all the attributes and see if we can find a match.
+ ConditionResult result = ConditionResult.FALSE;
for (Attribute a : attrs)
{
- // FIXME next if is incorrect
- if (a.contains(normAssertionValue))
+ final ConditionResult cr = a.matchesEqualityAssertion(assertionValue);
+ if (cr == ConditionResult.TRUE)
{
if (logger.isTraceEnabled())
{
logger.trace(
- "Returning TRUE for equality component %s in " +
- "filter %s for entry %s", this, completeFilter, entry.getName());
+ "Returning TRUE for equality component %s in filter %s " +
+ "for entry %s", this, completeFilter, entry.getName());
}
return ConditionResult.TRUE;
}
+ else if (cr == ConditionResult.UNDEFINED)
+ {
+ result = ConditionResult.UNDEFINED;
+ }
}
if (logger.isTraceEnabled())
{
logger.trace(
- "Returning FALSE for equality component %s in filter " +
- "%s because entry %s didn't have attribute type %s with value %s",
- this, completeFilter, entry.getName(), attributeType.getNameOrOID(), assertionValue);
+ "Returning %s for equality component %s in filter %s " +
+ "because entry %s didn't have attribute type %s with value %s",
+ result, this, completeFilter, entry.getName(), attributeType.getNameOrOID(), assertionValue);
}
- return ConditionResult.FALSE;
+ return result;
}
diff --git a/opendj3-server-dev/src/server/org/opends/server/types/SmallMap.java b/opendj3-server-dev/src/server/org/opends/server/types/SmallMap.java
new file mode 100644
index 0000000..88769c8
--- /dev/null
+++ b/opendj3-server-dev/src/server/org/opends/server/types/SmallMap.java
@@ -0,0 +1,257 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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
+ *
+ * Copyright 2014 ForgeRock AS
+ */
+package org.opends.server.types;
+
+import java.util.*;
+
+/**
+ * A small map of values. This map implementation is optimized to use as little
+ * memory as possible in the case where there zero or one elements. In addition,
+ * any normalization of entriess is delayed until the second entry is added
+ * (normalization may be triggered by invoking {@link Object#hashCode()} or
+ * {@link Object#equals(Object)}.
+ * <p>
+ * Null keys are not supported by this map.
+ *
+ * @param <K>
+ * the type of keys maintained by this map
+ * @param <V>
+ * the type of mapped values
+ */
+public class SmallMap<K, V> extends AbstractMap<K, V>
+{
+
+ /** The map of entries if there are more than one. */
+ private LinkedHashMap<K, V> entries;
+
+ /** The first key of the Map. */
+ private K firstKey;
+ /** The first value of the Map. */
+ private V firstValue;
+
+
+ /** Creates a new small map which is initially empty. */
+ public SmallMap()
+ {
+ // No implementation required.
+ }
+
+ private void rejectIfNull(Object key)
+ {
+ if (key == null)
+ {
+ throw new NullPointerException("null keys are not allowed");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public V get(Object key)
+ {
+ rejectIfNull(key);
+ if (entries != null)
+ { // >= 2 entries case
+ return entries.get(key);
+ }
+ // 0 and 1 case
+ if (firstKey != null && firstKey.equals(key))
+ {
+ return firstValue;
+ }
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public V put(K key, V value)
+ {
+ rejectIfNull(key);
+ if (entries != null)
+ { // >= 2 entries case
+ return entries.put(key, value);
+ }
+ if (firstKey == null)
+ { // 0 entries case
+ firstKey = key;
+ firstValue = value;
+ return null;
+ }
+ // 1 entry case
+ if (firstKey.equals(key))
+ { // replace value
+ V oldValue = firstValue;
+ firstValue = value;
+ return oldValue;
+ }
+ // overflow to the underlying map
+ entries = new LinkedHashMap<K, V>(2);
+ entries.put(firstKey, firstValue);
+ firstKey = null;
+ firstValue = null;
+ return entries.put(key, value);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void putAll(Map<? extends K, ? extends V> m)
+ {
+ for (Entry<? extends K, ? extends V> entry : m.entrySet())
+ {
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public V remove(Object key)
+ {
+ if (entries != null)
+ {
+ // Note: if there is one or zero values left we could stop using the map.
+ // However, lets assume that if the map was multi-valued before
+ // then it may become multi-valued again.
+ return entries.remove(key);
+ }
+
+ if (firstKey != null && firstKey.equals(key))
+ {
+ V oldV = firstValue;
+ firstKey = null;
+ firstValue = null;
+ return oldV;
+ }
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean containsKey(Object key)
+ {
+ rejectIfNull(key);
+ if (entries != null)
+ {
+ return entries.containsKey(key);
+ }
+ return firstKey != null && firstKey.equals(key);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean containsValue(Object value)
+ {
+ if (entries != null)
+ {
+ return entries.containsValue(value);
+ }
+ if (firstKey == null)
+ {
+ return false;
+ }
+ if (firstValue == null)
+ {
+ return value == null;
+ }
+ return firstValue.equals(value);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void clear()
+ {
+ firstKey = null;
+ firstValue = null;
+ entries = null;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int size()
+ {
+ if (entries != null)
+ {
+ return entries.size();
+ }
+ return firstKey != null ? 1 : 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Set<Entry<K, V>> entrySet()
+ {
+ if (entries != null)
+ {
+ return entries.entrySet();
+ }
+ if (firstKey == null)
+ {
+ return Collections.emptySet();
+ }
+
+ return new AbstractSet<Entry<K, V>>()
+ {
+
+ @Override
+ public Iterator<Entry<K, V>> iterator()
+ {
+ return new Iterator<Entry<K, V>>()
+ {
+
+ private boolean isFirst = true;
+
+ @Override
+ public boolean hasNext()
+ {
+ return isFirst;
+ }
+
+ @Override
+ public Entry<K, V> next()
+ {
+ if (!isFirst)
+ {
+ throw new NoSuchElementException();
+ }
+ isFirst = false;
+ return new SimpleEntry<K, V>(firstKey, firstValue);
+ }
+
+ @Override
+ public void remove()
+ {
+ firstKey = null;
+ firstValue = null;
+ }
+ };
+ }
+
+ @Override
+ public int size()
+ {
+ return 1;
+ }
+ };
+ }
+
+}
diff --git a/opendj3-server-dev/src/server/org/opends/server/types/VirtualAttribute.java b/opendj3-server-dev/src/server/org/opends/server/types/VirtualAttribute.java
index 03f7c30..77021b9 100644
--- a/opendj3-server-dev/src/server/org/opends/server/types/VirtualAttribute.java
+++ b/opendj3-server-dev/src/server/org/opends/server/types/VirtualAttribute.java
@@ -35,9 +35,7 @@
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConditionResult;
-import org.forgerock.opendj.ldap.DecodeException;
import org.forgerock.util.Utils;
-import org.opends.server.api.MatchingRule;
import org.opends.server.api.VirtualAttributeProvider;
/**
@@ -93,9 +91,9 @@
/** {@inheritDoc} */
@Override
- public ConditionResult approximatelyEqualTo(ByteString value)
+ public ConditionResult approximatelyEqualTo(ByteString assertionValue)
{
- return provider.approximatelyEqualTo(entry, rule, value);
+ return provider.approximatelyEqualTo(entry, rule, assertionValue);
}
@@ -116,6 +114,12 @@
return provider.hasAllValues(entry, rule, values);
}
+ /** {@inheritDoc} */
+ @Override
+ public ConditionResult matchesEqualityAssertion(ByteString assertionValue)
+ {
+ return provider.matchesEqualityAssertion(entry, rule, assertionValue);
+ }
/** {@inheritDoc} */
@@ -161,9 +165,9 @@
/** {@inheritDoc} */
@Override
- public ConditionResult greaterThanOrEqualTo(ByteString value)
+ public ConditionResult greaterThanOrEqualTo(ByteString assertionValue)
{
- return provider.greaterThanOrEqualTo(entry, rule, value);
+ return provider.greaterThanOrEqualTo(entry, rule, assertionValue);
}
@@ -224,9 +228,9 @@
/** {@inheritDoc} */
@Override
- public ConditionResult lessThanOrEqualTo(ByteString value)
+ public ConditionResult lessThanOrEqualTo(ByteString assertionValue)
{
- return provider.lessThanOrEqualTo(entry, rule, value);
+ return provider.lessThanOrEqualTo(entry, rule, assertionValue);
}
@@ -263,27 +267,6 @@
/** {@inheritDoc} */
@Override
- public int hashCode()
- {
- int hashCode = getAttributeType().hashCode();
- for (ByteString value : this)
- {
- try
- {
- final MatchingRule eqRule = attributeType.getEqualityMatchingRule();
- final ByteString nv = eqRule.normalizeAttributeValue(value);
- hashCode += nv.hashCode();
- }
- catch (DecodeException e)
- {
- logger.traceException(e);
- }
- }
- return hashCode;
- }
-
- /** {@inheritDoc} */
- @Override
public void toString(StringBuilder buffer)
{
buffer.append("VirtualAttribute(");
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java
index c85ae42..93b7b2c 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java
@@ -408,7 +408,7 @@
ByteString[] badValues = new ByteString[values.length];
System.arraycopy(values, 1, badValues, 0, values.length - 1);
badValues[badValues.length-1] = values[0];
- svs.remove(id, values, types);
+ svs.remove(id, values);
svs.add(id, badValues, types);
vlvIndex.putSortValuesSet(null, svs);
@@ -697,7 +697,7 @@
SortValuesSet svs = vlvIndex.getSortValuesSet(null, 0, new ByteString[3], types);
long id = svs.getEntryIDs()[0];
Entry entry = eContainer.getID2Entry().get(null, new EntryID(id), LockMode.DEFAULT);
- svs.remove(id, vlvIndex.getSortValues(entry), types);
+ svs.remove(id, vlvIndex.getSortValues(entry));
// Add an incorrectly ordered values.
SortValuesSet svs2 = svs.split(2);
@@ -710,7 +710,7 @@
ByteString[] badValues = new ByteString[values.length];
System.arraycopy(values, 1, badValues, 0, values.length - 1);
badValues[badValues.length-1] = values[0];
- svs.remove(id, values, types);
+ svs.remove(id, values);
svs.add(id, badValues, types);
vlvIndex.putSortValuesSet(null, svs);
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SearchFilterTests.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SearchFilterTests.java
index 3ee6816..3b2d643 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SearchFilterTests.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SearchFilterTests.java
@@ -27,26 +27,25 @@
*/
package org.opends.server.types;
-import org.forgerock.opendj.ldap.ByteString;
-import org.opends.server.DirectoryServerTestCase;
-import org.opends.server.TestCaseUtils;
-import org.opends.server.util.StaticUtils;
-import org.opends.server.util.Base64;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.RawFilter;
-import org.opends.server.core.DirectoryServer;
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeClass;
-import org.testng.Assert;
-
-import java.util.List;
+import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
-import java.text.ParseException;
+import java.util.List;
-import static java.util.Arrays.asList;
+import org.forgerock.opendj.ldap.ByteString;
+import org.opends.server.DirectoryServerTestCase;
+import org.opends.server.TestCaseUtils;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.util.Base64;
+import org.opends.server.util.StaticUtils;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static java.util.Arrays.*;
+
import static org.opends.server.util.StaticUtils.*;
import static org.testng.Assert.*;
@@ -611,7 +610,7 @@
private FilterDescription assertionFilterDescription(FilterType filterType,
String attributeType,
String attributeValue,
- List<String> matchedEntries) {
+ String... matchedEntries) {
FilterDescription description = new FilterDescription();
description.filterType = filterType;
@@ -634,8 +633,8 @@
fail(filterType + " is not handled.");
}
- description.matchedEntriesLdif = matchedEntries;
- description.unmatchedEntriesLdif = getEntriesExcluding(matchedEntries);
+ description.matchedEntriesLdif = asList(matchedEntries);
+ description.unmatchedEntriesLdif = getEntriesExcluding(description.matchedEntriesLdif);
return description;
}
@@ -643,28 +642,28 @@
private FilterDescription equalityFilterDescription(String attributeType,
String attributeValue,
- List<String> matchedEntries) {
+ String... matchedEntries) {
return assertionFilterDescription(FilterType.EQUALITY, attributeType, attributeValue, matchedEntries);
}
private FilterDescription lessEqualFilterDescription(String attributeType,
String attributeValue,
- List<String> matchedEntries) {
+ String... matchedEntries) {
return assertionFilterDescription(FilterType.LESS_OR_EQUAL, attributeType, attributeValue, matchedEntries);
}
private FilterDescription greaterEqualFilterDescription(String attributeType,
String attributeValue,
- List<String> matchedEntries) {
+ String... matchedEntries) {
return assertionFilterDescription(FilterType.GREATER_OR_EQUAL, attributeType, attributeValue, matchedEntries);
}
private FilterDescription approximateFilterDescription(String attributeType,
String attributeValue,
- List<String> matchedEntries) {
+ String... matchedEntries) {
return assertionFilterDescription(FilterType.APPROXIMATE_MATCH, attributeType, attributeValue, matchedEntries);
}
@@ -681,9 +680,12 @@
description.subInitialElement = ByteString.valueOf(subInitial);
description.subAnyElements = new ArrayList<ByteString>();
- for (int i = 0; (subAny != null) && (i < subAny.size()); i++) {
- String s = subAny.get(i);
- description.subAnyElements.add(ByteString.valueOf(s));
+ if (subAny != null)
+ {
+ for (String s : subAny)
+ {
+ description.subAnyElements.add(ByteString.valueOf(s));
+ }
}
description.subFinalElement = ByteString.valueOf(subFinal);
@@ -787,67 +789,38 @@
private List<FilterDescription> getEqualityFilters() throws Exception {
- List<FilterDescription> descriptions = new ArrayList<FilterDescription>();
-
- descriptions.add(equalityFilterDescription("sn", "Smith",
- asList(JANE_SMITH_LDIF, JOE_SMITH_LDIF)));
-
- descriptions.add(equalityFilterDescription("givenname", "Jane",
- asList(JANE_SMITH_LDIF, JANE_AUSTIN_LDIF)));
-
- return descriptions;
+ return asList(
+ equalityFilterDescription("sn", "Smith", JANE_SMITH_LDIF, JOE_SMITH_LDIF),
+ equalityFilterDescription("givenname", "Jane", JANE_SMITH_LDIF, JANE_AUSTIN_LDIF));
}
private List<FilterDescription> getApproximateFilters() throws Exception {
- List<FilterDescription> descriptions = new ArrayList<FilterDescription>();
-
- descriptions.add(approximateFilterDescription("sn", "Smythe",
- asList(JANE_SMITH_LDIF, JOE_SMITH_LDIF)));
-
- return descriptions;
+ return asList(approximateFilterDescription("sn", "Smythe", JANE_SMITH_LDIF, JOE_SMITH_LDIF));
}
private List<FilterDescription> getSubstringFilters() throws Exception {
- List<FilterDescription> descriptions = new ArrayList<FilterDescription>();
-
- descriptions.add(substringFilterDescription(
+ return asList(substringFilterDescription(
"sn",
"S", asList("i"), "th", // S*i*th
asList(JANE_SMITH_LDIF, JOE_SMITH_LDIF)));
-
- return descriptions;
}
private List<FilterDescription> getInequalityFilters() throws Exception {
- List<FilterDescription> descriptions = new ArrayList<FilterDescription>();
-
- descriptions.add(lessEqualFilterDescription("sn", "Aus",
- new ArrayList<String>()));
-
- descriptions.add(greaterEqualFilterDescription("sn", "Aus",
- asList(JANE_AUSTIN_LDIF, JOE_AUSTIN_LDIF,
- JANE_SMITH_LDIF, JOE_SMITH_LDIF)));
-
-
- descriptions.add(lessEqualFilterDescription("sn", "Smi",
- asList(JANE_AUSTIN_LDIF, JOE_AUSTIN_LDIF)));
-
- descriptions.add(greaterEqualFilterDescription("sn", "Smi",
- asList(JANE_SMITH_LDIF, JOE_SMITH_LDIF)));
-
-
- descriptions.add(lessEqualFilterDescription("sn", "Smith",
- asList(JANE_AUSTIN_LDIF, JOE_AUSTIN_LDIF,
- JANE_SMITH_LDIF, JOE_SMITH_LDIF)));
-
- descriptions.add(greaterEqualFilterDescription("sn", "Smith",
- asList(JANE_SMITH_LDIF, JOE_SMITH_LDIF)));
-
-
- return descriptions;
+ return asList(
+ lessEqualFilterDescription("sn", "Aus"),
+ greaterEqualFilterDescription("sn", "Aus",
+ JANE_AUSTIN_LDIF, JOE_AUSTIN_LDIF, JANE_SMITH_LDIF, JOE_SMITH_LDIF),
+ lessEqualFilterDescription("sn", "Smi",
+ JANE_AUSTIN_LDIF, JOE_AUSTIN_LDIF),
+ greaterEqualFilterDescription("sn", "Smi",
+ JANE_SMITH_LDIF, JOE_SMITH_LDIF),
+ lessEqualFilterDescription("sn", "Smith",
+ JANE_AUSTIN_LDIF, JOE_AUSTIN_LDIF, JANE_SMITH_LDIF, JOE_SMITH_LDIF),
+ greaterEqualFilterDescription("sn", "Smith",
+ JANE_SMITH_LDIF, JOE_SMITH_LDIF));
}
@@ -899,8 +872,7 @@
// Now convert to [][]
FilterDescription[][] descriptionArray = new FilterDescription[allDescriptions.size()][];
for (int i = 0; i < allDescriptions.size(); i++) {
- FilterDescription description = allDescriptions.get(i);
- descriptionArray[i] = new FilterDescription[]{description};
+ descriptionArray[i] = new FilterDescription[]{ allDescriptions.get(i) };
}
return descriptionArray;
@@ -913,16 +885,14 @@
for (String ldif: description.matchedEntriesLdif) {
Entry entry = TestCaseUtils.entryFromLdifString(ldif);
- if (!description.searchFilter.matchesEntry(entry)) {
- fail("Expected to match entry. " + description + entry);
- }
+ assertTrue(description.searchFilter.matchesEntry(entry),
+ "Expected to match entry. " + description + " " + entry);
}
for (String ldif: description.unmatchedEntriesLdif) {
Entry entry = TestCaseUtils.entryFromLdifString(ldif);
- if (description.searchFilter.matchesEntry(entry)) {
- fail("Should not have matched entry. " + description + entry);
- }
+ assertFalse(description.searchFilter.matchesEntry(entry),
+ "Should not have matched entry. " + description + " " + entry);
}
}
@@ -1075,7 +1045,7 @@
@DataProvider(name = "differentNormalization")
public Object[][] differentNormalizationData() throws ParseException
{
- final String BASE64_CERT_VALUE =
+ final String BASE64_CERT_VALUE =
"MIICpTCCAg6gAwIBAgIJALeoA6I3ZC/cMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV" +
"BAYTAlVTMRMwEQYDVQQHEwpDdXBlcnRpb25lMRwwGgYDVQQLExNQcm9kdWN0IERl" +
"dmVsb3BtZW50MRQwEgYDVQQDEwtCYWJzIEplbnNlbjAeFw0xMjA1MDIxNjM0MzVa" +
@@ -1091,10 +1061,10 @@
"6CD0WRmc2pBeYX2z94/PWO5L3Fx+eIZh2wTxScF+FdRWJzLbUaBuClrxuy0Y5ifj" +
"axuJ8LFNbZtsp1ldW3i84+F5+SYT+xI67ZcoAtwx/VFVI9s5I/Gkmu9f9nxjPpK7" +
"1AIUXiE3Qcck";
- final String CERT_EXACT_ASSERTION =
+ final String CERT_EXACT_ASSERTION =
"{ serialNumber 13233831500277100508, issuer rdnSequence:\""+
"CN=Babs Jensen,OU=Product Development,L=Cupertione,C=US\" }";
- final String CERTIFICATE_LDIF = TestCaseUtils.makeLdif(
+ final String LDIF_ENTRY = TestCaseUtils.makeLdif(
"dn: cn=John Smith,dc=example,dc=com",
"objectclass: inetorgperson",
"cn: John Smith",
@@ -1106,8 +1076,9 @@
final String CERTIFICATE_ENCODED = builder.toString();
return new Object[][]{
- {CERTIFICATE_LDIF, "userCertificate="+CERT_EXACT_ASSERTION, true},
- {CERTIFICATE_LDIF, "userCertificate="+CERTIFICATE_ENCODED, true}};
+ { LDIF_ENTRY, "userCertificate=" + CERT_EXACT_ASSERTION, true },
+ { LDIF_ENTRY, "userCertificate=" + CERTIFICATE_ENCODED, true },
+ };
}
@Test(dataProvider = "differentNormalization")
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SmallMapTest.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SmallMapTest.java
new file mode 100644
index 0000000..3086943
--- /dev/null
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/SmallMapTest.java
@@ -0,0 +1,249 @@
+/*
+ * 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 legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * 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 legal-notices/CDDLv1_0.txt.
+ * 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
+ *
+ * Copyright 2014 ForgeRock AS
+ */
+package org.opends.server.types;
+
+import java.util.*;
+import java.util.Map.Entry;
+
+import org.testng.annotations.Test;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.testng.Assert.*;
+
+@SuppressWarnings("javadoc")
+public class SmallMapTest
+{
+
+ @Test
+ public void testPutAndSize() throws Exception
+ {
+ SmallMap<Integer, String> map = new SmallMap<Integer, String>();
+ assertEquals(map.size(), 0);
+ assertEquals(map.put(1, "one"), null);
+ assertEquals(map.size(), 1);
+ assertEquals(map.put(1, "ONE"), "one");
+ assertEquals(map.size(), 1);
+ assertEquals(map.put(2, "two"), null);
+ assertEquals(map.size(), 2);
+ assertEquals(map.put(3, "three"), null);
+ assertEquals(map.size(), 3);
+ }
+
+ @Test(dependsOnMethods = { "testPutAndSize" })
+ public void testGet() throws Exception
+ {
+ SmallMap<Integer, String> map = new SmallMap<Integer, String>();
+ assertEquals(map.get(1), null);
+ assertEquals(map.get(2), null);
+ map.put(1, "one");
+ assertEquals(map.get(1), "one");
+ assertEquals(map.get(2), null);
+ map.put(1, "ONE");
+ assertEquals(map.get(1), "ONE");
+ assertEquals(map.get(2), null);
+ map.put(2, "two");
+ assertEquals(map.get(1), "ONE");
+ assertEquals(map.get(2), "two");
+ }
+
+ @Test(dependsOnMethods = { "testPutAndSize" })
+ public void testPutAll() throws Exception
+ {
+ final SmallMap<Integer, String> map = new SmallMap<Integer, String>();
+ final HashMap<Integer, String> hashMap = new HashMap<Integer, String>();
+ map.putAll(hashMap);
+ assertEquals(map.size(), 0);
+ hashMap.put(1, "one");
+ map.putAll(hashMap);
+ assertEquals(map.size(), 1);
+ assertEquals(map.get(1), "one");
+ }
+
+ @Test(dependsOnMethods = { "testPutAndSize" })
+ public void testRemove() throws Exception
+ {
+ SmallMap<Integer, String> map = new SmallMap<Integer, String>();
+ assertEquals(map.size(), 0);
+ assertEquals(map.remove(2), null);
+ assertEquals(map.remove(1), null);
+
+ map.put(1, "one");
+ assertEquals(map.size(), 1);
+ assertEquals(map.remove(2), null);
+ assertEquals(map.remove(1), "one");
+ assertEquals(map.size(), 0);
+
+ map.put(1, "one");
+ map.put(2, "two");
+ assertEquals(map.size(), 2);
+ assertEquals(map.remove(1), "one");
+ assertEquals(map.size(), 1);
+ }
+
+ @Test(dependsOnMethods = { "testPutAndSize" })
+ public void testContains() throws Exception
+ {
+ SmallMap<Integer, String> map = new SmallMap<Integer, String>();
+ assertDoesNotContain(map, entry(2, "two"));
+
+ map.put(1, null);
+ assertContains(map, entry(1, (String) null));
+ assertDoesNotContain(map, entry(2, "two"));
+
+ map.put(1, "one");
+ assertContains(map, entry(1, "one"));
+ assertDoesNotContain(map, entry(2, "two"));
+
+ map.put(2, "two");
+ assertContains(map, entry(1, "one"));
+ assertContains(map, entry(2, "two"));
+ assertDoesNotContain(map, entry(3, "three"));
+ }
+
+ @Test(dependsOnMethods = { "testPutAndSize" })
+ public void testClear() throws Exception
+ {
+ SmallMap<Integer, String> map = new SmallMap<Integer, String>();
+ map.clear();
+ assertEquals(map.size(), 0);
+
+ map.put(1, "one");
+ map.clear();
+ assertEquals(map.size(), 0);
+
+ map.put(1, "one");
+ map.put(2, "two");
+ map.clear();
+ assertEquals(map.size(), 0);
+ }
+
+ @Test(dependsOnMethods = { "testPutAndSize" })
+ public void testEntrySetSize() throws Exception
+ {
+ SmallMap<Integer, String> map = new SmallMap<Integer, String>();
+ assertEquals(map.entrySet().size(), 0);
+
+ map.put(1, "one");
+ assertEquals(map.entrySet().size(), 1);
+
+ map.put(1, "one");
+ map.put(2, "two");
+ assertEquals(map.entrySet().size(), 2);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test(dependsOnMethods = { "testEntrySetSize" })
+ public void testEntrySetIterator() throws Exception
+ {
+ SmallMap<Integer, String> map = new SmallMap<Integer, String>();
+ assertThat(map.entrySet().iterator()).isEmpty();
+
+ map.put(1, "one");
+ assertThat(map.entrySet().iterator()).containsExactly(
+ entry(1, "one"));
+
+ map.put(1, "one");
+ map.put(2, "two");
+ assertThat(map.entrySet().iterator()).containsExactly(
+ entry(1, "one"), entry(2, "two"));
+ }
+
+ @Test(dependsOnMethods = { "testEntrySetIterator" })
+ public void testEntrySetIteratorNextRemove() throws Exception
+ {
+ SmallMap<Integer, String> map = new SmallMap<Integer, String>();
+ map.put(1, "one");
+ Iterator<Entry<Integer, String>> iter = map.entrySet().iterator();
+ assertTrue(iter.hasNext());
+ assertNotNull(iter.next());
+ iter.remove();
+ assertFalse(iter.hasNext());
+
+ assertTrue(map.isEmpty());
+ }
+
+ @Test(dependsOnMethods = { "testEntrySetIterator" },
+ expectedExceptions = { NoSuchElementException.class })
+ public void testEntrySetIteratorNextThrowsNoSuchElementException() throws Exception
+ {
+ SmallMap<Integer, String> map = new SmallMap<Integer, String>();
+ map.put(1, "one");
+ Iterator<Entry<Integer, String>> iter = map.entrySet().iterator();
+ assertTrue(iter.hasNext());
+ iter.next();
+ assertFalse(iter.hasNext());
+ iter.next(); // throw an exception
+ }
+
+ private <K, V> Entry<K, V> entry(K key, V value)
+ {
+ return new AbstractMap.SimpleImmutableEntry<K, V>(key, value);
+ }
+
+ private void assertContains(SmallMap<Integer, String> map,
+ Entry<Integer, String> entry)
+ {
+ assertContains(map, entry, true);
+ }
+
+ private void assertDoesNotContain(SmallMap<Integer, String> map,
+ Entry<Integer, String> entry)
+ {
+ assertContains(map, entry, false);
+ }
+
+ private void assertContains(SmallMap<Integer, String> map,
+ Entry<Integer, String> entry, boolean expected)
+ {
+ assertEquals(map.containsKey(entry.getKey()), expected);
+ assertEquals(map.containsValue(entry.getValue()), expected);
+ }
+
+ @Test(expectedExceptions = { NullPointerException.class })
+ public void testGetRejectsNull() throws Exception
+ {
+ new SmallMap<Integer, String>().get(null);
+ }
+
+ @Test(expectedExceptions = { NullPointerException.class })
+ public void testContainsKeyRejectsNull() throws Exception
+ {
+ new SmallMap<Integer, String>().containsKey(null);
+ }
+
+ @Test(expectedExceptions = { NullPointerException.class })
+ public void testPutRejectsNull() throws Exception
+ {
+ new SmallMap<Integer, String>().put(null, null);
+ }
+
+ @Test(expectedExceptions = { NullPointerException.class })
+ public void testPutAllRejectsNull() throws Exception
+ {
+ final HashMap<Integer, String> map = new HashMap<Integer, String>();
+ map.put(null, null);
+ new SmallMap<Integer, String>().putAll(map);
+ }
+}
diff --git a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/TestEntry.java b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/TestEntry.java
index eddb4fdd..e5a2cbb 100644
--- a/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/TestEntry.java
+++ b/opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/types/TestEntry.java
@@ -257,11 +257,13 @@
Entry entry = createTestEntry(type, values);
Set<SubtreeSpecification> result = new HashSet<SubtreeSpecification>();
List<Attribute> attributes = entry.getAttribute(type, true);
- for (ByteString value : new AttributeValueIterable(attributes))
+ for (Attribute a : attributes)
{
- result.add(SubtreeSpecification.valueOf(rootDN, value.toString()));
+ for (ByteString value : a)
+ {
+ result.add(SubtreeSpecification.valueOf(rootDN, value.toString()));
+ }
}
-
assertEquals(expected, result);
}
--
Gitblit v1.10.0