[Mulgara-svn] r1177 - trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa

pag at mulgara.org pag at mulgara.org
Tue Aug 26 05:41:35 UTC 2008


Author: pag
Date: 2008-08-25 22:41:34 -0700 (Mon, 25 Aug 2008)
New Revision: 1177

Modified:
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalFactory.java
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalImpl.java
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalUnitTest.java
Log:
Updated xsd:decimal to handle full decimal values, using BigDecimal as the underlying data type. Now differentiates between xsd:decimal and all the extending types, which can only encode integral value.

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalFactory.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalFactory.java	2008-08-25 11:18:25 UTC (rev 1176)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalFactory.java	2008-08-26 05:41:34 UTC (rev 1177)
@@ -65,8 +65,13 @@
   @SuppressWarnings("unused")
   private final static Logger logger = Logger.getLogger(SPDecimalFactory.class);
 
+  private final static URI XSD_DEC = URI.create(XSD.NAMESPACE + "decimal");
+  private final static int XSD_DEC_ID;
+  private final static URI XSD_DEC_SHORT = URI.create(XSDAbbrev.NAMESPACE + "decimal");
+  private final static int XSD_DEC_SHORT_ID;
+
   private final static URI[] TYPE_URIS = {
-      URI.create(XSD.NAMESPACE + "decimal"),
+      XSD_DEC,
       URI.create(XSD.NAMESPACE + "integer"),
       URI.create(XSD.NAMESPACE + "nonPositiveInteger"),
       URI.create(XSD.NAMESPACE + "negativeInteger"),
@@ -81,7 +86,7 @@
       URI.create(XSD.NAMESPACE + "unsignedByte"),
       URI.create(XSD.NAMESPACE + "positiveInteger"),
       // Hacks to pick up on missing namespaces
-      URI.create(XSDAbbrev.NAMESPACE + "decimal"),
+      XSD_DEC_SHORT,
       URI.create(XSDAbbrev.NAMESPACE + "integer"),
       URI.create(XSDAbbrev.NAMESPACE + "nonPositiveInteger"),
       URI.create(XSDAbbrev.NAMESPACE + "negativeInteger"),
@@ -100,11 +105,16 @@
 
   private final static Map<URI,Integer> uriToSubtypeIdMap;
   static {
+    int decId = 0, decShortId = 0;
     // Populate the uriToSubtypeIdMap.
     uriToSubtypeIdMap = new HashMap<URI,Integer>();
     for (int i = 0; i < TYPE_URIS.length; ++i) {
       uriToSubtypeIdMap.put(TYPE_URIS[i], new Integer(i));
+      if (TYPE_URIS[i].equals(XSD_DEC)) decId = i;
+      if (TYPE_URIS[i].equals(XSD_DEC_SHORT)) decShortId = i;
     }
+    XSD_DEC_ID = decId;
+    XSD_DEC_SHORT_ID = decShortId;
   }
 
 
@@ -126,7 +136,11 @@
     if (subtypeIdI == null) {
       throw new IllegalArgumentException("Invalid type URI: " + typeURI);
     }
-    return new SPDecimalImpl(subtypeIdI.intValue(), typeURI, lexicalForm);
+    if (subtypeIdI == XSD_DEC_ID || subtypeIdI == XSD_DEC_SHORT_ID) {
+      return new SPDecimalBaseImpl(subtypeIdI, typeURI, lexicalForm);
+    } else {
+      return new SPDecimalExtImpl(subtypeIdI, typeURI, lexicalForm);
+    }
   }
 
 
@@ -134,7 +148,11 @@
     if (subtypeId < 0 || subtypeId >= TYPE_URIS.length) {
       throw new IllegalArgumentException("Invalid subtype ID: " + subtypeId);
     }
-    return new SPDecimalImpl(subtypeId, TYPE_URIS[subtypeId], data);
+    if (subtypeId == XSD_DEC_ID || subtypeId == XSD_DEC_SHORT_ID) {
+      return new SPDecimalBaseImpl(subtypeId, TYPE_URIS[subtypeId], data);
+    } else {
+      return new SPDecimalExtImpl(subtypeId, TYPE_URIS[subtypeId], data);
+    }
   }
 
 }

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalImpl.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalImpl.java	2008-08-25 11:18:25 UTC (rev 1176)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalImpl.java	2008-08-26 05:41:34 UTC (rev 1177)
@@ -27,6 +27,7 @@
 package org.mulgara.store.stringpool.xa;
 
 // Java 2 standard packages
+import java.math.BigDecimal;
 import java.net.URI;
 import java.nio.ByteBuffer;
 
@@ -40,140 +41,380 @@
 
 /**
  * An SPTypedLiteral that represents xsd:decimal literals.
- * TODO This is currently implemented as a 64 bit (long) value.  xsd:decimal
- * and xsd:integer are not properly supported by this class.
- * Also, decimal places are not held for floating point values, meaning
- * that these values are not round-tripped.
  *
  * @created 2004-10-05
- *
  * @author David Makepeace
- *
- * @version $Revision: 1.1 $
- *
- * @modified $Date: 2005/03/11 04:15:22 $
- *
- * @maintenanceAuthor $Author: raboczi $
- *
  * @company <A href="mailto:info at PIsoftware.com">Plugged In Software</A>
- *
- * @copyright &copy; 2004 <A href="http://www.PIsoftware.com/">Plugged In
- *      Software Pty Ltd</A>
- *
+ * @copyright &copy; 2004 <A href="http://www.PIsoftware.com/">Plugged In Software Pty Ltd</A>
  * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
  */
-public final class SPDecimalImpl extends AbstractSPTypedLiteral {
+public abstract class SPDecimalImpl extends AbstractSPTypedLiteral {
 
   @SuppressWarnings("unused")
   private final static Logger logger = Logger.getLogger(SPDecimalImpl.class);
 
-  private long l;
-  
+  /** An ID used for all Decimal types */
   static final int TYPE_ID = 2; // Unique ID
 
+  /** The offset into the byte buffer to find out the encoding used for this data. */
+  static final int END_IDX = Constants.SIZEOF_LONG;
 
-  SPDecimalImpl(int subtypeId, URI typeURI, long l) {
+  /**
+   * Common abstract constructor for all decimal types.
+   * @param subtypeId The subtype, this is the ID for either the full or abbreviated URI.
+   * @param typeURI The full URI for the data type.
+   */
+  SPDecimalImpl(int subtypeId, URI typeURI) {
     super(TYPE_ID, subtypeId, typeURI);
-    this.l = l;
   }
 
 
-  SPDecimalImpl(int subtypeId, URI typeURI, ByteBuffer data) {
-    super(TYPE_ID, subtypeId, typeURI);
-    this.l = data.getLong();
+  /**
+   * Reads a byte buffer and converts to a BigDecimal, regardless of formatting.
+   * @param bb The byte buffer to decode.
+   * @return A BigDecimal representing the stored number.
+   */
+  static BigDecimal decode(ByteBuffer bb) {
+    ByteBuffer number = bb;
+    if (bb.limit() == END_IDX + 1) {
+      byte type = bb.get(END_IDX);
+      if (type == SPDecimalExtImpl.END_BYTE) {
+        return BigDecimal.valueOf(bb.getLong());
+      }
+      bb.limit(END_IDX);
+      number = bb.slice();
+    }
+    return new BigDecimal(CHARSET.decode(number).toString());
   }
 
+}
 
-  SPDecimalImpl(int subtypeId, URI typeURI, String lexicalForm) {
-    super(TYPE_ID, subtypeId, typeURI);
-    if (lexicalForm.charAt(0) == '+') lexicalForm = lexicalForm.substring(1);
-    int decPos = lexicalForm.indexOf('.');
-    if (decPos < 0) {
-      l = Long.valueOf(lexicalForm);
-    } else {
-      for (int i = decPos + 1; i < lexicalForm.length(); i++) {
-        if (lexicalForm.charAt(i) != '0') throw new NumberFormatException("Fractional value in integer: " + lexicalForm);
-      }
-      l = Long.valueOf(lexicalForm.substring(0, decPos));
+
+/**
+ * This class represents xsd:decimal.
+ * The data format is as a string. If the string is exactly the length of a Long
+ * (the other format available) then it will be incremented by 1, and a -1 byte appended.
+ */
+class SPDecimalBaseImpl extends SPDecimalImpl {
+
+  /**
+   * The terminating byte, indicating the type of this buffer. Only needed if the buffer
+   * is the same length as a long.
+   */
+  static final byte END_BYTE = -1;
+
+  /** The value of the data. */
+  final BigDecimal val;
+
+  /** The string representation of the data. */
+  final String lexical;
+
+  /**
+   * Creates an xsd:decimal out of a long.
+   * @param subtypeId The ID for either the full or abbreviated xsd:decimal.
+   * @param typeURI The full or abbreviated URI for xsd:decimal.
+   * @param l The long value to store.
+   */
+  SPDecimalBaseImpl(int subtypeId, URI typeURI, long l) {
+    super(subtypeId, typeURI);
+    lexical = Long.toString(l);
+    val = new BigDecimal(l);
+  }
+
+
+  /**
+   * Creates an xsd:decimal out of a BigDecimal.
+   * @param subtypeId The ID for either the full or abbreviated xsd:decimal.
+   * @param typeURI The full or abbreviated URI for xsd:decimal.
+   * @param bd The BigDecimal value to store.
+   */
+  SPDecimalBaseImpl(int subtypeId, URI typeURI, BigDecimal bd) {
+    super(subtypeId, typeURI);
+    lexical = bd.toPlainString();
+    val = bd;
+  }
+
+
+  /**
+   * Creates an xsd:decimal by decoding from a data buffer.
+   * @param subtypeId The ID for either the full or abbreviated xsd:decimal.
+   * @param typeURI The full or abbreviated URI for xsd:decimal.
+   * @param data The data containing the xsd:decimal value.
+   */
+  SPDecimalBaseImpl(int subtypeId, URI typeURI, ByteBuffer data) {
+    super(subtypeId, typeURI);
+    ByteBuffer number = data;
+    if (data.limit() == END_IDX + 1) {
+      assert data.get(END_IDX) == END_BYTE;
+      data.limit(END_IDX);
+      number = data.slice();
     }
+    lexical = CHARSET.decode(number).toString();
+    val = new BigDecimal(lexical);
   }
 
 
-  /* from SPObject interface. */
+  /**
+   * Creates an xsd:decimal by decoding from a string.
+   * @param subtypeId The ID for either the full or abbreviated xsd:decimal.
+   * @param typeURI The full or abbreviated URI for xsd:decimal.
+   * @param lexicalForm The string containing the xsd:decimal value.
+   */
+  SPDecimalBaseImpl(int subtypeId, URI typeURI, String lexicalForm) {
+    super(subtypeId, typeURI);
+    this.lexical = lexicalForm;
+    val = new BigDecimal(lexicalForm);
+  }
 
+
+  /** @see org.mulgara.store.stringpool.SPObject#getData() */
   public ByteBuffer getData() {
-    ByteBuffer data = ByteBuffer.allocate(Constants.SIZEOF_LONG);
+    ByteBuffer data = CHARSET.encode(lexical);
+    if (data.limit() == END_IDX) {
+      ByteBuffer newData = ByteBuffer.allocate(END_IDX + 1);
+      newData.put(data);
+      newData.put(END_IDX, END_BYTE);
+      data = newData;
+    }
+    return data;
+  }
+
+
+  /** @see org.mulgara.store.stringpool.SPObject#getSPComparator() */
+  public SPComparator getSPComparator() {
+    return SPDecimalBaseComparator.getInstance();
+  }
+
+
+  /** @see org.mulgara.store.stringpool.SPObject#getLexicalForm() */
+  public String getLexicalForm() {
+    return lexical;
+  }
+
+
+  /** @see org.mulgara.store.stringpool.AbstractSPTypedLiteral#compareTo(org.mulgara.store.stringpool.SPObject) */
+  public int compareTo(SPObject o) {
+    // Compare types.
+    int c = super.compareTo(o);
+    if (c != 0) return c;
+
+    // Compare the longs.
+    if (o instanceof SPDecimalExtImpl) {
+      long ol = ((SPDecimalExtImpl)o).l;
+      return val.compareTo(BigDecimal.valueOf(ol));
+    }
+    SPDecimalBaseImpl di = (SPDecimalBaseImpl)o;
+    return val.compareTo(di.val);
+  }
+
+
+  /** @see java.lang.Object#hashCode() */
+  public int hashCode() {
+    return lexical.hashCode();
+  }
+
+
+  /** @see java.lang.Object#equals(java.lang.Object) */
+  public boolean equals(Object obj) {
+    // Check for null.
+    if (obj == null) return false;
+
+    try {
+      SPDecimalBaseImpl di = (SPDecimalBaseImpl)obj;
+      return lexical.equals(di.lexical);
+    } catch (ClassCastException ex) {
+      // obj was not an SPDecimalImpl.
+      return false;
+    }
+  }
+
+  /** Compares the binary representations of two SPDecimalBaseImpl objects. */
+  public static class SPDecimalBaseComparator implements SPComparator {
+
+    /** The singleton instance of this class. */
+    private static final SPDecimalBaseComparator INSTANCE = new SPDecimalBaseComparator();
+
+    /**
+     * @return The singleton instance of this class.
+     */
+    public static SPDecimalBaseComparator getInstance() {
+      return INSTANCE;
+    }
+
+    /**
+     * @see org.mulgara.store.stringpool.SPComparator#comparePrefix(java.nio.ByteBuffer, java.nio.ByteBuffer, int)
+     * @return Always 0, since this cannot compare on prefixes alone.
+     */
+    public int comparePrefix(ByteBuffer d1, ByteBuffer d2, int d2Size) {
+      return 0;
+    }
+
+    /**
+     * @see org.mulgara.store.stringpool.SPComparator#compare(java.nio.ByteBuffer, java.nio.ByteBuffer)
+     * This comparator WILL compare between xsd:decimal and the extending types
+     */
+    public int compare(ByteBuffer d1, ByteBuffer d2) {
+      return decode(d1).compareTo(decode(d2));
+    }
+
+  }
+
+}
+
+
+/**
+ * This class represents extensions of xsd:decimal.
+ * The data format is as a long, followed by a byte marker set to 0. This is to
+ * distinguish the data format from xsd:decimal, which is stored as a string.
+ */
+class SPDecimalExtImpl extends SPDecimalImpl {
+
+  /** The terminating byte, to distinguish the data types from SPDecimalBaseImpl */
+  static final byte END_BYTE = 0;
+
+  /** The long value containing the number. */
+  final Long l;
+
+  /**
+   * Creates an xsd:decimal extension out of a long.
+   * @param subtypeId The ID for either the full or abbreviated URI.
+   * @param typeURI The full or abbreviated URI.
+   * @param l The long value to store.
+   */
+  SPDecimalExtImpl(int subtypeId, URI typeURI, long l) {
+    super(subtypeId, typeURI);
+    this.l = l;
+  }
+
+
+  /**
+   * Creates an xsd:decimal extension out of a buffer.
+   * @param subtypeId The ID for either the full or abbreviated URI.
+   * @param typeURI The full or abbreviated URI.
+   * @param data The buffer containing the data encoding the value.
+   */
+  SPDecimalExtImpl(int subtypeId, URI typeURI, ByteBuffer data) {
+    super(subtypeId, typeURI);
+    assert data.limit() == Constants.SIZEOF_LONG + 1;
+    int end = data.limit() - 1;
+    assert data.get(end) == END_BYTE;
+    l = data.getLong();
+  }
+
+
+  /**
+   * Creates an xsd:decimal extension out of a string.
+   * @param subtypeId The ID for either the full or abbreviated URI.
+   * @param typeURI The full or abbreviated URI.
+   * @param lexicalForm The string containing the value.
+   */
+  SPDecimalExtImpl(int subtypeId, URI typeURI, String lexicalForm) {
+    super(subtypeId, typeURI);
+    l = Long.valueOf(lexicalForm);
+  }
+
+
+  /** @see org.mulgara.store.stringpool.SPObject#getData() */
+  public ByteBuffer getData() {
+    ByteBuffer data = ByteBuffer.allocate(Constants.SIZEOF_LONG + 1);
     data.putLong(l);
+    data.put((byte)END_BYTE);
     data.flip();
     return data;
   }
 
 
+  /** @see org.mulgara.store.stringpool.SPObject#getSPComparator() */
   public SPComparator getSPComparator() {
-    return SPDecimalComparator.getInstance();
+    return SPDecimalExtComparator.getInstance();
   }
 
 
+  /** @see org.mulgara.store.stringpool.SPObject#getLexicalForm() */
   public String getLexicalForm() {
     return Long.toString(l);
   }
 
 
-  /* from Comparable interface. */
-
+  /** @see org.mulgara.store.stringpool.AbstractSPTypedLiteral#compareTo(org.mulgara.store.stringpool.SPObject) */
   public int compareTo(SPObject o) {
     // Compare types.
     int c = super.compareTo(o);
     if (c != 0) return c;
 
+    // The super will have returned a value already, but just in case we need to compare
+    // values between different types, we convert.
+    if (o instanceof SPDecimalBaseImpl) {
+      return -((SPDecimalBaseImpl)o).compareTo(this);
+    }
     // Compare the longs.
-    SPDecimalImpl di = (SPDecimalImpl)o;
+    SPDecimalExtImpl di = (SPDecimalExtImpl)o;
     return compare(l, di.l);
   }
 
 
-  /* from Object. */
-
+  /** @see java.lang.Object#hashCode() */
   public int hashCode() {
     return (int)(l * 7) | (int)(l >> 32);
   }
 
 
+  /** @see java.lang.Object#equals(java.lang.Object) */
   public boolean equals(Object obj) {
     // Check for null.
     if (obj == null) return false;
 
     try {
-      SPDecimalImpl di = (SPDecimalImpl)obj;
+      SPDecimalExtImpl di = (SPDecimalExtImpl)obj;
       return l == di.l;
     } catch (ClassCastException ex) {
-      // obj was not an SPDecimalImpl.
+      // obj was not an SPDecimalExtImpl.
       return false;
     }
   }
 
-  static int compare(long l1, long l2) {
+
+  /**
+   * Utility for comparing long values.
+   * @param l1 The first long.
+   * @param l2 The second long.
+   * @return +1 if l1 > l2, -1 if l1 < l2, and 0 if l1 == l2
+   */
+  public static int compare(long l1, long l2) {
     return l1 < l2 ? -1 : (l1 > l2 ? 1 : 0);
   }
 
 
-  /** Compares the binary representations of two SPDecimalImpl objects. */
-  public static class SPDecimalComparator implements SPComparator {
+  /** Compares the binary representations of two SPDecimalExtImpl objects. */
+  public static class SPDecimalExtComparator implements SPComparator {
 
-    private static final SPDecimalComparator INSTANCE = new SPDecimalComparator();
+    /** The singleton instance of this object. */
+    private static final SPDecimalExtComparator INSTANCE = new SPDecimalExtComparator();
 
-    public static SPDecimalComparator getInstance() {
+    /** @return The singleton instance of this object. */
+    public static SPDecimalExtComparator getInstance() {
       return INSTANCE;
     }
 
+    /**
+     * @see org.mulgara.store.stringpool.SPComparator#comparePrefix(java.nio.ByteBuffer, java.nio.ByteBuffer, int)
+     * @return Always 0, since all data is needed for comparing on this class.
+     */
     public int comparePrefix(ByteBuffer d1, ByteBuffer d2, int d2Size) {
       return 0;
     }
 
+    /**
+     * @see org.mulgara.store.stringpool.SPComparator#compare(java.nio.ByteBuffer, java.nio.ByteBuffer)
+     * This comparator WILL compare between xsd:decimal and the extending types
+     */
     public int compare(ByteBuffer d1, ByteBuffer d2) {
-      return SPDecimalImpl.compare(d1.getLong(), d2.getLong());
+      if (d1.get(END_IDX) == END_BYTE && d2.get(END_IDX) == END_BYTE) {
+        return SPDecimalExtImpl.compare(d1.getLong(), d2.getLong());
+      }
+      return SPDecimalExtImpl.compare(d1.getLong(), d2.getLong());
     }
 
   }
 
-}
+}
\ No newline at end of file

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalUnitTest.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalUnitTest.java	2008-08-25 11:18:25 UTC (rev 1176)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPDecimalUnitTest.java	2008-08-26 05:41:34 UTC (rev 1177)
@@ -26,6 +26,7 @@
 package org.mulgara.store.stringpool.xa;
 
 // Standard Java
+import java.math.BigDecimal;
 import java.nio.ByteBuffer;
 
 // JUnit
@@ -59,7 +60,7 @@
 
   private static final String INVALID_XSD_DECIMAL = "x";
   private static final String INVALID_XSD_DECIMAL2 = "0x";
-  private static final String INVALID_XSD_DECIMAL3 = "10.10";
+  private static final String INVALID_XSD_DECIMAL3 = "10.10.";
 
   /**
    * Constructs a new test with the given name.
@@ -80,6 +81,7 @@
     suite.addTest(new SPDecimalUnitTest("testValid"));
     suite.addTest(new SPDecimalUnitTest("testInvalid"));
     suite.addTest(new SPDecimalUnitTest("testCompare"));
+    suite.addTest(new SPDecimalUnitTest("testCompareFractions"));
 
     return suite;
   }
@@ -108,7 +110,7 @@
     validTest(VALID_XSD_DECIMAL5, factory);
     validTest(VALID_XSD_DECIMAL6, factory);
 
-    SPDecimalImpl dec = (SPDecimalImpl)factory.newSPTypedLiteral(XSD.DECIMAL_URI, VALID_XSD_DECIMAL1);
+    SPDecimalImpl dec = (SPDecimalImpl)factory.newSPTypedLiteral(XSD.INT_URI, VALID_XSD_DECIMAL1);
 
     // Retrieve the byte data of the decimal object
     ByteBuffer dtBytes = dec.getData();
@@ -119,17 +121,18 @@
     assertEquals(VALID_XSD_DECIMAL1, Long.toString(dLong));
 
     // Byte buffer to hold our decimal information
-    ByteBuffer buffer = ByteBuffer.wrap(new byte[Constants.SIZEOF_LONG]);
+    ByteBuffer buffer = ByteBuffer.wrap(new byte[Constants.SIZEOF_LONG + 1]);
 
     // If the previous step passed then we know the long value is what we want,
     // so store it in our buffer
     buffer.putLong(dLong);
+    buffer.put((byte)0);
 
     // Reset the buffer for reading
     buffer.flip();
 
     // Create a decimal object by byte buffer
-    dec = (SPDecimalImpl)factory.newSPTypedLiteral(0, buffer);
+    dec = (SPDecimalImpl)factory.newSPTypedLiteral(1, buffer);
 
     // Test that the lexical form of the decimal is correct
     assertEquals(VALID_XSD_DECIMAL1, dec.getLexicalForm());
@@ -139,22 +142,22 @@
     // Create a decimal object by lexical string
     SPDecimalImpl d = (SPDecimalImpl)factory.newSPTypedLiteral(XSD.DECIMAL_URI, number);
 
-    if (number.contains(".")) number = number.substring(0, number.indexOf('.'));
-    if (number.charAt(0) == '+') number = number.substring(1);
     // Test that the lexical form of the decimal is correct
     assertEquals(number, d.getLexicalForm());
 
     // Retrieve the byte data of the decimal object
     ByteBuffer dtBytes = d.getData();
 
-    // Create a decimal object from the decimal's long
-    SPDecimalImpl dDec;
-    dDec = new SPDecimalImpl(0, XSD.DECIMAL_URI, dtBytes.getLong());
+    // Create a decimal object from the decimal's data - may not be identical, but the data is equivalent
+    SPDecimalBaseImpl dDec = new SPDecimalBaseImpl(0, XSD.DECIMAL_URI, SPDecimalImpl.decode(dtBytes));
 
-    assertEquals(d, dDec);
+    BigDecimal bdNum;
+    if (d instanceof SPDecimalBaseImpl) bdNum = ((SPDecimalBaseImpl)d).val;
+    else bdNum = BigDecimal.valueOf(((SPDecimalExtImpl)d).l);
+    assertEquals(bdNum, dDec.val);
 
     dtBytes.rewind();
-    SPDecimalImpl rebuilt = new SPDecimalImpl(0, XSD.DECIMAL_URI, dtBytes);
+    SPDecimalImpl rebuilt = new SPDecimalBaseImpl(0, XSD.DECIMAL_URI, dtBytes);
     assertEquals(d, rebuilt);
   }
 
@@ -199,8 +202,47 @@
     assertTrue(t3.compareTo(t1) == 1);
     assertTrue(t3.compareTo(t2) == 1);
     assertTrue(t3.compareTo(t3) == 0);
+
+    t1 = (SPDecimalImpl) factory.newSPTypedLiteral(XSD.INTEGER_URI, "101");
+    t2 = (SPDecimalImpl) factory.newSPTypedLiteral(XSD.INTEGER_URI, "1001");
+    t3 = (SPDecimalImpl) factory.newSPTypedLiteral(XSD.INTEGER_URI, "1021");
+
+    assertTrue(t1.compareTo(t1) == 0);
+    assertTrue(t1.compareTo(t2) == -1);
+    assertTrue(t1.compareTo(t3) == -1);
+
+    assertTrue(t2.compareTo(t1) == 1);
+    assertTrue(t2.compareTo(t2) == 0);
+    assertTrue(t2.compareTo(t3) == -1);
+
+    assertTrue(t3.compareTo(t1) == 1);
+    assertTrue(t3.compareTo(t2) == 1);
+    assertTrue(t3.compareTo(t3) == 0);
   }
 
+  public void testCompareFractions() throws Exception {
+    // Create a new factory
+    SPDecimalFactory factory = new SPDecimalFactory();
+
+    SPDecimalImpl t1, t2, t3;
+
+    t1 = (SPDecimalImpl) factory.newSPTypedLiteral(XSD.DECIMAL_URI, "1");
+    t2 = (SPDecimalImpl) factory.newSPTypedLiteral(XSD.DECIMAL_URI, "1.5");
+    t3 = (SPDecimalImpl) factory.newSPTypedLiteral(XSD.DECIMAL_URI, "123456.7890");
+
+    assertTrue(t1.compareTo(t1) == 0);
+    assertTrue(t1.compareTo(t2) == -1);
+    assertTrue(t1.compareTo(t3) == -1);
+
+    assertTrue(t2.compareTo(t1) == 1);
+    assertTrue(t2.compareTo(t2) == 0);
+    assertTrue(t2.compareTo(t3) == -1);
+
+    assertTrue(t3.compareTo(t1) == 1);
+    assertTrue(t3.compareTo(t2) == 1);
+    assertTrue(t3.compareTo(t3) == 0);
+  }
+
   /**
    * Initialise members.
    *




More information about the Mulgara-svn mailing list