You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2009/05/29 13:45:55 UTC
svn commit: r779936 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/query/lucene/DecimalField.java
test/java/org/apache/jackrabbit/core/query/lucene/DecimalConvertTest.java
Author: thomasm
Date: Fri May 29 11:45:55 2009
New Revision: 779936
URL: http://svn.apache.org/viewvc?rev=779936&view=rev
Log:
JCR-1609: new Property Types (BigDecimal to sortable String and back)
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DecimalField.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/DecimalConvertTest.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DecimalField.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DecimalField.java?rev=779936&r1=779935&r2=779936&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DecimalField.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/DecimalField.java Fri May 29 11:45:55 2009
@@ -21,32 +21,29 @@
/**
* The <code>DecimalField</code> class is a utility to convert
- * <code>java.math.BigDecimal</code> values into <code>String</code>
+ * <code>java.math.BigDecimal</code> values to <code>String</code>
* values that are lexicographically sortable according to the decimal value.
* <p>
- * The string format only uses the digits '0' to '9' (except the last character
- * for negative values) and contains the following elements:
+ * The string format uses the characters '0' to '9' and consists of:
* <pre>
- * { signum of value + 2 (1 character; decimal) }
- * { signum of exponent + 2 (1 character; decimal) }
- * { length of exponent - 1 (1 character; decimal) }
- * { unsigned exponent (decimal) }
- * { unsigned value (decimal) }
- * { 'n' if negated }
+ * { value signum +2 }
+ * { exponent signum +2 }
+ * { exponent length -1 }
+ * { exponent value }
+ * { value (-1 if inverted) }
* </pre>
- * If the signum is zero, then the value is zero and that's it. The same goes
- * for the exponent: it is only encoded if the signum of the exponent is not 0.
- * If the signum is -1, the rest of the string is "negated" character by
- * character as follows: '0' is converted to '9', '1' to '8', and so on. The
- * same applies to the exponent.
+ * Only the signum is encoded if the value is zero. The exponent is not
+ * encoded if zero. Negative values are "inverted" character by character
+ * ('0' -> 9, '1' -> '8', and so on). The same applies to the exponent.
* <p>
* Examples:
- * Decimal 0: String "2"
- * Decimal 2: String "322": Signum 1; exponent 0; value 2)
- * Decimal 123: String "3302123": Signum 1; exponent 2 which is
- * encoded as signum 3, length 1, value 2; value 123).
- * Decimal -1: String "178n": Signum -1, the rest is negated;
- * exponent 0 ("2" negated); value 1 ("1" negated).
+ * 0 => "2"
+ * 2 => "322" (signum 1; exponent 0; value 2)
+ * 120 => "330212" (signum 1; exponent signum 1, length 1, value 2; value 12).
+ * -1 => "179" (signum -1, rest inverted; exponent 0; value 1 (-1, inverted).
+ * <p>
+ * Values between BigDecimal(BigInteger.ONE, Integer.MIN_VALUE) and
+ * BigDecimal(BigInteger.ONE, Integer.MAX_VALUE) are supported.
*/
public class DecimalField {
@@ -57,12 +54,9 @@
* @return the String
*/
public static String decimalToString(BigDecimal value) {
- // sign (1: negative, 2: zero, 3: positive)
switch (value.signum()) {
case -1:
- // without the 'n', the string representation of -101
- // is larger than the string representation of -100
- return "1" + negate(positiveDecimalToString(value.negate())) + "n";
+ return "1" + invert(positiveDecimalToString(value.negate()), 1);
case 0:
return "2";
default:
@@ -77,68 +71,50 @@
* @return the BigDecimal
*/
public static BigDecimal stringToDecimal(String value) {
- int signum = value.charAt(0) - '2';
- if (signum == 0) {
+ int sig = value.charAt(0) - '2';
+ if (sig == 0) {
return BigDecimal.ZERO;
- } else if (signum < 0) {
- value = negate(value).substring(0, value.length() - 1);
+ } else if (sig < 0) {
+ value = invert(value, 1);
}
- int expSignum = value.charAt(1) - '2';
- long exp;
- if (expSignum == 0) {
+ long expSig = value.charAt(1) - '2', exp;
+ if (expSig == 0) {
exp = 0;
value = value.substring(2);
} else {
- String e = value.substring(2, 3);
- if (expSignum < 0) {
- e = negate(e);
- }
- int expSize = e.charAt(0) - '0' + 1;
- e = value.substring(3, 3 + expSize);
- if (expSignum < 0) {
- e = negate(e);
- }
- exp = Long.parseLong(e);
- if (expSignum < 0) {
- exp = -exp;
+ int expSize = value.charAt(2) - '0' + 1;
+ if (expSig < 0) {
+ expSize = 11 - expSize;
}
+ String e = value.substring(3, 3 + expSize);
+ exp = expSig * Long.parseLong(expSig < 0 ? invert(e, 0) : e);
value = value.substring(3 + expSize);
}
+ BigInteger x = new BigInteger(value);
int scale = (int) (value.length() - exp - 1);
- BigInteger unscaled = new BigInteger(value.substring(0));
- if (signum < 0) {
- unscaled = unscaled.negate();
- }
- return new BigDecimal(unscaled, scale);
+ return new BigDecimal(sig < 0 ? x.negate() : x, scale);
}
private static String positiveDecimalToString(BigDecimal value) {
StringBuilder buff = new StringBuilder();
- int precision = value.precision();
- int scale = value.scale();
- long exp = precision - scale - 1;
+ long exp = value.precision() - value.scale() - 1;
// exponent signum and size
if (exp == 0) {
buff.append('2');
} else {
- // exponent
String e = String.valueOf(Math.abs(exp));
// exponent size is prepended
e = String.valueOf(e.length() - 1) + e;
// exponent signum
if (exp > 0) {
- buff.append('3');
+ buff.append('3').append(e);
} else {
- buff.append('1');
- // the exponent is negated
- e = negate(e);
+ buff.append('1').append(invert(e, 0));
}
- buff.append(e);
}
- // the unscaled value
String s = value.unscaledValue().toString();
- int max = s.length() - 1;
// remove trailing 0s
+ int max = s.length() - 1;
while (s.charAt(max) == '0') {
max--;
}
@@ -146,17 +122,18 @@
}
/**
- * "Negate" a number digit by digit (0 becomes 9, 9 becomes 0, and so on).
+ * "Invert" a number digit by digit (0 becomes 9, 9 becomes 0, and so on).
*
* @param s the original string
+ * @param incLast how much to increment the last character
* @return the negated string
*/
- private static String negate(String s) {
- // negate character by character
+ private static String invert(String s, int incLast) {
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
chars[i] = (char) ('9' - chars[i] + '0');
}
+ chars[chars.length - 1] += incLast;
return String.valueOf(chars);
}
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/DecimalConvertTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/DecimalConvertTest.java?rev=779936&r1=779935&r2=779936&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/DecimalConvertTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/lucene/DecimalConvertTest.java Fri May 29 11:45:55 2009
@@ -32,7 +32,7 @@
public void testCommon() {
// System.out.println(DecimalField.decimalToString(new BigDecimal(0)));
// System.out.println(DecimalField.decimalToString(new BigDecimal(2)));
- // System.out.println(DecimalField.decimalToString(new BigDecimal(123)));
+ // System.out.println(DecimalField.decimalToString(new BigDecimal(120)));
// System.out.println(DecimalField.decimalToString(new BigDecimal(-1)));
ArrayList<BigDecimal> list = new ArrayList<BigDecimal>();
@@ -62,6 +62,8 @@
list.add(BigDecimal.ZERO);
list.add(BigDecimal.ONE);
list.add(BigDecimal.TEN);
+ list.add(new BigDecimal(BigInteger.ONE, Integer.MAX_VALUE));
+ list.add(new BigDecimal(BigInteger.ONE, Integer.MIN_VALUE));
Random random = new Random(1);
// a few regular values
for (int i = 0; i < 10000; i++) {
@@ -103,7 +105,9 @@
}
}
BigDecimal test = DecimalField.stringToDecimal(s);
- assertEquals(d + "<>" + test, test.compareTo(d), 0);
+ if (test.compareTo(d) != 0) {
+ assertEquals(d + "<>" + test.toPlainString(), 0, test.compareTo(d));
+ }
lastDecimal = d;
lastString = s;
}