[Mulgara-svn] r1267 - in trunk: . lib src/jar/server-http src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa

pag at mulgara.org pag at mulgara.org
Tue Sep 23 04:36:55 UTC 2008


Author: pag
Date: 2008-09-22 21:36:54 -0700 (Mon, 22 Sep 2008)
New Revision: 1267

Added:
   trunk/lib/icu4j_3_4.jar
   trunk/lib/iri-0.5.jar
   trunk/lib/jena-2.5.6.jar
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/AbstractSPGDateTime.java
Removed:
   trunk/lib/icu4j.jar
   trunk/lib/jena-2.1.jar
Modified:
   trunk/.classpath
   trunk/build.properties
   trunk/build.xml
   trunk/common.xml
   trunk/src/jar/server-http/build.xml
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayImpl.java
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayUnitTest.java
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayImpl.java
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayUnitTest.java
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthImpl.java
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthUnitTest.java
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearImpl.java
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthImpl.java
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthUnitTest.java
   trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearUnitTest.java
Log:
Updated the Jena libs (this will let us avoid Jena soon, and just keep ARP). Also found and fixed a series of bugs in the Gdate data types, where the lexical form could change depending on the entered timezone, and the timezone of the running system.

Modified: trunk/.classpath
===================================================================
--- trunk/.classpath	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/.classpath	2008-09-23 04:36:54 UTC (rev 1267)
@@ -91,7 +91,8 @@
 	<classpathentry kind="lib" path="lib/jasper-runtime-4.2.29.jar"/>
 	<classpathentry kind="lib" path="lib/javacc.jar"/>
 	<classpathentry kind="lib" path="lib/jboss-j2ee.jar"/>
-	<classpathentry kind="lib" path="lib/jena-2.1.jar"/>
+	<classpathentry kind="lib" path="lib/jena-2.5.6.jar"/>
+	<classpathentry kind="lib" path="lib/iri-0.5.jar"/>
 	<classpathentry kind="lib" path="lib/jetty-6.1.11.jar"/>
 	<classpathentry kind="lib" path="lib/jetty-util-6.1.11.jar"/>
 	<classpathentry kind="lib" path="lib/jid3-0.34.jar"/>

Modified: trunk/build.properties
===================================================================
--- trunk/build.properties	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/build.properties	2008-09-23 04:36:54 UTC (rev 1267)
@@ -106,14 +106,15 @@
 d2r.jar                  =d2rmap-V02.jar
 emory-util.jar           =emory-util-2.1-remote.jar
 httpclient.jar           =${commons-httpclient.jar}
-icu4j.jar                =icu4j.jar
+icu4j.jar                =icu4j_3_4.jar
 jargs.jar                =jargs-0.2.jar
 jasper.compiler.jar      =jasper-compiler-4.2.29.jar
 jasper.runtime.jar       =jasper-runtime-4.2.29.jar
 jaxrpc.jar               =jaxrpc-1.4.jar
 jakarta-oro.jar          =jakarta-oro-2.0.5.jar
 jca.jar                  =connector-1_5.jar
-jena.jar                 =jena-2.1.jar
+jena.jar                 =jena-2.5.6.jar
+iri.jar                  =iri-0.5.jar
 jetty.jar                =jetty-6.1.11.jar
 jetty.plus.jar           =jetty-util-6.1.11.jar
 jid3.jar                 =jid3-0.34.jar

Modified: trunk/build.xml
===================================================================
--- trunk/build.xml	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/build.xml	2008-09-23 04:36:54 UTC (rev 1267)
@@ -512,6 +512,7 @@
       <zipfileset src="${lib.dir}/${jaxrpc.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jca.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jena.jar}" excludes="META-INF/**"/>
+      <zipfileset src="${lib.dir}/${iri.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jetty.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jetty.plus.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jid3.jar}" excludes="META-INF/**"/>
@@ -1391,7 +1392,7 @@
       <fileset dir="${src.dir}/war/mulgara"
           includes="WEB-INF/**" excludes="WEB-INF/web.xml"/>
 
-      <lib dir="${lib.dir}" includes="log4j-core-*.jar, icu4j.jar, jena-*.jar, antlr*.jar,
+        <lib dir="${lib.dir}" includes="log4j-core-*.jar, icu4j.jar, jena-*.jar, ${iri.jar}, antlr*.jar,
         lucene*.jar, apache-soap-*.jar, ${joda-time.jar}, ${commons-logging.jar}, ${sesame-model.jar}"/>
       <lib dir="${bin.dir}" includes="${query.jar},
         ${driver.jar}, ${querylang.jar}, ${rules.jar}, ${rmi.jar},
@@ -1647,6 +1648,7 @@
       <zipfileset src="${lib.dir}/${jaxrpc.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jca.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jena.jar}" excludes="META-INF/**"/>
+      <zipfileset src="${lib.dir}/${iri.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jetty.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jetty.plus.jar}" excludes="META-INF/**"/>
       <zipfileset src="${lib.dir}/${jid3.jar}" excludes="META-INF/**"/>

Modified: trunk/common.xml
===================================================================
--- trunk/common.xml	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/common.xml	2008-09-23 04:36:54 UTC (rev 1267)
@@ -140,7 +140,7 @@
 
     <fileset dir="${lib.dir}"
              includes="log4j-*.jar, xmlParserAPIs.jar, xercesImpl.jar,
-                       jena-*.jar, jxunit*.jar, castor*.jar,
+                       ${jena.jar}, ${iri.jar}, ${icu4j.jar}, jxunit*.jar, castor*.jar,
                        mail-*.jar, activation-*.jar, apache-soap-*.jar,
                        axis-*.jar, saaj-*.jar, emory-*.jar, trove-*.jar,
                        jargs-*.jar, jetty-*.jar, jta-spec*.jar,

Deleted: trunk/lib/icu4j.jar
===================================================================
(Binary files differ)

Added: trunk/lib/icu4j_3_4.jar
===================================================================
(Binary files differ)


Property changes on: trunk/lib/icu4j_3_4.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/lib/iri-0.5.jar
===================================================================
(Binary files differ)


Property changes on: trunk/lib/iri-0.5.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Deleted: trunk/lib/jena-2.1.jar
===================================================================
(Binary files differ)

Added: trunk/lib/jena-2.5.6.jar
===================================================================
(Binary files differ)


Property changes on: trunk/lib/jena-2.5.6.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/src/jar/server-http/build.xml
===================================================================
--- trunk/src/jar/server-http/build.xml	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/src/jar/server-http/build.xml	2008-09-23 04:36:54 UTC (rev 1267)
@@ -149,7 +149,7 @@
     <manifest file="${obj.dir}/META-INF/MANIFEST_Mulgara_HTTP_BOOTSTRAP.MF">
 
       <attribute name="Main-Class" value="org.mulgara.util.Bootstrap"/>
-      <attribute name="Embedded-Jar" value="lib/${driver.jar}, lib/${query.jar},lib/${querylang.jar}, lib/${rules.jar}, lib/${server.jar}, lib/${util.jar}, lib/${config.jar}, lib/activation-1.0.2.jar, lib/icu4j.jar, lib/jena-2.1.jar,lib/antlr.jar, lib/${commons-logging.jar}, lib/log4j-1.2.15.jar, lib/mail-1.3.jar, lib/${jetty.jar},lib/${jetty.plus.jar}, lib/${jasper.runtime.jar}, lib/${servlet.jar}, lib/jargs-0.2.jar,lib/${castor-xml.jar}, lib/${castor-xml-schema.jar}, lib/xercesImpl.jar, lib/xmlParserAPIs.jar, lib/${jrdf.jar},lib/jakarta-oro-2.0.5.jar, lib/${emory-util.jar}, lib/${sesame-model.jar}"/>
+      <attribute name="Embedded-Jar" value="lib/${driver.jar}, lib/${query.jar},lib/${querylang.jar}, lib/${rules.jar}, lib/${server.jar}, lib/${util.jar}, lib/${config.jar}, lib/activation-1.0.2.jar, lib/icu4j.jar, lib/${jena.jar}, lib/${iri.jar}, lib/antlr.jar, lib/${commons-logging.jar}, lib/log4j-1.2.15.jar, lib/mail-1.3.jar, lib/${jetty.jar},lib/${jetty.plus.jar}, lib/${jasper.runtime.jar}, lib/${servlet.jar}, lib/jargs-0.2.jar,lib/${castor-xml.jar}, lib/${castor-xml-schema.jar}, lib/xercesImpl.jar, lib/xmlParserAPIs.jar, lib/${jrdf.jar},lib/jakarta-oro-2.0.5.jar, lib/${emory-util.jar}, lib/${sesame-model.jar}"/>
       <attribute name="Embedded-Main-Class" value="org.mulgara.server.EmbeddedMulgaraHttpServer"/>
     </manifest>
 
@@ -171,7 +171,7 @@
                   includes="log4j-mulgara.xml, webdefault.xml, mulgara-rmi.policy,
                     mulgara.policy"/>
       <zipfileset dir="${lib.dir}" prefix="lib"
-        includes="log4j*.jar, icu4j.jar, jena-*.jar, antlr*.jar, ${commons-logging.jar},
+        includes="log4j*.jar, icu4j.jar, ${jena.jar}, ${iri.jar}, antlr*.jar, ${commons-logging.jar},
           activation*.jar, jargs*.jar,
           ${jetty.jar}, ${jetty.plus.jar}, ${servlet.jar}, ${jasper.runtime.jar},
           xerces*.jar, mail-*.jar, castor*.jar, trove-*.jar, ${jrdf.jar}, ${emory-util.jar}, ${sesame-model.jar}"/>

Added: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/AbstractSPGDateTime.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/AbstractSPGDateTime.java	                        (rev 0)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/AbstractSPGDateTime.java	2008-09-23 04:36:54 UTC (rev 1267)
@@ -0,0 +1,373 @@
+/*
+ * The contents of this file are subject to the Open Software License
+ * Version 3.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.opensource.org/licenses/osl-3.0.txt
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ */
+
+package org.mulgara.store.stringpool.xa;
+
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+import org.apache.log4j.Logger;
+import org.mulgara.store.stringpool.*;
+import org.mulgara.util.Constants;
+import org.mulgara.util.Timezone;
+
+/**
+ * Holds constants used by the SPG dateTime types.
+ *
+ * @created Sep 19, 2008
+ * @author Paul Gearon
+ * @copyright &copy; 2008 <a href="http://www.topazproject.org/">The Topaz Project</a>
+ * @licence <a href="{@docRoot}/../../LICENCE.txt">Open Software License v3.0</a>
+ */
+public abstract class AbstractSPGDateTime extends AbstractSPTypedLiteral {
+
+  private final static Logger logger = Logger.getLogger(AbstractSPGDateTime.class);
+
+  /** The arbitrary default year to use for a type that has no year. */
+  public static int D_YEAR = 2000;
+
+  /** The arbitrary default month to use for a type that has no month. */
+  public static int D_MONTH = 0;
+
+  /** The arbitrary default day to use for a type that has no day. */
+  public static int D_DAY = 1;
+
+  /** The arbitrary default hour to use for a types with no hour. */
+  public static int D_HOUR_OF_DAY = 0;
+
+  /** The arbitrary default minute to use for a type that has no minutes. */
+  public static int D_MINUTE = 0;
+
+  /** The arbitrary default seconds to use for a type that has no seconds. */
+  public static int D_SECOND = 0;
+
+  /** The arbitrary default milliseconds to use for a type that has no milliseconds. */
+  public static int D_MILLISECOND = 0;
+
+  /** Bit 0 indicates a timezone. */
+  static final byte NO_TZ_BIT = 1;
+
+  /** The date representation for the data. */
+  protected Calendar gDate;
+
+  /** The timezone info. */
+  protected Timezone tz = null;
+
+
+  /**
+   * Constructs a new GDay representation using a calendar object representation.
+   *
+   * @param dayDate The gDay object represented as a date
+   */
+  AbstractSPGDateTime(int typeID, URI typeURI, Date dayDate) {
+    super(typeID, typeURI);
+
+    // Initialise the calendar object
+    gDate = Calendar.getInstance();
+    gDate.setTime(dayDate);
+  }
+
+
+  /**
+   * Constructs a new GDay representation using a calendar object representation.
+   *
+   * @param dayCalendar The gDay object represented as a calendar
+   */
+  AbstractSPGDateTime(int typeID, URI typeURI, Calendar dayCalendar, Timezone tz) {
+    super(typeID, typeURI);
+
+    // Store the day date as a calendar
+    gDate = dayCalendar;
+    this.tz = tz;
+  }
+
+
+  /**
+   * Creates a new gDay representation using a long value of the day
+   * and creating a Date object from it.
+   *
+   * @param dayLong The day as a long
+   */
+  AbstractSPGDateTime(int typeID, URI typeURI, long dayLong) {
+    // Use the date constructor to create a new instance
+    this(typeID, typeURI, new Date(dayLong));
+  }
+
+
+  /**
+   *
+   * Constructs a gDay object which reads the day value from a byte buffer as
+   * an integer.
+   *
+   * @param data The byte buffer storing the day as an integer
+   */
+  AbstractSPGDateTime(int typeID, URI typeURI, ByteBuffer data) {
+    // Call the constructor using a long for the date
+    this(typeID, typeURI, data.getLong());
+    // update the timezone
+    setTzByte(data.get());
+  }
+
+
+  /**
+   * Retrieve the size of the buffer needed for this object. This is the size of the buffer
+   * returned by {@link #getData()} or used by {@link #AbstractSPGDateTime(int, URI, ByteBuffer)}.
+   * @return A buffer size in bytes.
+   */
+  public static int getBufferSize() {
+    return Constants.SIZEOF_LONG + 1;
+  }
+
+
+  /**
+   * Converts this gDate/Time object to a buffer of byte data.
+   * @return The byte representation of this gDate/Time object
+   */
+  public ByteBuffer getData() {
+
+    // Create a new byte buffer that can hold a long object
+    ByteBuffer data = ByteBuffer.allocate(getBufferSize());
+
+    // Store the date as a long value
+    data.putLong(gDate.getTimeInMillis());
+    data.put(getTzByte());
+
+    // Prepare the buffer for reading
+    data.flip();
+
+    return data;
+  }
+
+
+  /**
+   * Compares this gDay representation to another object to see if they are
+   * the same values.  First the typing is checked and then the value.
+   * @param object The object we are comparing against
+   * @return Whether the gDay value is greater than (> 0), less than (< 0), or equal to (0) this value
+   */
+  public int compareTo(SPObject object) {
+    // Compare types.
+    int comparison = super.compareTo(object);
+    if (comparison != 0) return comparison;
+    // Compare the dates lexically
+    return getLexicalForm().compareTo(((AbstractSPGDateTime)object).getLexicalForm());
+  }
+
+
+  /** @see java.lang.Object#hashCode() */
+  public int hashCode() {
+    return gDate.hashCode();
+  }
+
+
+  /**
+   * Determines whether the object is equal to the one passed in, in both type
+   * and value.  This is different to the compareTo(Object) method in the
+   * respect that it does a direct comparison, not a ranking comparison.
+   * @param object The object to compare this one to
+   * @return Whether the object is the same as this one
+   */
+  public boolean equals(Object object) {
+    if (object == null) return false;
+    return object.getClass().isInstance(this) && ((AbstractSPGDateTime)object).getLexicalForm().equals(getLexicalForm());
+  }
+
+
+  /**
+   * Create a new comparator for comparison operations.
+   * @return The comparator to be used for comparisons
+   */
+  public SPComparator getSPComparator() {
+    return SPGDateTimeComparator.getInstance();
+  }
+
+
+  /**
+   * Convert the gDay representation to a lexical string as defined by XSD datatypes.
+   * @return The lexical form of the gDay object
+   */
+  public String getLexicalForm() {
+    // Create a formatter to output the date
+    SimpleDateFormat formatter = new SimpleDateFormat(getFormatString());
+    if (tz != null) formatter.setTimeZone(tz.asJavaTimeZone());
+
+    // Apply the formatting
+    String lexical = formatter.format(gDate.getTime());
+
+    // append the timezone if needed
+    if (tz != null) lexical += tz.toString();
+    return lexical;
+  }
+
+
+  /**
+   * Get the format string used for lexical form.
+   * @return A format string used by {@linkplain java.text.SimpleDateFormat}.
+   */
+  abstract protected String getFormatString();
+
+
+  /**
+   * Set up a calendar object for the "arbitrary" year/month/time used by this type.
+   * @param cal The calendar to configure
+   */
+  protected static void configureCalendar(Calendar cal) {
+    cal.set(Calendar.YEAR, D_YEAR);
+    cal.set(Calendar.MONTH, D_MONTH);
+    cal.set(Calendar.DAY_OF_MONTH, D_DAY);
+    cal.set(Calendar.HOUR_OF_DAY, D_HOUR_OF_DAY);
+    cal.set(Calendar.MINUTE, D_MINUTE);
+    cal.set(Calendar.SECOND, D_SECOND);
+    cal.set(Calendar.MILLISECOND, D_MILLISECOND);
+  }
+
+
+  /**
+   * Scan a lexical form for a timezone, and return an appropriate timezone.
+   * @param str The lexical form of the day value.
+   * @param maxDashes The number of dashes used when no timezone is present.
+   * @return a new Timezone built from the string, or null if none found.
+   */
+  protected static Timezone scanForTimezone(String str, int maxDashes) {
+    if (str.indexOf('Z') > 1) return Timezone.newZuluTimezone();
+
+    // look for indicators of a negative or a positive timezone,
+    // and set the start of the timezone string
+    int startPos = str.indexOf('+') + 1;
+
+    if (startPos == 0) {
+      int splitLen = str.split("-").length;
+      // Add a dash to check for negative timezones, and one more for the number of fields.
+      if (splitLen > maxDashes + 2) throw new IllegalArgumentException("Bad timezone. Too many dashes in: " + str);
+      if (splitLen == maxDashes + 2) startPos = str.lastIndexOf("-");
+    } else {
+      // positive offset, so there should be no dashes after this point
+      if (str.lastIndexOf('-') >= startPos) throw new IllegalArgumentException("Bad timezone characters in: " + str);
+    }
+
+    Timezone result = null;
+    // If the timezone string is there, then pull it out and set the object
+    if (startPos > 1) {
+      String[] zone = str.substring(startPos).split(":");
+      if (zone.length < 2) throw new IllegalArgumentException("Bad timezone characters in: " + str.substring(startPos));
+      result = buildTimezone(zone[0], zone[1]);
+    }
+    return result;
+  }
+
+
+  /**
+   * Creates a "Standard" calendar object, with a default date and time, in the given timezone.
+   * @param tz The timezone for the calendar.
+   * @return A new default calendar in the given timezone.
+   */
+  protected static Calendar createCalendar(Timezone tz) {
+    // Get the date/time object as a calendar
+    Calendar calendar = tz == null ? new GregorianCalendar() : new GregorianCalendar(tz.asJavaTimeZone());
+    configureCalendar(calendar);
+    if (logger.isDebugEnabled()) {
+      logger.debug("Calendar lexical string is: " +
+                   calendar.get(Calendar.YEAR) + "-" +
+                   calendar.get(Calendar.MONTH) + "-" +
+                   calendar.get(Calendar.DAY_OF_MONTH));
+      logger.debug("TimeZone of calendar is: " + calendar.getTimeZone());
+      logger.debug("Calendar as date: " + calendar.getTime());
+    }
+    return calendar;
+  }
+
+  /**
+   * Creates a Timezone for an object
+   * @param hr The hour offset of the timezone as a string. May be negative.
+   * @param min The minute offset of the timezone as a string.
+   */
+  private static Timezone buildTimezone(String hr, String min) {
+    return new Timezone(Integer.parseInt(hr), Integer.parseInt(min));
+  }
+
+
+  /**
+   * Calculate an encoding byte for the timezone.
+   * @return A code for the presence of a timezone.
+   */
+  private byte getTzByte() {
+    return (tz == null) ? NO_TZ_BIT : tz.getCode();
+  }
+
+
+  /**
+   * Calculate an encoding byte for the timezone.
+   * @return A code for the presence of a timezone.
+   */
+  private void setTzByte(byte tzData) {
+    tz = null;
+    if ((tzData & NO_TZ_BIT) == 0) tz = new Timezone(tzData);
+  }
+
+
+  /**
+   * Implementation of an SPComparator which compares the binary representations of GDateTime objects.
+   */
+  public static class SPGDateTimeComparator implements SPComparator {
+
+    /** Singleton instance of the comparator */
+    private static final SPGDateTimeComparator INSTANCE = new SPGDateTimeComparator();
+
+    /**
+     * Retrieves the singleton instance of this comparator.
+     *
+     * @return The comparator singleton instance
+     */
+    public static SPGDateTimeComparator getInstance() {
+      return INSTANCE;
+    }
+
+    /**
+     * Gives the comparator an opportunity to return an ordering where only the
+     * prefix of the binary representation of one or both SPObjects is available.
+     * If the comparator does not support this method or if an ordering can not
+     * be determined from the available data then zero (0) should be returned.
+     *
+     * @param d1 The first gDay's byte buffer
+     * @param d2 The second gDay's byte buffer
+     * @param d2Size The number of bytes to compare
+     *
+     * @return Whether the first prefix is greater than (> 0), less than (< 0),
+     *         or equal to (0) the other
+     */
+    public int comparePrefix(ByteBuffer d1, ByteBuffer d2, int d2Size) {
+      return 0;
+    }
+
+    /**
+     * Compares the content of a byte buffer to the other and determines whether
+     * they are equal or not.
+     *
+     * @param d1 The first byte buffer
+     * @param d2 The second byte buffer
+     * @return Whether the first buffer's content is greater than (> 0), less
+     *         than (< 0), or equal to (0) the other
+     */
+    public int compare(ByteBuffer d1, int st1, ByteBuffer d2, int st2) {
+      int c = AbstractSPObject.compare(d1.getLong(), d2.getLong());
+      if (c != 0) return c;
+      // if equal then compare the timezone bytes
+      return AbstractSPObject.compare(d1.get(), d2.get());
+    }
+
+  }
+
+}

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayImpl.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayImpl.java	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayImpl.java	2008-09-23 04:36:54 UTC (rev 1267)
@@ -29,111 +29,73 @@
 // Java 2 standard packages
 import java.net.URI;
 import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Calendar;
 
 // Third party packages
 import org.apache.log4j.Logger;
-import com.hp.hpl.jena.datatypes.xsd.impl.XSDDayType;
-import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
 
 // Locally written packages
 import org.mulgara.query.rdf.XSD;
-import org.mulgara.store.stringpool.*;
-import org.mulgara.util.Constants;
+import org.mulgara.util.Timezone;
 
 /**
  * An SPObject that represents monthly Gregorian calendar days.
+ * Format: ---DD
  *
  * @created 2004-10-06
- *
  * @author Mark Ludlow
- *
- * @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>
- *
+ * @author Paul Gearon
+ * @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 SPGDayImpl extends AbstractSPTypedLiteral {
+public final class SPGDayImpl extends AbstractSPGDateTime {
 
   private final static Logger logger = Logger.getLogger(SPGDayImpl.class);
 
-  /** The date representation for the day */
-  private Calendar day;
-
   static final int TYPE_ID = 10; // Unique ID
 
   /** URI for our gday representation */
   static final URI TYPE_URI = XSD.GDAY_URI;
 
-  /** Indicator as to whether we have a time zone or not */
-  private boolean hasTimeZone;
+  /** The number of dashes that appear without a timezone */
+  static private final int STD_DASHES = 3;
 
   /**
    * Constructs a new GDay representation using a calendar object representation.
-   *
    * @param dayDate The gDay object represented as a date
    */
   SPGDayImpl(Date dayDate) {
-
-    // Call the super constructor
-    super(TYPE_ID, TYPE_URI);
-
-    // Initialise the calendar object
-    day = Calendar.getInstance();
-
-    // Store the day date as a calendar
-    day.setTime(dayDate);
+    super(TYPE_ID, TYPE_URI, dayDate);
   }
 
   /**
    * Constructs a new GDay representation using a calendar object representation.
-   *
    * @param dayCalendar The gDay object represented as a calendar
    */
-  SPGDayImpl(Calendar dayCalendar) {
-
-    // Call the super constructor
-    super(TYPE_ID, TYPE_URI);
-
-    // Store the day date as a calendar
-    day = dayCalendar;
+  SPGDayImpl(Calendar dayCalendar, Timezone tz) {
+    super(TYPE_ID, TYPE_URI, dayCalendar, tz);
   }
 
   /**
    *
-   * Constructs a gDay object which reads the day value from a byte buffer as
-   * an integer.
-   *
+   * Constructs a gDay object which reads the day value from a byte buffer as an integer.
    * @param data The byte buffer storing the day as an integer
    */
   SPGDayImpl(ByteBuffer data) {
-
-    // Call the constructor using a long for the date
-    this(data.getLong());
+    super(TYPE_ID, TYPE_URI, data);
   }
 
   /**
    * Creates a new gDay representation using a long value of the day
    * and creating a Date object from it.
-   *
    * @param dayLong The day as a long
    */
   SPGDayImpl(long dayLong) {
-
-    // Use the date constructor to create a new instance
-    this(new Date(dayLong));
+    super(TYPE_ID, TYPE_URI, dayLong);
   }
 
+
   /**
    * Constructs a new GDay object given the lexical form of a date.
    *
@@ -142,248 +104,44 @@
    */
   static SPGDayImpl newInstance(String lexicalForm) {
 
-    // The XSD day type object we are creating
-    SPGDayImpl dayImpl = null;
+    if (lexicalForm.length() < 5 || !lexicalForm.startsWith("---")) {
+      throw new IllegalArgumentException("Invalid gDay lexical format: " + lexicalForm);
+    }
 
-    // Container for our date time object
-    XSDDateTime dateTime = null;
+    String dateValue = lexicalForm.substring(3, 5);
 
-    // Create a data type to represent a gDay
-    XSDDayType dataType = new XSDDayType("gDay");
-
+    // Parse the value to an integer
+    int dateInt;
     try {
-
-      // Create a date time object to parse out our date
-      dateTime = (XSDDateTime) dataType.parseValidated(lexicalForm);
-    } catch (RuntimeException ex) {
-
-      // Since the highest level exception that can occur during parsing is the
-      // runtime exception, we should capture them and report a bad lexical
-      // formation
-      throw new IllegalArgumentException("Invalid gDay lexical format: " +
-                                         lexicalForm);
+      dateInt = Integer.parseInt(dateValue);
+    } catch (NumberFormatException e) {
+      throw new IllegalArgumentException("Invalid gDay lexical format: " + lexicalForm);
     }
 
-    // Jena uses the day value as day of year, except we want day of month so we
-    // need to perform a check that the day is within valid bounds
-    String dateValue = lexicalForm.substring(3, 5);
-
-    // Parse the value to an integer (We know it is a valid number)
-    int dateInt = Integer.parseInt(dateValue);
-
     // Check that the value is valid
     if (dateInt <= 0 || dateInt >= 32) {
-
-      throw new IllegalArgumentException("gDay value [" + lexicalForm +
-                                         "] is not a valid day number.");
+      throw new IllegalArgumentException("gDay value [" + lexicalForm + "] is not a valid day number.");
     }
 
-    // Get the date/time object as a calendar
-    Calendar calendar = dateTime.asCalendar();
+    // Create a timezone for this object
+    Timezone tz = scanForTimezone(lexicalForm, STD_DASHES);
 
-    calendar.set(Calendar.MONTH, 2);
+    Calendar calendar = createCalendar(tz);
 
-    if (dateInt > 29) {
+    calendar.set(Calendar.DAY_OF_MONTH, dateInt);
 
-      // Jena wraps days after 29 so we need to fix any wrapped dates
-      calendar.set(Calendar.DAY_OF_MONTH, dateInt);
-    }
+    if (logger.isDebugEnabled()) logger.debug("Day value before calendar is: " + dateInt);
 
-    if (logger.isDebugEnabled()) {
-
-      logger.debug("Day value before calendar is: " + dateTime.getDays());
-      logger.debug("Calendar lexical string is: " +
-                   calendar.get(Calendar.YEAR) + "-" +
-                   calendar.get(Calendar.MONTH) + "-" +
-                   calendar.get(Calendar.DAY_OF_MONTH));
-      logger.debug("TimeZone of calendar is: " +
-                   calendar.getTimeZone().toString());
-      logger.debug("Calendar as date: " + calendar.getTime().toString());
-    }
-
     // Create our object
-    dayImpl = new SPGDayImpl(calendar);
-
-    if (lexicalForm.indexOf("Z") > 1 || lexicalForm.split("-").length == 5 ||
-        lexicalForm.indexOf("+") > 1) {
-
-      // If we have a timezone then set the flag to be true
-      dayImpl.setHasTimeZone(true);
-    }
-
-    return dayImpl;
+    return new SPGDayImpl(calendar, tz);
   }
 
-  /**
-   * A local method to set whether we have a timezone or not.
-   *
-   * @param value Whether we have a time zone or not
-   */
-  public void setHasTimeZone(boolean value) {
 
-    // Store whether we have a timezone or not
-    hasTimeZone = value;
-  }
-
   /**
-   * Converts this gDay object to a buffer of byte data.
-   *
-   * @return The byte representation of this gDay object
+   * @see org.mulgara.store.stringpool.xa.AbstractSPGDateTime#getFormatString()
    */
-  public ByteBuffer getData() {
-
-    // Create a new byte buffer that can hold a long object
-    ByteBuffer data = ByteBuffer.allocate(Constants.SIZEOF_LONG);
-
-    // Store the date as a long value
-    data.putLong(day.getTimeInMillis());
-
-    // Prepare the buffer for reading
-    data.flip();
-
-    return data;
+  protected String getFormatString() {
+    return "'---'dd";
   }
 
-  /**
-   * Create a new comparator for comparison operations.
-   *
-   * @return The comparator to be used for comparisons
-   */
-  public SPComparator getSPComparator() {
-
-    return SPGDayComparator.getInstance();
-  }
-
-  /**
-   * Convert the gDay representation to a lexical string as defined by XSD
-   * datatypes.
-   *
-   * @return The lexical form of the gDay object
-   */
-  public String getLexicalForm() {
-
-    // Create the default format string
-    String formatString = "'---'dd";
-
-    if (hasTimeZone) {
-
-      formatString += "'Z'";
-    }
-
-    // Create a formatter to parse the date
-    SimpleDateFormat formatter = new SimpleDateFormat(formatString);
-
-    // Apply the formatting
-    return formatter.format(day.getTime());
-  }
-
-  /**
-   * Compares this gDay representation to another object to see if they are
-   * the same values.  First the typing is checked and then the value.
-   *
-   * @param object The object we are comparing against
-   *
-   * @return Whether the gDay value is greater than (> 0), less than (< 0), or
-   *         equal to (0) this value
-   */
-  public int compareTo(SPObject object) {
-
-    // Compare types.
-    int comparison = super.compareTo(object);
-
-    // If we have not got matching types return the value
-    if (comparison != 0) return comparison;
-
-    // Compare the dates lexiocally
-    return getLexicalForm().compareTo(((SPGDayImpl) object).getLexicalForm());
-  }
-
-  /**
-   * Calculate the hash code for the gDay object
-   *
-   * @return The hash code for the object
-   */
-  public int hashCode() {
-
-    return day.hashCode();
-  }
-
-  /**
-   * Determines whether the object is equal to the one passed in, in both type
-   * and value.  This is different to the compareTo(Object) method in the
-   * respect that it does a direct comparison, not a ranking comparison.
-   *
-   * @param object The object to compare this one to
-   *
-   * @return Whether the object is the same as this one
-   */
-  public boolean equals(Object object) {
-
-    // Check for null.
-    if (object == null) {
-
-      return false;
-    }
-
-    if (object.getClass().isInstance(this)) {
-
-      // If the object is also a gDay object then compare the date
-      return ((SPGDayImpl) object).getLexicalForm().equals(getLexicalForm());
-    } else {
-
-      // The object is of a different type and not equal
-      return false;
-    }
-  }
-
-  /**
-   * Implementation of an SPComparator which compares the binary representations
-   * of a GDay object.
-   */
-  public static class SPGDayComparator implements SPComparator {
-
-    /** Singleton instance of the comparator */
-    private static final SPGDayComparator INSTANCE = new SPGDayComparator();
-
-    /**
-     * Retrieves the singleton instance of this comparator.
-     *
-     * @return The comparator singleton instance
-     */
-    public static SPGDayComparator getInstance() {
-
-      return INSTANCE;
-    }
-
-    /**
-     * Gives the comparator an opportunity to return an ordering where only the
-     * prefix of the binary representation of one or both SPObjects is available.
-     * If the comparator does not support this method or if an ordering can not
-     * be determined from the available data then zero (0) should be returned.
-     *
-     * @param d1 The first gDay's byte buffer
-     * @param d2 The second gDay's byte buffer
-     * @param d2Size The number of bytes to compare
-     *
-     * @return Whether the first prefix is greater than (> 0), less than (< 0),
-     *         or equal to (0) the other
-     */
-    public int comparePrefix(ByteBuffer d1, ByteBuffer d2, int d2Size) {
-      return 0;
-    }
-
-    /**
-     * Compares the content of a byte buffer to the other and determines whether
-     * they are equal or not.
-     *
-     * @param d1 The first byte buffer
-     * @param d2 The second byte buffer
-     * @return Whether the first buffer's content is greater than (> 0), less
-     *         than (< 0), or equal to (0) the other
-     */
-    public int compare(ByteBuffer d1, int st1, ByteBuffer d2, int st2) {
-      return AbstractSPObject.compare(d1.getLong(), d2.getLong());
-    }
-
-  }
 }

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayUnitTest.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayUnitTest.java	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGDayUnitTest.java	2008-09-23 04:36:54 UTC (rev 1267)
@@ -85,15 +85,24 @@
   /** Constant valid test date (date with UTC timezone) */
   private static final String VALID_DATE3 = "---04Z";
 
-  /** A valid value for the VALID_DATE3 in TimeZones west of GMT **/ 
-  private static final String VALID_DATE3_WEST = "---03Z";
+  /** Constant valid test date (Upper/Lower bounds test) */
+  private static final String VALID_DATE4 = "---31Z";
 
-  /** Constant valid test date (Upper bounds test) */
-  private static final String VALID_DATE4 = "---31";
-  
   /** A valid value for the VALID_DATE4 in TimeZones west of GMT **/ 
   private static final String VALID_DATE4_WEST = "---30";
 
+  /** A valid value for the VALID_DATE4 in TimeZones west of GMT **/ 
+  private static final String VALID_DATE4_EAST = "---31";
+
+  /** Constant valid test date (Upper/Lower bounds test) */
+  private static final String VALID_DATE5 = "---01Z";
+
+  /** A valid value for the VALID_DATE5 in TimeZones west of GMT **/ 
+  private static final String VALID_DATE5_WEST = "---31";
+
+  /** A valid value for the VALID_DATE5 in TimeZones west of GMT **/ 
+  private static final String VALID_DATE5_EAST = "---01";
+
   /** Invalid date 1 (non-numeric characters) */
   private static final String INVALID_DATE_1 = "---2g";
 
@@ -166,11 +175,10 @@
    */
   public void testValid() {
 
-	// Get a TimeZone instance which will help us interpret the results.
-	TimeZone tz = TimeZone.getDefault();
+  	// Get a TimeZone instance which will help us interpret the results.
+  	TimeZone tz = TimeZone.getDefault();
+  	boolean westOfGMT = tz.getRawOffset() < 0;
 	
-	boolean westOfGMT = tz.getRawOffset() < 0;
-	
     // Create a new factory
     SPGDayFactory factory = new SPGDayFactory();
 
@@ -186,9 +194,7 @@
     // Test that the lexical form of the date is correct
     assertTrue("GDay lexical form was not " + VALID_DATE +
                " as expected. was:" + gDay.getLexicalForm(),
-               !westOfGMT ? 
-           		   gDay.getLexicalForm().equals(VALID_DATE)
-           		   : gDay.getLexicalForm().equals( VALID_DATE_WEST ) );
+               gDay.getLexicalForm().equals(VALID_DATE));
 
     // Retrieve the byte data of the gDay object
     ByteBuffer dayBytes = gDay.getData();
@@ -205,17 +211,15 @@
     // Test the correct value is stored
     assertTrue("GDay byte buffer value was not " + VALID_DATE +
                " as expected, was: " + day,
-               !westOfGMT ?
-            	("" + day).equals(VALID_DATE)
-                 : ("" + day).equals(VALID_DATE_WEST)
-                 );
+            	("" + day).equals(VALID_DATE));
 
     // Byte buffer to hold our date information
-    ByteBuffer buffer = ByteBuffer.wrap(new byte[Constants.SIZEOF_LONG]);
+    ByteBuffer buffer = ByteBuffer.wrap(new byte[SPGDayImpl.getBufferSize()]);
 
     // If the previous step passed then we know the long value is what we want,
     // so store it in our buffer
     buffer.putLong(dayLong);
+    buffer.put((byte)1);
 
     // Reset the buffer for reading
     buffer.flip();
@@ -227,6 +231,7 @@
 
       log.debug("Original day long vs. stored long: " + dayLong + " vs. " +
                 buffer.getLong());
+      buffer.get();
 
       // Reset the buffer
       buffer.flip();
@@ -237,10 +242,8 @@
 
     // Test that the lexical form of the date is correct
     assertTrue("GDay lexical form was not " + VALID_DATE +
-               " as expected. was:" +
-               gDay.getLexicalForm(),
-                  !westOfGMT ? gDay.getLexicalForm().equals(VALID_DATE)
-            		: gDay.getLexicalForm().equals(VALID_DATE_WEST ) );
+               " as expected. was:" + gDay.getLexicalForm(),
+                  gDay.getLexicalForm().equals(VALID_DATE));
 
     // Retrieve the byte data of the gDay object
     dayBytes = gDay.getData();
@@ -257,18 +260,16 @@
     // Test the correct value is stored
     assertTrue("GDay byte buffer value was not " + VALID_DATE +
                " as expected, was: " + day,
-               !westOfGMT ? ("" + day).equals(VALID_DATE)
-            	: ("" + day).equals(VALID_DATE_WEST ) );
+               ("" + day).equals(VALID_DATE));
 
     // Create a gDay object by lexical string (testing range acceptance)
     gDay = (SPGDayImpl) factory.newSPTypedLiteral(XSD.GDAY_URI,
                                                   VALID_DATE2);
 
     // Test that the lexical form of the date is correct
-    assertTrue("GDay lexical form was not " + VALID_DATE3 +
+    assertTrue("GDay lexical form was not " + VALID_DATE2 +
                " as expected. was:" + gDay.getLexicalForm(),
-               ! westOfGMT ? gDay.getLexicalForm().equals(VALID_DATE3)
-            	: gDay.getLexicalForm().equals(VALID_DATE3_WEST ));
+               gDay.getLexicalForm().equals(VALID_DATE2));
 
     // Retrieve the byte data of the gDay object
     dayBytes = gDay.getData();
@@ -295,8 +296,7 @@
     // Test that the lexical form of the date is correct
     assertTrue("GDay lexical form was not " + VALID_DATE3 +
                " as expected. was:" + gDay.getLexicalForm(),
-               ! westOfGMT ? gDay.getLexicalForm().equals(VALID_DATE3)
-                   	: gDay.getLexicalForm().equals(VALID_DATE3_WEST ));               
+               gDay.getLexicalForm().equals(VALID_DATE3));               
 
     // Retrieve the byte data of the gDay object
     dayBytes = gDay.getData();
@@ -323,8 +323,7 @@
     // Test that the lexical form of the date is correct
     assertTrue("GDay lexical form was not " + VALID_DATE4 +
                " as expected. was:" + gDay.getLexicalForm(),
-               !westOfGMT ? gDay.getLexicalForm().equals(VALID_DATE4) 
-            	 : gDay.getLexicalForm().equals(VALID_DATE4_WEST) );
+               gDay.getLexicalForm().equals(VALID_DATE4));
 
     // Retrieve the byte data of the gDay object
     dayBytes = gDay.getData();
@@ -341,8 +340,34 @@
     // Test the correct value is stored
     assertTrue("GDay byte buffer value was not " + VALID_DATE4 +
                " as expected, was: " + day,
-               !westOfGMT ? ("" + day).equals(VALID_DATE4)
+               !westOfGMT ? ("" + day).equals(VALID_DATE4_EAST)
             	 : ("" + day).equals(VALID_DATE4_WEST) );
+
+    // Create a gDay object by lexical string (testing timezone acceptance)
+    gDay = (SPGDayImpl) factory.newSPTypedLiteral(XSD.GDAY_URI, VALID_DATE5);
+
+    // Test that the lexical form of the date is correct
+    assertTrue("GDay lexical form was not " + VALID_DATE5 +
+               " as expected. was:" + gDay.getLexicalForm(),
+               gDay.getLexicalForm().equals(VALID_DATE5));
+
+    // Retrieve the byte data of the gDay object
+    dayBytes = gDay.getData();
+
+    // Retrieve the long value from the buffer
+    dayLong = dayBytes.getLong();
+
+    // Create a date object from the day's long
+    dayDate = new Date(dayLong);
+
+    // Format the resulting day
+    day = format.format(dayDate);
+
+    // Test the correct value is stored
+    assertTrue("GDay byte buffer value was not " + VALID_DATE5 +
+               " as expected, was: " + day,
+               !westOfGMT ? ("" + day).equals(VALID_DATE5_EAST)
+               : ("" + day).equals(VALID_DATE5_WEST) );
   }
 
   /**

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayImpl.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayImpl.java	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayImpl.java	2008-09-23 04:36:54 UTC (rev 1267)
@@ -29,369 +29,120 @@
 // Java 2 standard packages
 import java.net.URI;
 import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Calendar;
 
 // Third party packages
 import org.apache.log4j.Logger;
-import com.hp.hpl.jena.datatypes.xsd.impl.XSDMonthDayType;
-import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
 
 // Locally written packages
 import org.mulgara.query.rdf.XSD;
-import org.mulgara.store.stringpool.*;
-import org.mulgara.util.Constants;
+import org.mulgara.util.Timezone;
 
 /**
  * An SPObject that represents a specific day in a specific month of Gregorian
  * Calendars.
+ * Format: --MM-DD
  *
  * @created 2004-10-06
  *
  * @author Mark Ludlow
- *
- * @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>
- *
+ * @author Paul Gearon
+ * @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 SPGMonthDayImpl extends AbstractSPTypedLiteral {
+public final class SPGMonthDayImpl extends AbstractSPGDateTime {
 
   private final static Logger logger = Logger.getLogger(SPGMonthDayImpl.class);
 
-  /** The date representation for the monthDay */
-  private Calendar monthDay;
-
   static final int TYPE_ID = 9; // Unique ID
 
   /** URI for our gmonthDay representation */
   static final URI TYPE_URI = XSD.GMONTHDAY_URI;
 
-  /** Indicator as to whether we have a time zone or not */
-  private boolean hasTimeZone;
+  /** The number of dashes that appear without a timezone */
+  static private final int STD_DASHES = 3;
 
   /**
    * Constructs a new GMonthDay representation using a calendar object representation.
-   *
    * @param monthDayDate The gMonthDay object represented as an integer
    */
   SPGMonthDayImpl(Date monthDayDate) {
-
-    // Call the super constructor
-    super(TYPE_ID, TYPE_URI);
-
-    // Initialise the calendar object
-    monthDay = Calendar.getInstance();
-
-    // Store the monthDay date as a calendar
-    monthDay.setTime(monthDayDate);
+    super(TYPE_ID, TYPE_URI, monthDayDate);
   }
 
   /**
    * Constructs a new GMonthDay representation using a calendar object representation.
-   *
    * @param monthDayCalendar The gMonthDay object represented as a calendar
    */
-  SPGMonthDayImpl(Calendar monthDayCalendar) {
-
-    // Call the super constructor
-    super(TYPE_ID, TYPE_URI);
-
-    // Store the monthDay date as a calendar
-    monthDay = monthDayCalendar;
+  SPGMonthDayImpl(Calendar monthDayCalendar, Timezone tz) {
+    super(TYPE_ID, TYPE_URI, monthDayCalendar, tz);
   }
 
   /**
-   *
-   * Constructs a gMonthDay object which reads the monthDay value from a byte buffer as
-   * an integer.
-   *
+   * Constructs a gMonthDay object which reads the monthDay value from a byte buffer as an integer.
    * @param data The byte buffer storing the monthDay as an integer
    */
   SPGMonthDayImpl(ByteBuffer data) {
-
-    // Call the constructor using a long for the date
-    this(data.getLong());
+    super(TYPE_ID, TYPE_URI, data);
   }
 
   /**
    * Creates a new gMonthDay representation using a long value of the monthDay
    * and creating a Date object from it.
-   *
    * @param monthDayLong The monthDay as a long
    */
   SPGMonthDayImpl(long monthDayLong) {
-
-    // Use the date constructor to create a new instance
-    this(new Date(monthDayLong));
+    super(TYPE_ID, TYPE_URI, monthDayLong);
   }
 
   /**
    * Constructs a new GMonthDay object given the lexical form of a date.
-   *
    * @param lexicalForm The lexical form of the GMonthDay object
    * @return A new SPGMonthDay instance
    */
   static SPGMonthDayImpl newInstance(String lexicalForm) {
-
-    // The XSD monthDay type object we are creating
-    SPGMonthDayImpl monthDayImpl = null;
-
-    // Container for our date time object
-    XSDDateTime dateTime = null;
-
-    // Create a data type to represent a gMonthDay
-    XSDMonthDayType dataType = new XSDMonthDayType("gMonthDay");
-
-    try {
-
-      // Create a date time object to parse out our date
-      dateTime = (XSDDateTime) dataType.parseValidated(lexicalForm);
-    } catch (RuntimeException ex) {
-
-      // Since the highest level exception that can occur during parsing is the
-      // runtime exception, we should capture them and report a bad lexical
-      // formation
-      throw new IllegalArgumentException("Invalid gMonthDay lexical format: " +
-                                         lexicalForm);
+    if (lexicalForm.length() < 7 || !lexicalForm.startsWith("--") || lexicalForm.charAt(4) != '-') {
+      throw new IllegalArgumentException("Invalid gMonthDay lexical format: " + lexicalForm);
     }
 
-    // Jena wraps date values larger than 12, which we don't want, so we take
-    // the valid date (because it parsed) and check that it is within bounds
-    String dateValue = lexicalForm.substring(2, 4);
+    String monthValue = lexicalForm.substring(2, 4);
+    int monthInt = Integer.parseInt(monthValue);
 
-    // Parse the value to an integer (We know it is a valid number)
-    int dateInt = Integer.parseInt(dateValue);
-
     // Check that the value is valid
-    if (dateInt <= 0 || dateInt >= 13) {
-
+    if (monthInt <= 0 || monthInt >= 13) {
       throw new IllegalArgumentException("gMonthDay value [" + lexicalForm +
                                          "] does not have a valid month number.");
     }
+    String dayValue = lexicalForm.substring(5, 7);
+    int dayInt = Integer.parseInt(dayValue);
 
-    // Jena uses the day value as day of year, except we want day of month so we
-    // need to perform a check that the day is within valid bounds
-    dateValue = lexicalForm.substring(5, 7);
-
-    // Parse the value to an integer (We know it is a valid number)
-    dateInt = Integer.parseInt(dateValue);
-
     // Check that the value is valid
-    if (dateInt <= 0 || dateInt >= 32) {
-
+    if (dayInt <= 0 || dayInt >= 32) {
       throw new IllegalArgumentException("gMonthDay value [" + lexicalForm +
                                          "] does have a valid day number.");
     }
 
-    // Get the date/time object as a calendar
-    Calendar calendar = dateTime.asCalendar();
+    // Create a timezone for this object
+    Timezone tz = scanForTimezone(lexicalForm, STD_DASHES);
 
-    // Jena does not observe the zero based structure of the Calendar object
-    // so we need to adjust for this
-    calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
+    Calendar calendar = createCalendar(tz);
 
-    if (logger.isDebugEnabled()) {
+    calendar.set(Calendar.MONTH, monthInt - 1);
+    calendar.set(Calendar.DAY_OF_MONTH, dayInt);
 
-      logger.debug("Calendar lexical string is: " +
-                   calendar.get(Calendar.YEAR) + "-" +
-                   calendar.get(Calendar.MONTH) + "-" +
-                   calendar.get(Calendar.DAY_OF_MONTH));
-      logger.debug("Calendar as date: " + calendar.getTime().toString());
+    if (logger.isDebugEnabled()) {
+      logger.debug("Day value before calendar is: " + dayInt);
+      logger.debug("Month value before calendar is: " + monthInt);
     }
 
     // Create our object
-    monthDayImpl = new SPGMonthDayImpl(calendar);
-
-    if (lexicalForm.indexOf("Z") > 1 || lexicalForm.indexOf("-", 6) > 0 ||
-        lexicalForm.indexOf("+") > 1) {
-
-      // If we have a timezone then set the flag to be true
-      monthDayImpl.setHasTimeZone(true);
-    }
-
-    return monthDayImpl;
+    return new SPGMonthDayImpl(calendar, tz);
   }
 
-  /**
-   * A local method to set whether we have a timezone or not.
-   *
-   * @param value Whether we have a time zone or not
-   */
-  public void setHasTimeZone(boolean value) {
 
-    // Store whether we have a timezone or not
-    hasTimeZone = value;
+  protected String getFormatString() {
+    return "'--'MM-dd";
   }
 
-  /**
-   * Converts this gMonthDay object to a buffer of byte data.
-   *
-   * @return The byte representation of this gMonthDay object
-   */
-  public ByteBuffer getData() {
-
-    // Create a new byte buffer that can hold a long object
-    ByteBuffer data = ByteBuffer.allocate(Constants.SIZEOF_LONG);
-
-    // Store the date as a long value
-    data.putLong(monthDay.getTimeInMillis());
-
-    // Prepare the buffer for reading
-    data.flip();
-
-    return data;
-  }
-
-  /**
-   * Create a new comparator for comparison operations.
-   *
-   * @return The comparator to be used for comparisons
-   */
-  public SPComparator getSPComparator() {
-
-    return SPGMonthDayComparator.getInstance();
-  }
-
-  /**
-   * Convert the gMonthDay representation to a lexical string as defined by XSD
-   * datatypes.
-   *
-   * @return The lexical form of the gMonthDay object
-   */
-  public String getLexicalForm() {
-
-    // Create the default format string
-    String formatString = "'--'MM-dd";
-
-    if (hasTimeZone) {
-
-      formatString += "'Z'";
-    }
-
-    // Create a formatter to parse the date
-    SimpleDateFormat formatter = new SimpleDateFormat(formatString);
-
-    // Apply the formatting
-    return formatter.format(monthDay.getTime());
-  }
-
-  /**
-   * Compares this gMonthDay representation to another object to see if they are
-   * the same values.  First the typing is checked and then the value.
-   *
-   * @param object The object we are comparing against
-   *
-   * @return Whether the gMonthDay value is greater than (> 0), less than (< 0), or
-   *         equal to (0) this value
-   */
-  public int compareTo(SPObject object) {
-
-    // Compare types.
-    int comparison = super.compareTo(object);
-
-    // If we have not got matching types return the value
-    if (comparison != 0) return comparison;
-
-    // Compare the dates lexiocally
-    return getLexicalForm().compareTo(((SPGMonthDayImpl) object).getLexicalForm());
-  }
-
-  /**
-   * Calculate the hash code for the gMonthDay object
-   *
-   * @return The hash code for the object
-   */
-  public int hashCode() {
-
-    return monthDay.hashCode();
-  }
-
-  /**
-   * Determines whether the object is equal to the one passed in, in both type
-   * and value.  This is different to the compareTo(Object) method in the
-   * respect that it does a direct comparison, not a ranking comparison.
-   *
-   * @param object The object to compare this one to
-   *
-   * @return Whether the object is the same as this one
-   */
-  public boolean equals(Object object) {
-
-    // Check for null.
-    if (object == null) {
-
-      return false;
-    }
-
-    if (object.getClass().isInstance(this)) {
-
-      // If the object is also a gMonthDay object then compare the date
-      return ((SPGMonthDayImpl) object).getLexicalForm().equals(getLexicalForm());
-    } else {
-
-      // The object is of a different type and not equal
-      return false;
-    }
-  }
-
-  /**
-   * Implementation of an SPComparator which compares the binary representations
-   * of a GMonthDay object.
-   */
-  public static class SPGMonthDayComparator implements SPComparator {
-
-    /** Singleton instance of the comparator */
-    private static final SPGMonthDayComparator INSTANCE = new SPGMonthDayComparator();
-
-    /**
-     * Retrieves the singleton instance of this comparator.
-     *
-     * @return The comparator singleton instance
-     */
-    public static SPGMonthDayComparator getInstance() {
-
-      return INSTANCE;
-    }
-
-    /**
-     * Gives the comparator an opportunity to return an ordering where only the
-     * prefix of the binary representation of one or both SPObjects is available.
-     * If the comparator does not support this method or if an ordering can not
-     * be determined from the available data then zero (0) should be returned.
-     *
-     * @param d1 The first gMonthDay's byte buffer
-     * @param d2 The second gMonthDay's byte buffer
-     * @param d2Size The number of bytes to compare
-     *
-     * @return Whether the first prefix is greater than (> 0), less than (< 0),
-     *         or equal to (0) the other
-     */
-    public int comparePrefix(ByteBuffer d1, ByteBuffer d2, int d2Size) {
-      return 0;
-    }
-
-    /**
-     * Compares the content of a byte buffer to the other and determines whether
-     * they are equal or not.
-     *
-     * @param d1 The first byte buffer
-     * @param d2 The second byte buffer
-     * @return Whether the first buffer's content is greater than (> 0), less
-     *         than (< 0), or equal to (0) the other
-     */
-    public int compare(ByteBuffer d1, int st1, ByteBuffer d2, int st2) {
-      return AbstractSPObject.compare(d1.getLong(), d2.getLong());
-    }
-
-  }
 }

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayUnitTest.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayUnitTest.java	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthDayUnitTest.java	2008-09-23 04:36:54 UTC (rev 1267)
@@ -30,14 +30,11 @@
 import java.util.Date;
 import java.util.TimeZone;
 import java.text.SimpleDateFormat;
-import java.net.URL;
-import java.net.MalformedURLException;
 import java.nio.ByteBuffer;
 
 // Third party packages
 import junit.framework.*;
 import org.apache.log4j.*;
-import org.apache.log4j.xml.*;
 
 import org.mulgara.query.rdf.XSD;
 import org.mulgara.store.stringpool.*;
@@ -125,15 +122,11 @@
     // Load the logging configuration
     BasicConfigurator.configure();
 
-    try {
-
-      DOMConfigurator.configure(new URL(System.getProperty(
-          "log4j.configuration")));
-    } catch (MalformedURLException mue) {
-
-      log.error("Unable to configure logging service from XML configuration " +
-                "file", mue);
-    }
+//    try {
+//      DOMConfigurator.configure(new URL(System.getProperty("log4j.configuration")));
+//    } catch (MalformedURLException mue) {
+//      log.error("Unable to configure logging service from XML configuration file", mue);
+//    }
   }
 
   /**
@@ -178,14 +171,10 @@
     SPGMonthDayFactory factory = new SPGMonthDayFactory();
 
     // Create a gMonthDay object by lexical string
-    SPGMonthDayImpl gMonthDay = (SPGMonthDayImpl) factory.newSPTypedLiteral(XSD.
-        GMONTHDAY_URI, VALID_DATE);
+    SPGMonthDayImpl gMonthDay = (SPGMonthDayImpl)factory.newSPTypedLiteral(XSD.GMONTHDAY_URI, VALID_DATE);
 
     // Test that the lexical form of the date is correct
-    assertTrue("GMonthDay lexical form was not " + VALID_DATE +
-               " as expected. was:" + gMonthDay.getLexicalForm(),
-               !westOfGMT ? gMonthDay.getLexicalForm().equals(VALID_DATE)
-            		   : gMonthDay.getLexicalForm().equals(VALID_DATE_WEST) );
+    assertEquals(VALID_DATE, gMonthDay.getLexicalForm());
 
     // Retrieve the byte data of the gMonthDay object
     ByteBuffer monthDayBytes = gMonthDay.getData();
@@ -201,16 +190,15 @@
 
     // Test the correct value is stored
     assertTrue("GMonthDay byte buffer value was not " + VALID_DATE +
-       " as expected, was: " + monthDay,
-        !westOfGMT ? ("" + monthDay).equals(VALID_DATE)
-        	: ("" + monthDay).equals(VALID_DATE_WEST) );
+       " as expected, was: " + monthDay, ("" + monthDay).equals(VALID_DATE));
 
     // Byte buffer to hold our date information
-    ByteBuffer buffer = ByteBuffer.wrap(new byte[Constants.SIZEOF_LONG]);
+    ByteBuffer buffer = ByteBuffer.wrap(new byte[SPGMonthDayImpl.getBufferSize()]);
 
     // If the previous step passed then we know the long value is what we want,
     // so store it in our buffer
     buffer.putLong(monthDayLong);
+    buffer.put((byte)1);
 
     // Reset the buffer for reading
     buffer.flip();
@@ -223,6 +211,7 @@
       log.debug("Original monthDay long vs. stored long: " + monthDayLong +
                 " vs. " +
                 buffer.getLong());
+      buffer.get();
 
       // Reset the buffer
       buffer.flip();
@@ -233,10 +222,8 @@
 
     // Test that the lexical form of the date is correct
     assertTrue("GMonthDay lexical form was not " + VALID_DATE +
-               " as expected. was:" +
-               gMonthDay.getLexicalForm(),
-               !westOfGMT ? gMonthDay.getLexicalForm().equals(VALID_DATE)
-            	: gMonthDay.getLexicalForm().equals(VALID_DATE_WEST) );
+               " as expected. was:" + gMonthDay.getLexicalForm(),
+               gMonthDay.getLexicalForm().equals(VALID_DATE));
 
     // Retrieve the byte data of the gMonthDay object
     monthDayBytes = gMonthDay.getData();
@@ -253,18 +240,15 @@
     // Test the correct value is stored
     assertTrue("GMonthDay byte buffer value was not " + VALID_DATE +
                " as expected, was: " + monthDay,
-         !westOfGMT ? ("" + monthDay).equals(VALID_DATE)
-        		 : ("" + monthDay).equals(VALID_DATE_WEST) );
+               ("" + monthDay).equals(VALID_DATE));
 
     // Create a gMonthDay object by lexical string (testing range acceptance)
-    gMonthDay = (SPGMonthDayImpl) factory.newSPTypedLiteral(XSD.GMONTHDAY_URI,
-        VALID_DATE2);
+    gMonthDay = (SPGMonthDayImpl) factory.newSPTypedLiteral(XSD.GMONTHDAY_URI, VALID_DATE2);
 
     // Test that the lexical form of the date is correct
-    assertTrue("GMonthDay lexical form was not " + VALID_DATE3 +
+    assertTrue("GMonthDay lexical form was not " + VALID_DATE2 +
                " as expected. was:" + gMonthDay.getLexicalForm(),
-             !westOfGMT ? gMonthDay.getLexicalForm().equals(VALID_DATE3)
-                : gMonthDay.getLexicalForm().equals(VALID_DATE3_WEST) );
+               gMonthDay.getLexicalForm().equals(VALID_DATE2));
 
     // Retrieve the byte data of the gMonthDay object
     monthDayBytes = gMonthDay.getData();
@@ -285,14 +269,12 @@
             	 : ("" + monthDay).equals(VALID_DATE_WEST) );
 
     // Create a gMonthDay object by lexical string (testing timezone acceptance)
-    gMonthDay = (SPGMonthDayImpl) factory.newSPTypedLiteral(XSD.GMONTHDAY_URI,
-        VALID_DATE3);
+    gMonthDay = (SPGMonthDayImpl) factory.newSPTypedLiteral(XSD.GMONTHDAY_URI, VALID_DATE3);
 
     // Test that the lexical form of the date is correct
     assertTrue("GMonthDay lexical form was not " + VALID_DATE3 +
                " as expected. was:" + gMonthDay.getLexicalForm(),
-            !westOfGMT ? gMonthDay.getLexicalForm().equals(VALID_DATE3)
-           		: gMonthDay.getLexicalForm().equals(VALID_DATE3_WEST) );
+               gMonthDay.getLexicalForm().equals(VALID_DATE3));
 
     // Retrieve the byte data of the gMonthDay object
     monthDayBytes = gMonthDay.getData();
@@ -309,8 +291,8 @@
     // Test the correct value is stored
     assertTrue("GMonthDay byte buffer value was not " + VALID_DATE +
                " as expected, was: " + monthDay,
-        !westOfGMT ? ("" + monthDay).equals(VALID_DATE)
-        	: ("" + monthDay).equals(VALID_DATE_WEST ) );
+               !westOfGMT ? ("" + monthDay).equals(VALID_DATE)
+        	     : ("" + monthDay).equals(VALID_DATE_WEST ) );
   }
 
   /**

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthImpl.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthImpl.java	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthImpl.java	2008-09-23 04:36:54 UTC (rev 1267)
@@ -29,357 +29,107 @@
 // Java 2 standard packages
 import java.net.URI;
 import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Calendar;
 
 // Third party packages
 import org.apache.log4j.Logger;
-import com.hp.hpl.jena.datatypes.xsd.impl.XSDMonthType;
-import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
 
 // Locally written packages
 import org.mulgara.query.rdf.XSD;
-import org.mulgara.store.stringpool.*;
-import org.mulgara.util.Constants;
+import org.mulgara.util.Timezone;
 
 /**
  * An SPObject that represents yearly periodic Gregorian calendar months.
+ * Format: --MM
  *
  * @created 2004-10-06
- *
  * @author Mark Ludlow
- *
- * @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>
- *
+ * @author Paul Gearon
+ * @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 SPGMonthImpl extends AbstractSPTypedLiteral {
+public final class SPGMonthImpl extends AbstractSPGDateTime {
 
   private final static Logger logger = Logger.getLogger(SPGMonthImpl.class);
 
-  /** The date representation for the month */
-  private Calendar month;
-
   static final int TYPE_ID = 11; // Unique ID
 
   /** URI for our gmonth representation */
   static final URI TYPE_URI = XSD.GMONTH_URI;
 
-  /** Indicator as to whether we have a time zone or not */
-  private boolean hasTimeZone;
+  /** The number of dashes that appear without a timezone */
+  static private final int STD_DASHES = 2;
 
+
   /**
    * Constructs a new GMonth representation using a calendar object representation.
-   *
    * @param monthDate The gMonth object represented as an integer
    */
   SPGMonthImpl(Date monthDate) {
-
-    // Call the super constructor
-    super(TYPE_ID, TYPE_URI);
-
-    // Initialise the calendar object
-    month = Calendar.getInstance();
-
-    // Store the month date as a calendar
-    month.setTime(monthDate);
+    super(TYPE_ID, TYPE_URI, monthDate);
   }
 
   /**
    * Constructs a new GMonth representation using a calendar object representation.
-   *
    * @param monthCalendar The gMonth object represented as a calendar
    */
-  SPGMonthImpl(Calendar monthCalendar) {
-
-    // Call the super constructor
-    super(TYPE_ID, TYPE_URI);
-
-    // Store the month date as a calendar
-    month = monthCalendar;
+  SPGMonthImpl(Calendar monthCalendar, Timezone tz) {
+    super(TYPE_ID, TYPE_URI, monthCalendar, tz);
   }
 
   /**
-   *
-   * Constructs a gMonth object which reads the month value from a byte buffer as
-   * an integer.
-   *
+   * Constructs a gMonth object which reads the month value from a byte buffer as an integer.
    * @param data The byte buffer storing the month as an integer
    */
   SPGMonthImpl(ByteBuffer data) {
-
-    // Call the constructor using a long for the date
-    this(data.getLong());
+    super(TYPE_ID, TYPE_URI, data);
   }
 
   /**
    * Creates a new gMonth representation using a long value of the month
    * and creating a Date object from it.
-   *
    * @param monthLong The month as a long
    */
   SPGMonthImpl(long monthLong) {
-
-    // Use the date constructor to create a new instance
-    this(new Date(monthLong));
+    super(TYPE_ID, TYPE_URI, monthLong);
   }
 
   /**
    * Constructs a new GMonth object given the lexical form of a date.
-   *
    * @param lexicalForm The lexical form of the GMonth object
    * @return A new SPGMonth instance
    */
   static SPGMonthImpl newInstance(String lexicalForm) {
-
-    // The XSD month type object we are creating
-    SPGMonthImpl monthImpl = null;
-
-    // Container for our date time object
-    XSDDateTime dateTime = null;
-
-    // Create a data type to represent a gMonth
-    XSDMonthType dataType = new XSDMonthType("gMonth");
-
-    try {
-
-      // Create a date time object to parse out our date
-      dateTime = (XSDDateTime) dataType.parseValidated(lexicalForm);
-    } catch (RuntimeException ex) {
-
-      // Since the highest level exception that can occur during parsing is the
-      // runtime exception, we should capture them and report a bad lexical
-      // formation
-      throw new IllegalArgumentException("Invalid gMonth lexical format: " +
-                                         lexicalForm);
+    if (lexicalForm.length() < 4 || !lexicalForm.startsWith("--")) {
+      throw new IllegalArgumentException("Invalid gDay lexical format: " + lexicalForm);
     }
 
-    // Jena wraps date values larger than 12, which we don't want, so we take
-    // the valid date (because it parsed) and check that it is within bounds
     String dateValue = lexicalForm.substring(2, 4);
-
-    // Parse the value to an integer (We know it is a valid number)
     int dateInt = Integer.parseInt(dateValue);
 
     // Check that the value is valid
     if (dateInt <= 0 || dateInt >= 13) {
-
-      throw new IllegalArgumentException("gMonth value [" + lexicalForm +
-                                         "] is not a valid month number.");
+      throw new IllegalArgumentException("gMonth value [" + lexicalForm + "] is not a valid month number.");
     }
 
-    // Get the date/time object as a calendar
-    Calendar calendar = dateTime.asCalendar();
+    // Create a timezone for this object
+    Timezone tz = scanForTimezone(lexicalForm, STD_DASHES);
 
-    // Jena does not observe the zero based structure of the Calendar object
-    // so we need to adjust for this
-    calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
+    Calendar calendar = createCalendar(tz);
+    calendar.set(Calendar.MONTH, dateInt - 1);
 
-    if (logger.isDebugEnabled()) {
+    if (logger.isDebugEnabled()) logger.debug("Month value before calendar is: " + dateValue);
 
-      logger.debug("Month value before calendar is: " + dateTime.getMonths());
-      logger.debug("Calendar lexical string is: " +
-                   calendar.get(Calendar.YEAR) + "-" +
-                   calendar.get(Calendar.MONTH) + "-" +
-                   calendar.get(Calendar.DAY_OF_MONTH));
-      logger.debug("TimeZone of calendar is: " +
-                   calendar.getTimeZone().toString());
-      logger.debug("Calendar as date: " + calendar.getTime().toString());
-    }
-
-    // Create our object
-    monthImpl = new SPGMonthImpl(calendar);
-
-    if (lexicalForm.indexOf("Z") > 1 || lexicalForm.split("-").length == 6 ||
-        lexicalForm.split("-").length == 4 || lexicalForm.indexOf("+") > 1) {
-
-      // If we have a timezone then set the flag to be true
-      monthImpl.setHasTimeZone(true);
-    }
-
-    return monthImpl;
+    return new SPGMonthImpl(calendar, tz);
   }
 
-  /**
-   * A local method to set whether we have a timezone or not.
-   *
-   * @param value Whether we have a time zone or not
-   */
-  public void setHasTimeZone(boolean value) {
 
-    // Store whether we have a timezone or not
-    hasTimeZone = value;
-  }
-
   /**
-   * Converts this gMonth object to a buffer of byte data.
-   *
-   * @return The byte representation of this gMonth object
+   * @see org.mulgara.store.stringpool.xa.AbstractSPGDateTime#getFormatString()
    */
-  public ByteBuffer getData() {
-
-    // Create a new byte buffer that can hold a long object
-    ByteBuffer data = ByteBuffer.allocate(Constants.SIZEOF_LONG);
-
-    // Store the date as a long value
-    data.putLong(month.getTimeInMillis());
-
-    // Prepare the buffer for reading
-    data.flip();
-
-    return data;
+  protected String getFormatString() {
+    return "'--'MM";
   }
 
-  /**
-   * Create a new comparator for comparison operations.
-   *
-   * @return The comparator to be used for comparisons
-   */
-  public SPComparator getSPComparator() {
-
-    return SPGMonthComparator.getInstance();
-  }
-
-  /**
-   * Convert the gMonth representation to a lexical string as defined by XSD
-   * datatypes.
-   *
-   * @return The lexical form of the gMonth object
-   */
-  public String getLexicalForm() {
-
-    // Create the default format string
-    String formatString = "'--'MM";
-
-    if (hasTimeZone) {
-
-      formatString += "'Z'";
-    }
-
-    // Create a formatter to parse the date
-    SimpleDateFormat formatter = new SimpleDateFormat(formatString);
-
-    // Apply the formatting
-    return formatter.format(month.getTime());
-  }
-
-  /**
-   * Compares this gMonth representation to another object to see if they are
-   * the same values.  First the typing is checked and then the value.
-   *
-   * @param object The object we are comparing against
-   *
-   * @return Whether the gMonth value is greater than (> 0), less than (< 0), or
-   *         equal to (0) this value
-   */
-  public int compareTo(SPObject object) {
-
-    // Compare types.
-    int comparison = super.compareTo(object);
-
-    // If we have not got matching types return the value
-    if (comparison != 0) return comparison;
-
-    // Compare the dates lexiocally
-    return getLexicalForm().compareTo(((SPGMonthImpl) object).getLexicalForm());
-  }
-
-  /**
-   * Calculate the hash code for the gMonth object
-   *
-   * @return The hash code for the object
-   */
-  public int hashCode() {
-
-    return month.hashCode();
-  }
-
-  /**
-   * Determines whether the object is equal to the one passed in, in both type
-   * and value.  This is different to the compareTo(Object) method in the
-   * respect that it does a direct comparison, not a ranking comparison.
-   *
-   * @param object The object to compare this one to
-   *
-   * @return Whether the object is the same as this one
-   */
-  public boolean equals(Object object) {
-
-    // Check for null.
-    if (object == null) {
-
-      return false;
-    }
-
-    if (object.getClass().isInstance(this)) {
-
-      // If the object is also a gMonth object then compare the date
-      return ((SPGMonthImpl) object).getLexicalForm().equals(getLexicalForm());
-    } else {
-
-      // The object is of a different type and not equal
-      return false;
-    }
-  }
-
-  /**
-   * Implementation of an SPComparator which compares the binary representations
-   * of a GMonth object.
-   */
-  public static class SPGMonthComparator implements SPComparator {
-
-    /** Singleton instance of the comparator */
-    private static final SPGMonthComparator INSTANCE = new SPGMonthComparator();
-
-    /**
-     * Retrieves the singleton instance of this comparator.
-     *
-     * @return The comparator singleton instance
-     */
-    public static SPGMonthComparator getInstance() {
-
-      return INSTANCE;
-    }
-
-    /**
-     * Gives the comparator an opportunity to return an ordering where only the
-     * prefix of the binary representation of one or both SPObjects is available.
-     * If the comparator does not support this method or if an ordering can not
-     * be determined from the available data then zero (0) should be returned.
-     *
-     * @param d1 The first gMonth's byte buffer
-     * @param d2 The second gMonth's byte buffer
-     * @param d2Size The number of bytes to compare
-     *
-     * @return Whether the first prefix is greater than (> 0), less than (< 0),
-     *         or equal to (0) the other
-     */
-    public int comparePrefix(ByteBuffer d1, ByteBuffer d2, int d2Size) {
-      return 0;
-    }
-
-    /**
-     * Compares the content of a byte buffer to the other and determines whether
-     * they are equal or not.
-     *
-     * @param d1 The first byte buffer
-     * @param d2 The second byte buffer
-     * @return Whether the first buffer's content is greater than (> 0), less
-     *         than (< 0), or equal to (0) the other
-     */
-    public int compare(ByteBuffer d1, int st1, ByteBuffer d2, int st2) {
-      return AbstractSPObject.compare(d1.getLong(), d2.getLong());
-    }
-
-  }
 }

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthUnitTest.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthUnitTest.java	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGMonthUnitTest.java	2008-09-23 04:36:54 UTC (rev 1267)
@@ -28,6 +28,7 @@
 package org.mulgara.store.stringpool.xa;
 
 import java.util.Date;
+import java.util.TimeZone;
 import java.text.SimpleDateFormat;
 import java.net.URL;
 import java.net.MalformedURLException;
@@ -73,6 +74,9 @@
   /** Constant valid test date */
   private static final String VALID_DATE = "--04";
 
+  /** Constant valid test date, west of UTC */
+  private static final String VALID_DATE_WEST = "--03";
+
   /** Constant valid test date (Timezone added) */
   private static final String VALID_DATE2 = "--04-04:00";
 
@@ -184,11 +188,12 @@
                ("" + month).equals(VALID_DATE));
 
     // Byte buffer to hold our date information
-    ByteBuffer buffer = ByteBuffer.wrap(new byte[Constants.SIZEOF_LONG]);
+    ByteBuffer buffer = ByteBuffer.wrap(new byte[SPGMonthImpl.getBufferSize()]);
 
     // If the previous step passed then we know the long value is what we want,
     // so store it in our buffer
     buffer.putLong(monthLong);
+    buffer.put((byte)1);
 
     // Reset the buffer for reading
     buffer.flip();
@@ -200,6 +205,7 @@
 
       log.debug("Original month long vs. stored long: " + monthLong + " vs. " +
                 buffer.getLong());
+      buffer.get();
 
       // Reset the buffer
       buffer.flip();
@@ -235,9 +241,9 @@
     gMonth = (SPGMonthImpl) factory.newSPTypedLiteral(XSD.GMONTH_URI, VALID_DATE2);
 
     // Test that the lexical form of the date is correct
-    assertTrue("GMonth lexical form was not " + VALID_DATE3 +
+    assertTrue("GMonth lexical form was not " + VALID_DATE2 +
                " as expected. was:" + gMonth.getLexicalForm(),
-               gMonth.getLexicalForm().equals(VALID_DATE3));
+               gMonth.getLexicalForm().equals(VALID_DATE2));
 
     // Retrieve the byte data of the gMonth object
     monthBytes = gMonth.getData();
@@ -251,10 +257,13 @@
     // Format the resulting month
     month = format.format(monthDate);
 
+    boolean westOfGMT = TimeZone.getDefault().getRawOffset() < 0;
+
     // Test the correct value is stored
     assertTrue("GMonth byte buffer value was not " + VALID_DATE +
                " as expected, was: " + month,
-               ("" + month).equals(VALID_DATE));
+              !westOfGMT ? ("" + month).equals(VALID_DATE)
+                  : ("" + month).equals(VALID_DATE_WEST) );
 
     // Create a gMonth object by lexical string (testing timezone acceptance)
     gMonth = (SPGMonthImpl) factory.newSPTypedLiteral(XSD.GMONTH_URI,
@@ -280,11 +289,11 @@
     // Test the correct value is stored
     assertTrue("GMonth byte buffer value was not " + VALID_DATE +
                " as expected, was: " + month,
-               ("" + month).equals(VALID_DATE));
+               !westOfGMT ? ("" + month).equals(VALID_DATE)
+                   : ("" + month).equals(VALID_DATE_WEST) );
 
     // Create a gMonth object by lexical string (testing alternate format)
-    gMonth = (SPGMonthImpl) factory.newSPTypedLiteral(XSD.GMONTH_URI,
-        VALID_DATE4);
+    gMonth = (SPGMonthImpl) factory.newSPTypedLiteral(XSD.GMONTH_URI, VALID_DATE4);
 
     // Test that the lexical form of the date is correct
     assertTrue("GMonth lexical form was not " + VALID_DATE +

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearImpl.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearImpl.java	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearImpl.java	2008-09-23 04:36:54 UTC (rev 1267)
@@ -29,324 +29,131 @@
 // Java 2 standard packages
 import java.net.URI;
 import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Calendar;
 
 // Third party packages
 import org.apache.log4j.Logger;
-import com.hp.hpl.jena.datatypes.xsd.impl.XSDYearType;
-import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
 
 // Locally written packages
 import org.mulgara.query.rdf.XSD;
-import org.mulgara.store.stringpool.*;
-import org.mulgara.util.Constants;
+import org.mulgara.util.Timezone;
 
 /**
  * An SPObject that represents non-periodic Gregorian calendar years.
+ * Format: YYYY (no left truncation allowed)
  *
  * @created 2004-10-04
- *
  * @author Mark Ludlow
- *
- * @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>
- *
+ * @author Paul Gearon
+ * @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 SPGYearImpl extends AbstractSPTypedLiteral {
+public final class SPGYearImpl extends AbstractSPGDateTime {
 
   @SuppressWarnings("unused")
   private final static Logger logger = Logger.getLogger(SPGYearImpl.class);
 
-  /** The date representation for the year */
-  private Calendar year;
-
   static final int TYPE_ID = 8; // Unique ID
 
   static final URI TYPE_URI = XSD.GYEAR_URI;
 
-  /** Indicator as to whether we have a time zone or not */
-  private boolean hasTimeZone;
+  /** The number of dashes that appear without a timezone */
+  static private final int STD_DASHES = 0;
 
   /**
    * Constructs a new GYear representation using a calendar object representation.
-   *
    * @param yearDate The gYear object represented as an integer
    */
   SPGYearImpl(Date yearDate) {
-
-    // Call the super constructor
-    super(TYPE_ID, TYPE_URI);
-
-    // Initialise the calendar object
-    year = Calendar.getInstance();
-
-    // Store the year date as a calendar
-    year.setTime(yearDate);
+    super(TYPE_ID, TYPE_URI, yearDate);
   }
 
   /**
    * Constructs a new GYear representation using a calendar object representation.
-   *
    * @param yearCalendar The gYear object represented as a calendar
    */
-  SPGYearImpl(Calendar yearCalendar) {
-
-    // Call the super constructor
-    super(TYPE_ID, TYPE_URI);
-
-    // Store the year date as a calendar
-    year = yearCalendar;
+  SPGYearImpl(Calendar yearCalendar, Timezone tz) {
+    super(TYPE_ID, TYPE_URI, yearCalendar, tz);
   }
 
   /**
-   *
-   * Constructs a gYear object which reads the year value from a byte buffer as
-   * an integer.
-   *
+   * Constructs a gYear object which reads the year value from a byte buffer as an integer.
    * @param data The byte buffer storing the year as an integer
    */
   SPGYearImpl(ByteBuffer data) {
-
-    // Call the constructor using a long for the date
-    this(data.getLong());
+    super(TYPE_ID, TYPE_URI, data);
   }
 
   /**
    * Creates a new gYear representation using a long value of the year
    * and creating a Date object from it.
-   *
    * @param year The year as a long
    */
   SPGYearImpl(long year) {
-
-    // Use the date constructor to create a new instance
-    this(new Date(year));
+    super(TYPE_ID, TYPE_URI, year);
   }
 
   /**
    * Constructs a new GYear object given the lexical form of a date.
-   *
    * @param lexicalForm The lexical form of the GYear object
    * @return A new SPGYear instance
    */
   static SPGYearImpl newInstance(String lexicalForm) {
+    if (lexicalForm.length() < 4) {
+      throw new IllegalArgumentException("Invalid gYear lexical format: " + lexicalForm);
+    }
 
-    // The XSD year type object we are creating
-    SPGYearImpl yearImpl = null;
+    String yearValue = lexicalForm.substring(0, yearEnd(lexicalForm));
 
-    // Container for our date time object
-    XSDDateTime dateTime = null;
-
-    // Create a data type to represent a gYear
-    XSDYearType dataType = new XSDYearType("gYear");
-
+    // Parse the value to an integer
+    int yearInt;
     try {
-
-      // Create a date time object to parse out our date
-      dateTime = (XSDDateTime) dataType.parseValidated(lexicalForm);
-    } catch (RuntimeException ex) {
-
-      // Since the highest level exception that can occur during parsing is the
-      // runtime exception, we should capture them and report a bad lexical
-      // formation
-      throw new IllegalArgumentException("Invalid gYear lexical format: " +
-                                         lexicalForm);
+      yearInt = Integer.parseInt(yearValue);
+    } catch (NumberFormatException e) {
+      throw new IllegalArgumentException("Invalid gYear lexical format: " + lexicalForm);
     }
 
-    // Create our object
-    yearImpl = new SPGYearImpl(dateTime.asCalendar());
+    // Create a timezone for this object
+    Timezone tz = scanForTimezone(lexicalForm, STD_DASHES);
 
-    if (lexicalForm.indexOf("Z") > 1 || lexicalForm.indexOf("-") > 1 ||
-        lexicalForm.indexOf("+") > 1) {
+    Calendar calendar = createCalendar(tz);
 
-      // If we have a timezone then set the flag to be true
-      yearImpl.setHasTimeZone(true);
-    }
+    calendar.set(Calendar.YEAR, yearInt);
 
-    return yearImpl;
-  }
+    if (logger.isDebugEnabled()) logger.debug("Year value before calendar is: " + yearInt);
 
-  /**
-   * A local method to set whether we have a timezone or not.
-   *
-   * @param value Whether we have a time zone or not
-   */
-  public void setHasTimeZone(boolean value) {
-
-    // Store whether we have a timezone or not
-    hasTimeZone = value;
+    // Create our object
+    return new SPGYearImpl(calendar, tz);
   }
 
-  /**
-   * Converts this gYear object to a buffer of byte data.
-   *
-   * @return The byte representation of this gYear object
-   */
-  public ByteBuffer getData() {
 
-    // Create a new byte buffer that can hold a long object
-    ByteBuffer data = ByteBuffer.allocate(Constants.SIZEOF_LONG);
-
-    // Store the date as a long value
-    data.putLong(year.getTimeInMillis());
-
-    // Prepare the buffer for reading
-    data.flip();
-
-    return data;
-  }
-
   /**
-   * Create a new comparator for comparison operations.
-   *
-   * @return The comparator to be used for comparisons
+   * @see org.mulgara.store.stringpool.xa.AbstractSPGDateTime#getFormatString()
    */
-  public SPComparator getSPComparator() {
-
-    return SPGYearComparator.getInstance();
+  protected String getFormatString() {
+    return "yyyy";
   }
 
-  /**
-   * Convert the gYear representation to a lexical string as defined by XSD
-   * datatypes.
-   *
-   * @return The lexical form of the gYear object
-   */
-  public String getLexicalForm() {
 
-    // Create the default format string
-    String formatString = "yyyy";
-
-    if (hasTimeZone) {
-
-      formatString += "'Z'";
-    }
-
-    // Create a formatter to parse the date
-    SimpleDateFormat formatter = new SimpleDateFormat(formatString);
-
-    // Apply the formatting
-    return formatter.format(year.getTime());
-  }
-
   /**
-   * Compares this gYear representation to another object to see if they are
-   * the same values.  First the typing is checked and then the value.
-   *
-   * @param object The object we are comparing against
-   *
-   * @return Whether the gYear value is greater than (> 0), less than (< 0), or
-   *         equal to (0) this value
+   * Finds the end of the year text. This is marked either by the end of the string,
+   * or the start of the timezone.
+   * @param lexical The lexical representation of the gYear.
+   * @return The position of the first character that is not a part of the year.
    */
-  public int compareTo(SPObject object) {
-
-    // Compare types.
-    int comparison = super.compareTo(object);
-
-    // If we have not got matching types return the value
-    if (comparison != 0) return comparison;
-
-    // Compare the dates lexiocally
-    return getLexicalForm().compareTo(((SPGYearImpl) object).getLexicalForm());
-  }
-
-  /**
-   * Calculate the hash code for the gYear object
-   *
-   * @return The hash code for the object
-   */
-  public int hashCode() {
-
-    return year.hashCode();
-  }
-
-  /**
-   * Determines whether the object is equal to the one passed in, in both type
-   * and value.  This is different to the compareTo(Object) method in the
-   * respect that it does a direct comparison, not a ranking comparison.
-   *
-   * @param object The object to compare this one to
-   *
-   * @return Whether the object is the same as this one
-   */
-  public boolean equals(Object object) {
-
-    // Check for null.
-    if (object == null) {
-
-      return false;
-    }
-
-    if (object.getClass().isInstance(this)) {
-
-      // If the object is also a gYear object then compare the date
-      return ((SPGYearImpl) object).getLexicalForm().equals(getLexicalForm());
+  private static int yearEnd(String lexical) {
+    int end = lexical.length();
+    int tzCharPos = lexical.indexOf('+');
+    if (tzCharPos > 0) {
+      if (lexical.indexOf('-') > 0) throw new IllegalArgumentException("Invalid gYear lexical format: " + lexical);
+      end = tzCharPos;
     } else {
-
-      // The object is of a different type and not equal
-      return false;
+      tzCharPos = lexical.indexOf('-');
+      if (tzCharPos > 0) end = tzCharPos;
+      else if (lexical.charAt(end - 1) == 'Z') end--;
     }
+    return end;
   }
 
-  /**
-   * Implementation of an SPComparator which compares the binary representations
-   * of a GYear object.
-   */
-  public static class SPGYearComparator implements SPComparator {
-
-    /** Singleton instance of the comparator */
-    private static final SPGYearComparator INSTANCE = new SPGYearComparator();
-
-    /**
-     * Retrieves the singleton instance of this comparator.
-     *
-     * @return The comparator singleton instance
-     */
-    public static SPGYearComparator getInstance() {
-
-      return INSTANCE;
-    }
-
-    /**
-     * Gives the comparator an opportunity to return an ordering where only the
-     * prefix of the binary representation of one or both SPObjects is available.
-     * If the comparator does not support this method or if an ordering can not
-     * be determined from the available data then zero (0) should be returned.
-     *
-     * @param d1 The first gYear's byte buffer
-     * @param d2 The second gYear's byte buffer
-     * @param d2Size The number of bytes to compare
-     *
-     * @return Whether the first prefix is greater than (> 0), less than (< 0),
-     *         or equal to (0) the other
-     */
-    public int comparePrefix(ByteBuffer d1, ByteBuffer d2, int d2Size) {
-      return 0;
-    }
-
-    /**
-     * Compares the content of a byte buffer to the other and determines whether
-     * they are equal or not.
-     *
-     * @param d1 The first byte buffer
-     * @param d2 The second byte buffer
-     * @return Whether the first buffer's content is greater than (> 0), less
-     *         than (< 0), or equal to (0) the other
-     */
-    public int compare(ByteBuffer d1, int st1, ByteBuffer d2, int st2) {
-      return AbstractSPObject.compare(d1.getLong(), d2.getLong());
-    }
-
-  }
 }

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthImpl.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthImpl.java	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthImpl.java	2008-09-23 04:36:54 UTC (rev 1267)
@@ -29,350 +29,134 @@
 // Java 2 standard packages
 import java.net.URI;
 import java.nio.ByteBuffer;
-import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Calendar;
 
 // Third party packages
 import org.apache.log4j.Logger;
-import com.hp.hpl.jena.datatypes.xsd.impl.XSDYearMonthType;
-import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
 
 // Locally written packages
 import org.mulgara.query.rdf.XSD;
-import org.mulgara.store.stringpool.*;
-import org.mulgara.util.Constants;
+import org.mulgara.util.Timezone;
 
 /**
  * An SPObject that represents a specific month in a specific year of the
  * Gregorian calendar.
+ * Format: YYYY-MM
  *
  * @created 2004-10-06
- *
  * @author Mark Ludlow
- *
- * @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>
- *
+ * @author Paul Gearon
+ * @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 SPGYearMonthImpl extends AbstractSPTypedLiteral {
+public final class SPGYearMonthImpl extends AbstractSPGDateTime {
 
   @SuppressWarnings("unused")
   private final static Logger logger = Logger.getLogger(SPGYearMonthImpl.class);
 
-  /** The date representation for the yearMonth */
-  private Calendar yearMonth;
-
   static final int TYPE_ID = 7; // Unique ID
 
   static final URI TYPE_URI = XSD.GYEARMONTH_URI;
 
-  /** Indicator as to whether we have a time zone or not */
-  private boolean hasTimeZone;
+  /** The number of dashes that appear without a timezone */
+  static private final int STD_DASHES = 1;
 
   /**
    * Constructs a new GYearMonth representation using a calendar object representation.
-   *
    * @param yearMonthDate The gYearMonth object represented as an integer
    */
   SPGYearMonthImpl(Date yearMonthDate) {
-
-    // Call the super constructor
-    super(TYPE_ID, TYPE_URI);
-
-    // Initialise the calendar object
-    yearMonth = Calendar.getInstance();
-
-    // Store the yearMonth date as a calendar
-    yearMonth.setTime(yearMonthDate);
+    super(TYPE_ID, TYPE_URI, yearMonthDate);
   }
 
   /**
    * Constructs a new GYearMonth representation using a calendar object representation.
-   *
    * @param yearMonthCalendar The gYearMonth object represented as a calendar
    */
-  SPGYearMonthImpl(Calendar yearMonthCalendar) {
-
-    // Call the super constructor
-    super(TYPE_ID, TYPE_URI);
-
-    // Store the yearMonth date as a calendar
-    yearMonth = yearMonthCalendar;
+  SPGYearMonthImpl(Calendar yearMonthCalendar, Timezone tz) {
+    super(TYPE_ID, TYPE_URI, yearMonthCalendar, tz);
   }
 
   /**
-   *
-   * Constructs a gYearMonth object which reads the yearMonth value from a byte buffer as
-   * an integer.
-   *
+   * Constructs a gYearMonth object which reads the yearMonth value from a byte buffer as an integer.
    * @param data The byte buffer storing the yearMonth as an integer
    */
   SPGYearMonthImpl(ByteBuffer data) {
-
-    // Call the constructor using a long for the date
-    this(data.getLong());
+    super(TYPE_ID, TYPE_URI, data);
   }
 
   /**
    * Creates a new gYearMonth representation using a long value of the yearMonth
    * and creating a Date object from it.
-   *
    * @param yearMonth The yearMonth as a long
    */
   SPGYearMonthImpl(long yearMonth) {
-
-    // Use the date constructor to create a new instance
-    this(new Date(yearMonth));
+    super(TYPE_ID, TYPE_URI, yearMonth);
   }
 
+
   /**
    * Constructs a new GYearMonth object given the lexical form of a date.
-   *
    * @param lexicalForm The lexical form of the GYearMonth object
    * @return A new SPGYearMonth instance
    */
   static SPGYearMonthImpl newInstance(String lexicalForm) {
+    int dashPos = lexicalForm.indexOf('-');
+    if (lexicalForm.length() < 7 || dashPos < 4) {
+      throw new IllegalArgumentException("Invalid gYearMonth lexical format: " + lexicalForm);
+    }
 
-    // The XSD yearMonth type object we are creating
-    SPGYearMonthImpl yearMonthImpl = null;
+    int lastDashPos = lexicalForm.lastIndexOf('-');
+    int end = (lastDashPos > dashPos) ? lastDashPos : lexicalForm.length();
+    // chop off the last character if this is a Zulu date
+    if (lexicalForm.charAt(end - 1) == 'Z') end--;
 
-    // Container for our date time object
-    XSDDateTime dateTime = null;
+    if (end - dashPos != 3) throw new IllegalArgumentException("Invalid month in gYearMonth lexical format: " + lexicalForm);
 
-    // Create a data type to represent a gYearMonth
-    XSDYearMonthType dataType = new XSDYearMonthType("gYearMonth");
+    String monthValue = lexicalForm.substring(dashPos + 1, end);
+    String yearValue = lexicalForm.substring(0, dashPos);
 
+    // Parse the value to an integer (We know it is a valid number)
+    int monthInt;
+    int yearInt;
     try {
+      monthInt = Integer.parseInt(monthValue);
 
-      // Create a date time object to parse out our date
-      dateTime = (XSDDateTime) dataType.parseValidated(lexicalForm);
-    } catch (RuntimeException ex) {
+      // Check that the value is valid
+      if (monthInt <= 0 || monthInt >= 13) {
+        throw new IllegalArgumentException("gYearMonth value [" + lexicalForm +
+                                           "] does not have a valid month number.");
+      }
 
-      // Since the highest level exception that can occur during parsing is the
-      // runtime exception, we should capture them and report a bad lexical
-      // formation
-      throw new IllegalArgumentException("Invalid gYearMonth lexical format: " +
-                                         lexicalForm);
+      yearInt = Integer.parseInt(yearValue);
+    } catch (NumberFormatException e) {
+      throw new IllegalArgumentException("Invalid gYearMonth lexical format: " + lexicalForm);
     }
 
-    // Find the first character of the date value (because years can be negative
-    // and more than 4 characters
-    int dateStart = lexicalForm.indexOf("-", 1) + 1;
+    // Create a timezone for this object
+    Timezone tz = scanForTimezone(lexicalForm, STD_DASHES);
 
-    // Jena wraps month values larger than 12, which we don't want, so we take
-    // the valid date (because it parsed) and check that it is within bounds
-    String dateValue = lexicalForm.substring(dateStart, dateStart + 2);
+    Calendar calendar = createCalendar(tz);
 
-    // Parse the value to an integer (We know it is a valid number)
-    int dateInt = Integer.parseInt(dateValue);
+    calendar.set(Calendar.YEAR, yearInt);
+    calendar.set(Calendar.MONTH, monthInt - 1);
 
-    // Check that the value is valid
-    if (dateInt <= 0 || dateInt >= 13) {
-
-      throw new IllegalArgumentException("gMonth value [" + lexicalForm +
-                                         "] is not a valid month number.");
+    if (logger.isDebugEnabled()) {
+      logger.debug("Year value before calendar is: " + yearInt);
+      logger.debug("Month value before calendar is: " + monthInt);
     }
 
-    // Get the date/time object as a calendar
-    Calendar calendar = dateTime.asCalendar();
-
-    // Jena does not observe the zero based structure of the Calendar object
-    // so we need to adjust for this
-    calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
-
     // Create our object
-    yearMonthImpl = new SPGYearMonthImpl(calendar);
-
-    if (lexicalForm.indexOf("Z") > 1 || lexicalForm.indexOf("-", dateStart) > 1 ||
-        lexicalForm.indexOf("+") > 1) {
-
-      // If we have a timezone then set the flag to be true
-      yearMonthImpl.setHasTimeZone(true);
-    }
-
-    return yearMonthImpl;
+    return new SPGYearMonthImpl(calendar, tz);
   }
 
-  /**
-   * A local method to set whether we have a timezone or not.
-   *
-   * @param value Whether we have a time zone or not
-   */
-  public void setHasTimeZone(boolean value) {
 
-    // Store whether we have a timezone or not
-    hasTimeZone = value;
-  }
-
   /**
-   * Converts this gYearMonth object to a buffer of byte data.
-   *
-   * @return The byte representation of this gYearMonth object
+   * @see org.mulgara.store.stringpool.xa.AbstractSPGDateTime#getFormatString()
    */
-  public ByteBuffer getData() {
-
-    // Create a new byte buffer that can hold a long object
-    ByteBuffer data = ByteBuffer.allocate(Constants.SIZEOF_LONG);
-
-    // Store the date as a long value
-    data.putLong(yearMonth.getTimeInMillis());
-
-    // Prepare the buffer for reading
-    data.flip();
-
-    return data;
+  protected String getFormatString() {
+    return "yyyy-MM";
   }
-
-  /**
-   * Create a new comparator for comparison operations.
-   *
-   * @return The comparator to be used for comparisons
-   */
-  public SPComparator getSPComparator() {
-
-    return SPGYearMonthComparator.getInstance();
-  }
-
-  /**
-   * Convert the gYearMonth representation to a lexical string as defined by XSD
-   * datatypes.
-   *
-   * @return The lexical form of the gYearMonth object
-   */
-  public String getLexicalForm() {
-
-    // Create the default format string
-    String formatString = "yyyy-MM";
-
-    if (hasTimeZone) {
-
-      formatString += "'Z'";
-    }
-
-    // Create a formatter to parse the date
-    SimpleDateFormat formatter = new SimpleDateFormat(formatString);
-
-    // Apply the formatting
-    return formatter.format(yearMonth.getTime());
-  }
-
-  /**
-   * Compares this gYearMonth representation to another object to see if they are
-   * the same values.  First the typing is checked and then the value.
-   *
-   * @param object The object we are comparing against
-   *
-   * @return Whether the gYearMonth value is greater than (> 0), less than (< 0), or
-   *         equal to (0) this value
-   */
-  public int compareTo(SPObject object) {
-
-    // Compare types.
-    int comparison = super.compareTo(object);
-
-    // If we have not got matching types return the value
-    if (comparison != 0) return comparison;
-
-    // Compare the dates lexiocally
-    return getLexicalForm().compareTo(((SPGYearMonthImpl) object).getLexicalForm());
-  }
-
-  /**
-   * Calculate the hash code for the gYearMonth object
-   *
-   * @return The hash code for the object
-   */
-  public int hashCode() {
-
-    return yearMonth.hashCode();
-  }
-
-  /**
-   * Determines whether the object is equal to the one passed in, in both type
-   * and value.  This is different to the compareTo(Object) method in the
-   * respect that it does a direct comparison, not a ranking comparison.
-   *
-   * @param object The object to compare this one to
-   *
-   * @return Whether the object is the same as this one
-   */
-  public boolean equals(Object object) {
-
-    // Check for null.
-    if (object == null) {
-
-      return false;
-    }
-
-    if (object.getClass().isInstance(this)) {
-
-      // If the object is also a gYearMonth object then compare the date
-      return ((SPGYearMonthImpl) object).getLexicalForm().equals(getLexicalForm());
-    } else {
-
-      // The object is of a different type and not equal
-      return false;
-    }
-  }
-
-  /**
-   * Implementation of an SPComparator which compares the binary representations
-   * of a GYearMonth object.
-   */
-  public static class SPGYearMonthComparator implements SPComparator {
-
-    /** Singleton instance of the comparator */
-    private static final SPGYearMonthComparator INSTANCE = new SPGYearMonthComparator();
-
-    /**
-     * Retrieves the singleton instance of this comparator.
-     *
-     * @return The comparator singleton instance
-     */
-    public static SPGYearMonthComparator getInstance() {
-
-      return INSTANCE;
-    }
-
-    /**
-     * Gives the comparator an opportunity to return an ordering where only the
-     * prefix of the binary representation of one or both SPObjects is available.
-     * If the comparator does not support this method or if an ordering can not
-     * be determined from the available data then zero (0) should be returned.
-     *
-     * @param d1 The first gYearMonth's byte buffer
-     * @param d2 The second gYearMonth's byte buffer
-     * @param d2Size The number of bytes to compare
-     *
-     * @return Whether the first prefix is greater than (> 0), less than (< 0),
-     *         or equal to (0) the other
-     */
-    public int comparePrefix(ByteBuffer d1, ByteBuffer d2, int d2Size) {
-      return 0;
-    }
-
-    /**
-     * Compares the content of a byte buffer to the other and determines whether
-     * they are equal or not.
-     *
-     * @param d1 The first byte buffer
-     * @param d2 The second byte buffer
-     * @return Whether the first buffer's content is greater than (> 0), less
-     *         than (< 0), or equal to (0) the other
-     */
-    public int compare(ByteBuffer d1, int st1, ByteBuffer d2, int st2) {
-      return AbstractSPObject.compare(d1.getLong(), d2.getLong());
-    }
-
-  }
+  
 }

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthUnitTest.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthUnitTest.java	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearMonthUnitTest.java	2008-09-23 04:36:54 UTC (rev 1267)
@@ -28,6 +28,7 @@
 package org.mulgara.store.stringpool.xa;
 
 import java.util.Date;
+import java.util.TimeZone;
 import java.text.SimpleDateFormat;
 import java.net.URL;
 import java.net.MalformedURLException;
@@ -82,6 +83,9 @@
   /** Constant valid test date (date with timezone) */
   private static final String VALID_DATE4 = "2004-01Z";
 
+  /** Constant valid test date (date with timezone) */
+  private static final String VALID_DATE4_WEST = "2003-12";
+
   /** Invalid date 1 (non-numeric characters) */
   private static final String INVALID_DATE_1 = "2004g0-01";
 
@@ -189,11 +193,12 @@
                ("" + yearMonth).equals(VALID_DATE));
 
     // Byte buffer to hold our date information
-    ByteBuffer buffer = ByteBuffer.wrap(new byte[Constants.SIZEOF_LONG]);
+    ByteBuffer buffer = ByteBuffer.wrap(new byte[SPGYearMonthImpl.getBufferSize()]);
 
     // If the previous step passed then we know the long value is what we want,
     // so store it in our buffer
     buffer.putLong(yearMonthLong);
+    buffer.put((byte)1);
 
     // Reset the buffer for reading
     buffer.flip();
@@ -206,6 +211,7 @@
       log.debug("Original yearMonth long vs. stored long: " + yearMonthLong +
                 " vs. " +
                 buffer.getLong());
+      buffer.get();
 
       // Reset the buffer
       buffer.flip();
@@ -269,27 +275,10 @@
         GYEARMONTH_URI, VALID_DATE3);
 
     // Test that the lexical form of the date is correct
-    assertTrue("GYearMonth lexical form was not " + VALID_DATE4 +
+    assertTrue("GYearMonth lexical form was not " + VALID_DATE3 +
                " as expected. was:" + gYearMonth.getLexicalForm(),
-               gYearMonth.getLexicalForm().equals(VALID_DATE4));
+               gYearMonth.getLexicalForm().equals(VALID_DATE3));
 
-    // Retrieve the byte data of the gYearMonth object
-    yearMonthBytes = gYearMonth.getData();
-
-    // Retrieve the long value from the buffer
-    yearMonthLong = yearMonthBytes.getLong();
-
-    // Create a date object from the yearMonth's long
-    yearMonthDate = new Date(yearMonthLong);
-
-    // Format the resulting yearMonth
-    yearMonth = format.format(yearMonthDate);
-
-    // Test the correct value is stored
-    assertTrue("GYearMonth byte buffer value was not " + VALID_DATE +
-               " as expected, was: " + yearMonth,
-               ("" + yearMonth).equals(VALID_DATE));
-
     // Create a gYearMonth object by lexical string (testing 'Z' acceptance)
     gYearMonth = (SPGYearMonthImpl) factory.newSPTypedLiteral(XSD.
         GYEARMONTH_URI, VALID_DATE4);
@@ -312,10 +301,13 @@
     // Format the resulting yearMonth
     yearMonth = format.format(yearMonthDate);
 
+    boolean westOfGMT = TimeZone.getDefault().getRawOffset() < 0;
+
     // Test the correct value is stored
     assertTrue("GYearMonth byte buffer value was not " + VALID_DATE +
                " as expected, was: " + yearMonth,
-               ("" + yearMonth).equals(VALID_DATE));
+               !westOfGMT ? ("" + yearMonth).equals(VALID_DATE)
+                   : ("" + yearMonth).equals(VALID_DATE4_WEST));
   }
 
   /**

Modified: trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearUnitTest.java
===================================================================
--- trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearUnitTest.java	2008-09-23 04:32:14 UTC (rev 1266)
+++ trunk/src/jar/store-stringpool/java/org/mulgara/store/stringpool/xa/SPGYearUnitTest.java	2008-09-23 04:36:54 UTC (rev 1267)
@@ -28,6 +28,7 @@
 package org.mulgara.store.stringpool.xa;
 
 import java.util.Date;
+import java.util.TimeZone;
 import java.text.SimpleDateFormat;
 import java.net.URL;
 import java.net.MalformedURLException;
@@ -73,6 +74,9 @@
   /** Constant valid test date */
   private static final String VALID_DATE = "2004";
 
+  /** Constant valid test date (relative value for VALID_DATE3) */
+  private static final String VALID_DATE_WEST = "2003";
+
   /** Constant valid test date (date outside of 0001 - 9999) */
   private static final String VALID_DATE2 = "200400";
 
@@ -148,6 +152,8 @@
    */
   public void testValid() {
 
+    boolean westOfGMT = TimeZone.getDefault().getRawOffset() < 0;
+
     // Create a new factory
     SPGYearFactory factory = new SPGYearFactory();
 
@@ -172,17 +178,18 @@
     // Format the resulting year
     String year = format.format(yearDate);
 
-    // Test the correct value is stored
+    // Test the correct value is stored - relative year, so will always be 2004
     assertTrue("GYear byte buffer value was not " + VALID_DATE +
                " as expected, was: " + year,
                ("" + year).equals(VALID_DATE));
 
     // Byte buffer to hold our date information
-    ByteBuffer buffer = ByteBuffer.wrap(new byte[Constants.SIZEOF_LONG]);
+    ByteBuffer buffer = ByteBuffer.wrap(new byte[SPGYearImpl.getBufferSize()]);
 
     // If the previous step passed then we know the long value is what we want,
     // so store it in our buffer
     buffer.putLong(yearLong);
+    buffer.put((byte)1);
 
     // Reset the buffer for reading
     buffer.flip();
@@ -194,6 +201,7 @@
 
       log.debug("Original year long vs. stored long: " + yearLong + " vs. " +
                 buffer.getLong());
+      buffer.get();
 
       // Reset the buffer
       buffer.flip();
@@ -254,9 +262,9 @@
     gYear = (SPGYearImpl) factory.newSPTypedLiteral(XSD.GYEAR_URI, VALID_DATE3);
 
     // Test that the lexical form of the date is correct
-    assertTrue("GYear lexical form was not " + VALID_DATE4 +
+    assertTrue("GYear lexical form was not " + VALID_DATE3 +
                " as expected. was:" + gYear.getLexicalForm(),
-               gYear.getLexicalForm().equals(VALID_DATE4));
+               gYear.getLexicalForm().equals(VALID_DATE3));
 
     // Retrieve the byte data of the gYear object
     yearBytes = gYear.getData();
@@ -273,7 +281,8 @@
     // Test the correct value is stored
     assertTrue("GYear byte buffer value was not " + VALID_DATE +
                " as expected, was: " + year,
-               ("" + year).equals(VALID_DATE));
+               !westOfGMT ? ("" + year).equals(VALID_DATE)
+               : ("" + year).equals(VALID_DATE_WEST));
 
     // Create a gYear object by lexical string (testing 'Z' acceptance)
     gYear = (SPGYearImpl) factory.newSPTypedLiteral(XSD.GYEAR_URI, VALID_DATE4);
@@ -299,7 +308,8 @@
     // Test the correct value is stored
     assertTrue("GYear byte buffer value was not " + VALID_DATE +
                " as expected, was: " + year,
-               ("" + year).equals(VALID_DATE));
+               !westOfGMT ? ("" + year).equals(VALID_DATE)
+                   : ("" + year).equals(VALID_DATE_WEST));
   }
 
   /**




More information about the Mulgara-svn mailing list