From aa5f5b7688d3f2b3567411b214fd1a9cbb7030b1 Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Tue, 03 Nov 2015 16:49:00 +0000
Subject: [PATCH] OPENDJ-1802 Address review comments about "Make ByteStringBuilder methods"

---
 opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties                          |    8 
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java                        |   64 ++++++++--
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImpl.java |   41 ++----
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Base64.java                                   |   12 +-
 opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TimeBasedMatchingRulesImpl.java        |  182 +++++++++++++++--------------
 5 files changed, 168 insertions(+), 139 deletions(-)

diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Base64.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Base64.java
index 06c1245..8455758 100755
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Base64.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Base64.java
@@ -277,11 +277,11 @@
                     append = false;
                     switch (j) {
                     case 2:
-                        builder.appendByte(value >>> 4 & 0xFF);
+                        builder.appendByte(value >>> 4);
                         break;
                     case 3:
-                        builder.appendByte(value >>> 10 & 0xFF);
-                        builder.appendByte(value >>> 2 & 0xFF);
+                        builder.appendByte(value >>> 10);
+                        builder.appendByte(value >>> 2);
                         break;
                     }
                     break;
@@ -297,9 +297,9 @@
             }
 
             if (append) {
-                builder.appendByte(value >>> 16 & 0xFF);
-                builder.appendByte(value >>> 8 & 0xFF);
-                builder.appendByte(value & 0xFF);
+                builder.appendByte(value >>> 16);
+                builder.appendByte(value >>> 8);
+                builder.appendByte(value);
             } else {
                 break;
             }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
index ed3bc60..dccce3a 100755
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
@@ -67,7 +67,7 @@
 
         @Override
         public void write(final int i) {
-            appendByte(i & 0xFF);
+            appendByte(i);
         }
     }
 
@@ -302,6 +302,23 @@
 
     /**
      * Appends the provided byte to this byte string builder.
+     * <p>
+     * Note: this method accepts an {@code int} for ease of reading and writing.
+     * <p>
+     * This method only keeps the lowest 8-bits of the provided {@code int}.
+     * Higher bits will be truncated. This method performs the equivalent of:
+     *
+     * <pre>
+     * int i = ...;
+     * int i8bits = i & 0xFF;
+     * // only use "i8bits"
+     * </pre>
+     * OR
+     * <pre>
+     * int i = ...;
+     * byte b = (byte) i;
+     * // only use "b"
+     * </pre>
      *
      * @param b
      *            The byte to be appended to this byte string builder.
@@ -538,7 +555,7 @@
     public ByteStringBuilder appendInt(int i) {
         ensureAdditionalCapacity(4);
         for (int j = length + 3; j >= length; j--) {
-            buffer[j] = (byte) (i & 0xFF);
+            buffer[j] = (byte) i;
             i >>>= 8;
         }
         length += 4;
@@ -557,7 +574,7 @@
     public ByteStringBuilder appendLong(long l) {
         ensureAdditionalCapacity(8);
         for (int i = length + 7; i >= length; i--) {
-            buffer[i] = (byte) (l & 0xFF);
+            buffer[i] = (byte) l;
             l >>>= 8;
         }
         length += 8;
@@ -628,6 +645,23 @@
     /**
      * Appends the big-endian encoded bytes of the provided short to this byte
      * string builder.
+     * <p>
+     * Note: this method accepts an {@code int} for ease of reading and writing.
+     * <p>
+     * This method only keeps the lowest 16-bits of the provided {@code int}.
+     * Higher bits will be truncated. This method performs the equivalent of:
+     *
+     * <pre>
+     * int i = ...;
+     * int i16bits = i & 0xFFFF;
+     * // only use "i16bits"
+     * </pre>
+     * OR
+     * <pre>
+     * int i = ...;
+     * short s = (short) i;
+     * // only use "s"
+     * </pre>
      *
      * @param i
      *            The short whose big-endian encoding is to be appended to this
@@ -637,7 +671,7 @@
     public ByteStringBuilder appendShort(int i) {
         ensureAdditionalCapacity(2);
         for (int j = length + 1; j >= length; j--) {
-            buffer[j] = (byte) (i & 0xFF);
+            buffer[j] = (byte) i;
             i >>>= 8;
         }
         length += 2;
@@ -696,33 +730,33 @@
         if ((length & 0x0000007F) == length) {
             ensureAdditionalCapacity(1);
 
-            buffer[this.length++] = (byte) (length & 0xFF);
+            buffer[this.length++] = (byte) length;
         } else if ((length & 0x000000FF) == length) {
             ensureAdditionalCapacity(2);
 
             buffer[this.length++] = (byte) 0x81;
-            buffer[this.length++] = (byte) (length & 0xFF);
+            buffer[this.length++] = (byte) length;
         } else if ((length & 0x0000FFFF) == length) {
             ensureAdditionalCapacity(3);
 
             buffer[this.length++] = (byte) 0x82;
-            buffer[this.length++] = (byte) (length >> 8 & 0xFF);
-            buffer[this.length++] = (byte) (length & 0xFF);
+            buffer[this.length++] = (byte) (length >> 8);
+            buffer[this.length++] = (byte) length;
         } else if ((length & 0x00FFFFFF) == length) {
             ensureAdditionalCapacity(4);
 
             buffer[this.length++] = (byte) 0x83;
-            buffer[this.length++] = (byte) (length >> 16 & 0xFF);
-            buffer[this.length++] = (byte) (length >> 8 & 0xFF);
-            buffer[this.length++] = (byte) (length & 0xFF);
+            buffer[this.length++] = (byte) (length >> 16);
+            buffer[this.length++] = (byte) (length >> 8);
+            buffer[this.length++] = (byte) length;
         } else {
             ensureAdditionalCapacity(5);
 
             buffer[this.length++] = (byte) 0x84;
-            buffer[this.length++] = (byte) (length >> 24 & 0xFF);
-            buffer[this.length++] = (byte) (length >> 16 & 0xFF);
-            buffer[this.length++] = (byte) (length >> 8 & 0xFF);
-            buffer[this.length++] = (byte) (length & 0xFF);
+            buffer[this.length++] = (byte) (length >> 24);
+            buffer[this.length++] = (byte) (length >> 16);
+            buffer[this.length++] = (byte) (length >> 8);
+            buffer[this.length++] = (byte) length;
         }
         return this;
     }
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImpl.java
index 02e8d55..07c812f 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImpl.java
@@ -343,13 +343,11 @@
         return new DefaultSubstringAssertion(normInitial, normAnys, normFinal);
     }
 
-    ByteString normalizeSubString(final Schema schema, final ByteSequence value)
-            throws DecodeException {
+    ByteString normalizeSubString(final Schema schema, final ByteSequence value) throws DecodeException {
         return normalizeAttributeValue(schema, value);
     }
 
-    private char evaluateEscapedChar(final SubstringReader reader, final char[] escapeChars)
-            throws DecodeException {
+    private byte evaluateEscapedChar(final SubstringReader reader, final char[] escapeChars) throws DecodeException {
         final char c1 = reader.read();
         byte b;
         switch (c1) {
@@ -409,12 +407,12 @@
             break;
         default:
             if (c1 == BACKSLASH) {
-                return c1;
+                return (byte) c1;
             }
             if (escapeChars != null) {
                 for (final char escapeChar : escapeChars) {
                     if (c1 == escapeChar) {
-                        return c1;
+                        return (byte) c1;
                     }
                 }
             }
@@ -486,7 +484,7 @@
         default:
             throw DecodeException.error(ERR_HEX_DECODE_INVALID_CHARACTER.get(new String(new char[] { c1, c2 }), c1));
         }
-        return (char) b;
+        return b;
     }
 
     private ByteString evaluateEscapes(final SubstringReader reader, final char[] escapeChars) throws DecodeException {
@@ -496,18 +494,17 @@
     private ByteString evaluateEscapes(final SubstringReader reader, final char[] escapeChars,
             final char[] delimiterChars) throws DecodeException {
         int length = 0;
-        char c;
         ByteStringBuilder valueBuffer = null;
 
         reader.mark();
         while (reader.remaining() > 0) {
-            c = reader.read();
+            char c = reader.read();
             if (c == BACKSLASH) {
                 if (valueBuffer == null) {
                     valueBuffer = new ByteStringBuilder();
                 }
                 valueBuffer.appendUtf8(reader.read(length));
-                valueBuffer.appendInt(evaluateEscapedChar(reader, escapeChars));
+                valueBuffer.appendByte(evaluateEscapedChar(reader, escapeChars));
                 reader.mark();
                 length = 0;
                 continue;
@@ -515,32 +512,26 @@
             if (delimiterChars != null) {
                 for (final char delimiterChar : delimiterChars) {
                     if (c == delimiterChar) {
-                        reader.reset();
-                        if (valueBuffer != null) {
-                            valueBuffer.appendUtf8(reader.read(length));
-                            return valueBuffer.toByteString();
-                        } else {
-                            if (length > 0) {
-                                return ByteString.valueOf(reader.read(length));
-                            }
-                            return ByteString.empty();
-                        }
+                        return evaluateEscapes0(reader, length, valueBuffer);
                     }
                 }
             }
             length++;
         }
 
+        return evaluateEscapes0(reader, length, valueBuffer);
+    }
+
+    private ByteString evaluateEscapes0(final SubstringReader reader, int length, ByteStringBuilder valueBuffer) {
         reader.reset();
         if (valueBuffer != null) {
             valueBuffer.appendUtf8(reader.read(length));
             return valueBuffer.toByteString();
-        } else {
-            if (length > 0) {
-                return ByteString.valueOf(reader.read(length));
-            }
-            return ByteString.empty();
         }
+        if (length > 0) {
+            return ByteString.valueOf(reader.read(length));
+        }
+        return ByteString.empty();
     }
 
     @Override
diff --git a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TimeBasedMatchingRulesImpl.java b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TimeBasedMatchingRulesImpl.java
index 67762c8..4d2cd30 100644
--- a/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TimeBasedMatchingRulesImpl.java
+++ b/opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TimeBasedMatchingRulesImpl.java
@@ -26,7 +26,6 @@
  */
 package org.forgerock.opendj.ldap.schema;
 
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collection;
@@ -38,6 +37,7 @@
 import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.opendj.ldap.Assertion;
 import org.forgerock.opendj.ldap.ByteSequence;
+import org.forgerock.opendj.ldap.ByteSequenceReader;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
 import org.forgerock.opendj.ldap.ConditionResult;
@@ -53,9 +53,7 @@
 import static org.forgerock.opendj.ldap.DecodeException.*;
 import static org.forgerock.opendj.ldap.schema.SchemaConstants.*;
 
-/**
- * Implementations of time-based matching rules.
- */
+/** Implementations of time-based matching rules. */
 final class TimeBasedMatchingRulesImpl {
 
     private static final TimeZone TIME_ZONE_UTC = TimeZone.getTimeZone("UTC");
@@ -65,7 +63,7 @@
     private static final char MINUTE = 'm';
     private static final char HOUR = 'h';
     private static final char MONTH = 'M';
-    private static final char DATE = 'D';
+    private static final char DAY = 'D';
     private static final char YEAR = 'Y';
 
     private TimeBasedMatchingRulesImpl() {
@@ -99,15 +97,12 @@
         return new PartialDateAndTimeMatchingRuleImpl();
     }
 
-    /**
-     * This class defines a matching rule which is used for time-based searches.
-     */
+    /** This class defines a matching rule which is used for time-based searches. */
     private static abstract class TimeBasedMatchingRuleImpl extends AbstractMatchingRuleImpl {
 
         /** Unit tests can inject fake timestamps if necessary. */
         final TimeService timeService = TimeService.SYSTEM;
 
-        /** {@inheritDoc} */
         @Override
         public final ByteString normalizeAttributeValue(Schema schema, ByteSequence value) throws DecodeException {
             try {
@@ -123,14 +118,11 @@
         }
     }
 
-    /**
-     * Defines the relative time ordering matching rule.
-     */
+    /** Defines the relative time ordering matching rule. */
     private static abstract class RelativeTimeOrderingMatchingRuleImpl extends TimeBasedMatchingRuleImpl {
 
         final Indexer indexer = new DefaultIndexer(EMR_GENERALIZED_TIME_NAME);
 
-        /** {@inheritDoc} */
         @Override
         public Collection<? extends Indexer> createIndexers(IndexingOptions options) {
             return Collections.singletonList(indexer);
@@ -229,13 +221,10 @@
 
     }
 
-    /**
-     * Defines the "greater-than" relative time matching rule.
-     */
+    /** Defines the "greater-than" relative time matching rule. */
     private static final class RelativeTimeGreaterThanOrderingMatchingRuleImpl extends
         RelativeTimeOrderingMatchingRuleImpl {
 
-        /** {@inheritDoc} */
         @Override
         public Assertion getAssertion(final Schema schema, final ByteSequence value) throws DecodeException {
             final ByteString assertionValue = normalizeAssertionValue(value);
@@ -255,13 +244,10 @@
         }
     }
 
-    /**
-     * Defines the "less-than" relative time matching rule.
-     */
+    /** Defines the "less-than" relative time matching rule. */
     private static final class RelativeTimeLessThanOrderingMatchingRuleImpl extends
         RelativeTimeOrderingMatchingRuleImpl {
 
-        /** {@inheritDoc} */
         @Override
         public Assertion getAssertion(final Schema schema, final ByteSequence value) throws DecodeException {
             final ByteString assertionValue = normalizeAssertionValue(value);
@@ -281,20 +267,16 @@
         }
     }
 
-    /**
-     * Defines the partial date and time matching rule.
-     */
+    /** Defines the partial date and time matching rule. */
     private static final class PartialDateAndTimeMatchingRuleImpl extends TimeBasedMatchingRuleImpl {
 
         private final Indexer indexer = new PartialDateAndTimeIndexer(this);
 
-        /** {@inheritDoc} */
         @Override
         public Collection<? extends Indexer> createIndexers(IndexingOptions options) {
             return Collections.singletonList(indexer);
         }
 
-        /** {@inheritDoc} */
         @Override
         public Assertion getAssertion(final Schema schema, final ByteSequence value) throws DecodeException {
             final ByteString assertionValue = normalizeAssertionValue(value);
@@ -307,38 +289,46 @@
 
                 @Override
                 public <T> T createIndexQuery(IndexQueryFactory<T> factory) throws DecodeException {
-                    final ByteBuffer buffer = ByteBuffer.wrap(assertionValue.toByteArray());
-                    int assertSecond = buffer.getInt(0);
-                    int assertMinute = buffer.getInt(4);
-                    int assertHour = buffer.getInt(8);
-                    int assertDate = buffer.getInt(12);
-                    int assertMonth = buffer.getInt(16);
-                    int assertYear = buffer.getInt(20);
+                    final ByteSequenceReader reader = assertionValue.asReader();
+                    int assertSecond = reader.get();
+                    int assertMinute = reader.get();
+                    int assertHour = reader.get();
+                    int assertDay = reader.get();
+                    int assertMonth = reader.get();
+                    int assertYear = (int) reader.getCompactUnsigned();
 
                     List<T> queries = new ArrayList<>();
                     if (assertSecond >= 0) {
-                        queries.add(createExactMatchQuery(factory, assertSecond, SECOND));
+                        queries.add(createExactMatchByteQuery(factory, assertSecond, SECOND));
                     }
                     if (assertMinute >= 0) {
-                        queries.add(createExactMatchQuery(factory, assertMinute, MINUTE));
+                        queries.add(createExactMatchByteQuery(factory, assertMinute, MINUTE));
                     }
                     if (assertHour >= 0) {
-                        queries.add(createExactMatchQuery(factory, assertHour, HOUR));
+                        queries.add(createExactMatchByteQuery(factory, assertHour, HOUR));
                     }
-                    if (assertDate > 0) {
-                        queries.add(createExactMatchQuery(factory, assertDate, DATE));
+                    if (assertDay > 0) {
+                        queries.add(createExactMatchByteQuery(factory, assertDay, DAY));
                     }
                     if (assertMonth >= 0) {
-                        queries.add(createExactMatchQuery(factory, assertMonth, MONTH));
+                        queries.add(createExactMatchByteQuery(factory, assertMonth, MONTH));
                     }
                     if (assertYear > 0) {
-                        queries.add(createExactMatchQuery(factory, assertYear, YEAR));
+                        queries.add(createExactMatchCompactUnsignedQuery(factory, assertYear, YEAR));
                     }
                     return factory.createIntersectionQuery(queries);
                 }
 
-                private <T> T createExactMatchQuery(IndexQueryFactory<T> factory, int assertionValue, char type) {
-                    return factory.createExactMatchQuery(indexer.getIndexID(), getKey(assertionValue, type));
+                private <T> T createExactMatchByteQuery(
+                        IndexQueryFactory<T> factory, int assertionValue, char type) {
+                    return factory.createExactMatchQuery(
+                            indexer.getIndexID(), byteKey(assertionValue, type));
+                }
+
+                private <T> T createExactMatchCompactUnsignedQuery(
+                        IndexQueryFactory<T> factory, int assertionValue, char type) {
+                    return factory.createExactMatchQuery(
+                            indexer.getIndexID(), compactUnsignedKey(assertionValue, type));
                 }
             };
         }
@@ -366,14 +356,14 @@
          * The normalized value is actually the format of : smhDMY.
          */
         private ByteString normalizeAssertionValue(ByteSequence assertionValue) throws DecodeException {
-            final int initDate = 0;
+            final int initDay = 0;
             final int initValue = -1;
             int second = initValue;
             int minute = initValue;
             int hour = initValue;
-            int date = initDate;
+            int day = initDay;
             int month = initValue;
-            int year = initDate;
+            int year = initDay;
             int number = 0;
 
             int length = assertionValue.length();
@@ -385,29 +375,29 @@
                     switch (b) {
                     case 's':
                         if (second != initValue) {
-                            throw error(WARN_ATTR_DUPLICATE_SECOND_ASSERTION_FORMAT.get(assertionValue, date));
+                            throw error(WARN_ATTR_DUPLICATE_SECOND_ASSERTION_FORMAT.get(assertionValue, day));
                         }
                         second = number;
                         break;
                     case 'm':
                         if (minute != initValue) {
-                            throw error(WARN_ATTR_DUPLICATE_MINUTE_ASSERTION_FORMAT.get(assertionValue, date));
+                            throw error(WARN_ATTR_DUPLICATE_MINUTE_ASSERTION_FORMAT.get(assertionValue, day));
                         }
                         minute = number;
                         break;
                     case 'h':
                         if (hour != initValue) {
-                            throw error(WARN_ATTR_DUPLICATE_HOUR_ASSERTION_FORMAT.get(assertionValue, date));
+                            throw error(WARN_ATTR_DUPLICATE_HOUR_ASSERTION_FORMAT.get(assertionValue, day));
                         }
                         hour = number;
                         break;
                     case 'D':
                         if (number == 0) {
-                            throw error(WARN_ATTR_INVALID_DATE_ASSERTION_FORMAT.get(assertionValue, number));
-                        } else if (date != initDate) {
-                            throw error(WARN_ATTR_DUPLICATE_DATE_ASSERTION_FORMAT.get(assertionValue, date));
+                            throw error(WARN_ATTR_INVALID_DAY_ASSERTION_FORMAT.get(assertionValue, number));
+                        } else if (day != initDay) {
+                            throw error(WARN_ATTR_DUPLICATE_DAY_ASSERTION_FORMAT.get(assertionValue, day));
                         }
-                        date = number;
+                        day = number;
                         break;
                     case 'M':
                         if (number == 0) {
@@ -420,7 +410,7 @@
                     case 'Y':
                         if (number == 0) {
                             throw error(WARN_ATTR_INVALID_YEAR_ASSERTION_FORMAT.get(assertionValue, number));
-                        } else if (year != initDate) {
+                        } else if (year != initDay) {
                             throw error(WARN_ATTR_DUPLICATE_YEAR_ASSERTION_FORMAT.get(assertionValue, year));
                         }
                         year = number;
@@ -434,14 +424,14 @@
 
             month = toCalendarMonth(month, assertionValue);
 
-            // Validate year, month , date , hour, minute and second in that order.
+            // Validate year, month , day , hour, minute and second in that order.
             // -1 values are allowed when these values have not been provided
             if (year < 0) {
                 // A future date is allowed.
                 throw error(WARN_ATTR_INVALID_YEAR_ASSERTION_FORMAT.get(assertionValue, year));
             }
-            if (isDateInvalid(date, month, year)) {
-                throw error(WARN_ATTR_INVALID_DATE_ASSERTION_FORMAT.get(assertionValue, date));
+            if (isDayInvalid(day, month, year)) {
+                throw error(WARN_ATTR_INVALID_DAY_ASSERTION_FORMAT.get(assertionValue, day));
             }
             if (hour < initValue || hour > 23) {
                 throw error(WARN_ATTR_INVALID_HOUR_ASSERTION_FORMAT.get(assertionValue, hour));
@@ -455,14 +445,15 @@
             }
 
             // Since we reached here we have a valid assertion value.
-            // Construct a normalized value in the order: SECOND MINUTE HOUR DATE MONTH YEAR.
-            return new ByteStringBuilder(6 * 4)
-                .appendInt(second).appendInt(minute).appendInt(hour)
-                .appendInt(date).appendInt(month).appendInt(year).toByteString();
+            // Construct a normalized value in the order: SECOND MINUTE HOUR DAY MONTH YEAR.
+            // Using compact unsigned for year will use only two bytes until the year 16384 :)
+            return new ByteStringBuilder(5 + 2)
+                .appendByte(second).appendByte(minute).appendByte(hour)
+                .appendByte(day).appendByte(month).appendCompactUnsigned(year).toByteString();
         }
 
-        private boolean isDateInvalid(int date, int month, int year) {
-            switch (date) {
+        private boolean isDayInvalid(int day, int month, int year) {
+            switch (day) {
             case 29:
                 return month == Calendar.FEBRUARY && !isLeapYear(year);
             case 30:
@@ -477,7 +468,7 @@
                     && month != Calendar.OCTOBER
                     && month != Calendar.DECEMBER;
             default:
-                return date < 0 || date > 31;
+                return day < 0 || day > 31;
             }
         }
 
@@ -504,29 +495,27 @@
             int second = cal.get(Calendar.SECOND);
             int minute = cal.get(Calendar.MINUTE);
             int hour = cal.get(Calendar.HOUR_OF_DAY);
-            int date = cal.get(Calendar.DATE);
+            int day = cal.get(Calendar.DAY_OF_MONTH);
             int month = cal.get(Calendar.MONTH);
             int year = cal.get(Calendar.YEAR);
 
             // Build the information from the assertion value.
-            ByteBuffer b = ByteBuffer.wrap(assertionValue.toByteArray());
-            int assertSecond = b.getInt(0);
-            int assertMinute = b.getInt(4);
-            int assertHour = b.getInt(8);
-            int assertDate = b.getInt(12);
-            int assertMonth = b.getInt(16);
-            int assertYear = b.getInt(20);
+            ByteSequenceReader r = assertionValue.asReader();
+            int assertSecond = r.get();
+            int assertMinute = r.get();
+            int assertHour = r.get();
+            int assertDay = r.get();
+            int assertMonth = r.get();
+            int assertYear = (int) r.getCompactUnsigned();
 
             // All the non-zero and non -1 values should match.
-            if ((assertSecond != -1 && assertSecond != second)
-                || (assertMinute != -1 && assertMinute != minute)
-                || (assertHour != -1 && assertHour != hour)
-                || (assertDate != 0 && assertDate != date)
-                || (assertMonth != -1 && assertMonth != month)
-                || (assertYear != 0 && assertYear != year)) {
-                return ConditionResult.FALSE;
-            }
-            return ConditionResult.TRUE;
+            return ConditionResult.valueOf(
+                (assertSecond == -1 || assertSecond == second)
+                    && (assertMinute == -1 || assertMinute == minute)
+                    && (assertHour == -1 || assertHour == hour)
+                    && (assertDay == 0 || assertDay == day)
+                    && (assertMonth == -1 || assertMonth == month)
+                    && (assertYear == 0 || assertYear == year));
         }
 
         /**
@@ -550,7 +539,7 @@
             addKeyIfNotZero(keys, cal, Calendar.SECOND, SECOND);
             addKeyIfNotZero(keys, cal, Calendar.MINUTE, MINUTE);
             addKeyIfNotZero(keys, cal, Calendar.HOUR_OF_DAY, HOUR);
-            addKeyIfNotZero(keys, cal, Calendar.DATE, DATE);
+            addKeyIfNotZero(keys, cal, Calendar.DAY_OF_MONTH, DAY);
             addKeyIfNotZero(keys, cal, Calendar.MONTH, MONTH);
             addKeyIfNotZero(keys, cal, Calendar.YEAR, YEAR);
         }
@@ -558,18 +547,35 @@
         private void addKeyIfNotZero(Collection<ByteString> keys, GregorianCalendar cal, int calField, char type) {
             int value = cal.get(calField);
             if (value >= 0) {
-                keys.add(getKey(value, type));
+                switch (type) {
+                case SECOND:
+                case MINUTE:
+                case HOUR:
+                case DAY:
+                case MONTH:
+                    keys.add(byteKey(value, type));
+                    break;
+
+                case YEAR:
+                    keys.add(compactUnsignedKey(value, type));
+                    break;
+
+                default:
+                    break;
+                }
             }
         }
 
-        private ByteString getKey(int value, char type) {
-            return new ByteStringBuilder().appendInt(type).appendInt(value).toByteString();
+        private ByteString byteKey(int value, char type) {
+            return new ByteStringBuilder().appendInt(type).appendByte(value).toByteString();
+        }
+
+        private ByteString compactUnsignedKey(long value, char type) {
+            return new ByteStringBuilder().appendInt(type).appendCompactUnsigned(value).toByteString();
         }
     }
 
-    /**
-     * Indexer for Partial Date and Time Matching rules.
-     */
+    /** Indexer for Partial Date and Time Matching rules. */
     private static final class PartialDateAndTimeIndexer implements Indexer {
 
         private final PartialDateAndTimeMatchingRuleImpl matchingRule;
@@ -578,7 +584,6 @@
             this.matchingRule = matchingRule;
         }
 
-        /** {@inheritDoc} */
         @Override
         public void createKeys(Schema schema, ByteSequence value, Collection<ByteString> keys) {
             matchingRule.timeKeys(value, keys);
@@ -589,7 +594,6 @@
             return key.toByteString().toHexString();
         }
 
-        /** {@inheritDoc} */
         @Override
         public String getIndexID() {
             return MR_PARTIAL_DATE_AND_TIME_NAME;
diff --git a/opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties b/opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
index 01b41a8..dfae9ea 100755
--- a/opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
+++ b/opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
@@ -1612,12 +1612,12 @@
 WARN_ATTR_DUPLICATE_HOUR_ASSERTION_FORMAT=The provided \
  value "%s" could not be parsed as a valid assertion value because there is \
  conflicting value "%d" for h (hour) specification
-WARN_ATTR_INVALID_DATE_ASSERTION_FORMAT=The provided \
+WARN_ATTR_INVALID_DAY_ASSERTION_FORMAT=The provided \
  value "%s" could not be parsed as a valid assertion value because "%d" is not \
- a valid date specification
-WARN_ATTR_DUPLICATE_DATE_ASSERTION_FORMAT=The provided \
+ a valid day specification
+WARN_ATTR_DUPLICATE_DAY_ASSERTION_FORMAT=The provided \
  value "%s" could not be parsed as a valid assertion value because there is \
- conflicting value "%d" for DD (date) specification
+ conflicting value "%d" for DD (day of month) specification
 WARN_ATTR_INVALID_MONTH_ASSERTION_FORMAT=The provided \
  value "%s" could not be parsed as a valid assertion value because "%d" is not \
  a valid month specification

--
Gitblit v1.10.0