You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2012/05/05 22:36:25 UTC

svn commit: r1334490 - in /incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/projects/nodevalue: Dispatch.java NV2.java TestDateTimeOps.java

Author: andy
Date: Sat May  5 20:36:25 2012
New Revision: 1334490

URL: http://svn.apache.org/viewvc?rev=1334490&view=rev
Log:
Code for date/time arthimetic.

Added:
    incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/projects/nodevalue/TestDateTimeOps.java
Removed:
    incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/projects/nodevalue/Dispatch.java
Modified:
    incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/projects/nodevalue/NV2.java

Modified: incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/projects/nodevalue/NV2.java
URL: http://svn.apache.org/viewvc/incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/projects/nodevalue/NV2.java?rev=1334490&r1=1334489&r2=1334490&view=diff
==============================================================================
--- incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/projects/nodevalue/NV2.java (original)
+++ incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/projects/nodevalue/NV2.java Sat May  5 20:36:25 2012
@@ -22,6 +22,7 @@ import static com.hp.hpl.jena.sparql.exp
 import static com.hp.hpl.jena.sparql.expr.ValueSpaceClassification.VSPACE_NUM ;
 import static com.hp.hpl.jena.sparql.expr.ValueSpaceClassification.VSPACE_STRING ;
 import static javax.xml.datatype.DatatypeConstants.DAYS ;
+import static javax.xml.datatype.DatatypeConstants.FIELD_UNDEFINED ;
 import static javax.xml.datatype.DatatypeConstants.HOURS ;
 import static javax.xml.datatype.DatatypeConstants.MINUTES ;
 import static javax.xml.datatype.DatatypeConstants.MONTHS ;
@@ -31,12 +32,11 @@ import static javax.xml.datatype.Datatyp
 import java.util.GregorianCalendar ;
 
 import javax.xml.datatype.DatatypeConfigurationException ;
-import javax.xml.datatype.DatatypeConstants ;
 import javax.xml.datatype.DatatypeFactory ;
 import javax.xml.datatype.Duration ;
 import javax.xml.datatype.XMLGregorianCalendar ;
-import javax.xml.namespace.QName ;
 
+import com.hp.hpl.jena.query.ARQ ;
 import com.hp.hpl.jena.sparql.ARQInternalErrorException ;
 import com.hp.hpl.jena.sparql.expr.ExprEvalTypeException ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
@@ -53,44 +53,52 @@ public class NV2
     //    .getYear etc all blow up except if overridden.
     //XMLGregorianCalendar.getXYZ return MININT for undef.
     
+    /* Operations
+     * add, subtract (duration, duration)
+     * 
+(xsd:duration, xsd:duration) -> xsd:duration
+        10.6.1 op:add-yearMonthDurations
+        10.6.2 op:subtract-yearMonthDurations
+(xsd:duration, xsd:duration) -> xsd:duration
+        10.6.6 op:add-dayTimeDurations
+        10.6.7 op:subtract-dayTimeDurations
+** Java has general duration subtract 
+
+    * Subtract two date/times
+
+(xsd:dateTime, xsd:dateTime) -> xsd:duration
+        10.8.1 op:subtract-dateTimes -> xsd:dayTimeDuration
+(xsd:date, xsd:date) -> xsd:duration
+        10.8.2 op:subtract-dates
+(xsd:time, xsd:time) -> xsd:duration
+        10.8.3 op:subtract-times
+
+    * Date/time and duration
+** Java has general duration subtract (error needed?)
+
+(xsd:dateTime, xsd:duration) -> xsd:dateTime
+        10.8.4 op:add-yearMonthDuration-to-dateTime
+        10.8.5 op:add-dayTimeDuration-to-dateTime
+        10.8.6 op:subtract-yearMonthDuration-from-dateTime
+        10.8.7 op:subtract-dayTimeDuration-from-dateTime
+
+(xsd:date, xsd:duration) -> xsd:date
+        10.8.8 op:add-yearMonthDuration-to-date
+        10.8.9 op:add-dayTimeDuration-to-date
+        10.8.10 op:subtract-yearMonthDuration-from-date
+        10.8.11 op:subtract-dayTimeDuration-from-date
+
+(xsd:time, xsd:duration) -> xsd:time
+        10.8.12 op:add-dayTimeDuration-to-time
+        10.8.13 op:subtract-dayTimeDuration-from-time      */
+    
     /*
-     *   NodeValueDate.java
-     *   NodeValueDateTime.java
-     *   NodeValueGDay.java
-     *   NodeValueGMonth.java
-     *   NodeValueGMonthDay.java
-     *   NodeValueGYear.java
-     *   NodeValueGYearMonth.java
-     *   NodeValueTime.java
-
 fn:dateTime($arg1 as xs:date?, $arg2 as xs:time?) as xs:dateTime?
 
 http://www.w3.org/TR/xmlschema-2/#dateTime-order
 
 Properties of Date/time Seven-property Models
 http://www.w3.org/TR/xmlschema11-2/#dt-dt-7PropMod
-
-    NodeFunctions.java
-    NodeValueBoolean.java
-*   NodeValueDate.java
-*   NodeValueDateTime.java
-    NodeValueDecimal.java
-    NodeValueDouble.java
-    NodeValueDuration.java
-    NodeValueFloat.java
-*   NodeValueGDay.java
-*   NodeValueGMonth.java
-*   NodeValueGMonthDay.java
-*   NodeValueGYear.java
-*   NodeValueGYearMonth.java
-    NodeValueInteger.java
-    NodeValueNode.java
-    NodeValueString.java
-*   NodeValueTime.java
-    NodeValueVisitor.java
-    NumericType.java
-    XSDFuncOp.java
-
      */
     
     private static DatatypeFactory datatypefactory = null ;
@@ -103,139 +111,184 @@ http://www.w3.org/TR/xmlschema11-2/#dt-d
     
     public static void main(String... argv)
     {
-        NodeValue nv = NodeValue.makeDate("2012-04-29") ;
-        //System.out.println(nv.getDateTime().getHours()) ;
-        
-        //XSDFuncOp.add(nv, nv)
+//        execAdd("'2012-05-05T12:45:56.8'^^xsd:dateTime", "'P11DT0.788S'^^xsd:duration") ;
+//        execAdd("123", "45") ;
+//        execSub("'2012-05-05T12:45:56.8'^^xsd:dateTime", "'P11DT0.788S'^^xsd:duration") ;
+//        execAdd("'2012-05-05T12:45:56.8'^^xsd:dateTime", "'P11DT0.788S'^^xsd:duration") ;
+//        
+//        execSub("'2012-05-05T12:45:56.8'^^xsd:dateTime", "'2011-05-05T12:45:56.6'^^xsd:dateTime") ;
+        execSub("'2012'^^xsd:gYear", "'2012Z'^^xsd:gYear") ;
         
-        Duration dur = datatypefactory.newDuration("P10Y10MT2H") ;
-        XMLGregorianCalendar cal = datatypefactory.newXMLGregorianCalendar("2012-04-28T21:06:00Z") ;
-        
-        XMLGregorianCalendar cal3 = datatypefactory.newXMLGregorianCalendar("2012-04-28") ;
-        System.out.println(DatatypeConstants.FIELD_UNDEFINED) ;
-        System.out.println("min = "+cal3.getMinute()) ;
-        
-        
-        XMLGregorianCalendar cal2 = datatypefactory.newXMLGregorianCalendar("2012-04-29") ;
+        System.exit(0) ;
 
-        NodeValue nv1 = NodeValue.parse("'2012-04-28T21:06:00Z'^^xsd:dateTime") ;
-        NodeValue nv2 = NodeValue.makeDuration("P10Y10MT2H") ;
-        
-        System.out.println(addNV(nv1, nv2)) ;
-        System.out.println(addNV(nv2, nv1)) ;
-        
-        NodeValue nv3 = NodeValue.makeDuration("P1Y1MT2H") ;
-        System.out.println(NodeValue.compare(nv2, nv3)) ;
     }
     
-    static NodeValue addNV(NodeValue nv1, NodeValue nv2)
+    static void execAdd(String s1, String s2)
+    {
+        try {
+            NodeValue nv1 = NodeValue.parse(s1) ;
+            NodeValue nv2 = NodeValue.parse(s2) ;
+            System.out.printf("+(%s, %s)\n", nv1, nv2) ;
+            NodeValue nv3 = addNV(nv1, nv2) ;
+            System.out.printf("  %s\n", nv3) ;
+        } catch (Exception ex)
+        {
+            System.out.flush() ;
+            ex.printStackTrace(System.err) ;
+        }
+    }
+    
+    static void execSub(String s1, String s2)
+    {
+        try {
+            NodeValue nv1 = NodeValue.parse(s1) ;
+            NodeValue nv2 = NodeValue.parse(s2) ;
+            System.out.printf("- (%s, %s)\n", nv1, nv2) ;
+            NodeValue nv3 = subNV(nv1, nv2) ;
+            System.out.printf("   %s\n", nv3) ;
+        } catch (Exception ex)
+        {
+            System.out.flush() ;
+            ex.printStackTrace(System.err) ;
+        }
+    }
+    
+    // NodeFunctions
+    public static NodeValue addNV(NodeValue nv1, NodeValue nv2)
     {
         ValueSpaceClassification vs1 = nv1.getValueSpace() ;
         ValueSpaceClassification vs2 = nv2.getValueSpace() ;
         
         if ( vs1.equals(VSPACE_NUM) && vs2.equals(VSPACE_NUM) )
-            return XSDFuncOp.add(nv1, nv2) ;
+            return XSDFuncOp.numAdd(nv1, nv2) ;
+        if ( ARQ.isStrictMode() )
+            throw new ExprEvalTypeException("Operator '+' requires two numbers: got: "+nv1+" and "+nv2) ;
+        
         if ( vs1.equals(VSPACE_STRING) && vs2.equals(VSPACE_STRING) )
             return NodeValue.makeString(nv1.asString()+nv2.asString()) ;
+        if ( vs1.equals(VSPACE_DURATION) && vs2.equals(VSPACE_DURATION) )
+        {
+            Duration d3 = nv1.getDuration().add(nv2.getDuration()) ;
+            return NodeValue.makeDuration(d3) ;
+        }
         
+        // Loose style. Add any duration to any date or time value.
         if ( isDT(vs1) && vs2.equals(VSPACE_DURATION) )
         {
-            // Temp fakery.
-            XMLGregorianCalendar cal = datatypefactory.newXMLGregorianCalendar((GregorianCalendar)nv1.getDateTime().asCalendar()) ;
-            XMLGregorianCalendar result = add(cal, nv2.getDuration()) ;
-            // Unfakery.
-            NodeValue r = NodeValue.makeDateTime(result.toGregorianCalendar()) ;
+            XMLGregorianCalendar cal = nv1.getDateTime() ;
+            XMLGregorianCalendar result = xsd_add(cal, nv2.getDuration()) ;
+            NodeValue r = NodeValue.makeDateTime(result) ;
             return r ;
         }
         
         if ( isDT(vs2) && vs1.equals(VSPACE_DURATION) )
         {
-            // Temp fakery.
-            XMLGregorianCalendar cal = datatypefactory.newXMLGregorianCalendar((GregorianCalendar)nv2.getDateTime().asCalendar()) ;
-            XMLGregorianCalendar result = add(cal, nv1.getDuration()) ;
-            // Unfakery.
-            NodeValue r = NodeValue.makeDateTime(result.toGregorianCalendar()) ;
+            XMLGregorianCalendar cal = nv2.getDateTime() ;
+            XMLGregorianCalendar result = xsd_add(cal, nv1.getDuration()) ;
+            NodeValue r = NodeValue.makeDateTime(result) ;
             return r ;
         }
-        
         throw new ExprEvalTypeException("Operator '+' : Undefined addition: "+nv1+" and "+nv2) ; 
     }
 
-    private static XMLGregorianCalendar add(XMLGregorianCalendar cal, Duration duration)
+    // NodeFunctions
+    public static NodeValue subNV(NodeValue nv1, NodeValue nv2)
     {
+        ValueSpaceClassification vs1 = nv1.getValueSpace() ;
+        ValueSpaceClassification vs2 = nv2.getValueSpace() ;
+        
+        if ( vs1.equals(VSPACE_NUM) && vs2.equals(VSPACE_NUM) )
+            return XSDFuncOp.numSubtract(nv1, nv2) ;
+        if ( ARQ.isStrictMode() )
+            throw new ExprEvalTypeException("Operator '-' requires two numbers: got: "+nv1+" and "+nv2) ;
+        
+        if ( vs1.equals(VSPACE_DURATION) && vs2.equals(VSPACE_DURATION) )
+        {
+            Duration d3 = nv1.getDuration().subtract(nv2.getDuration()) ;
+            return NodeValue.makeDuration(d3) ;
+        }
+        
+        if ( isDT(vs1) && isDT(vs2) )
+        {
+            XMLGregorianCalendar cal1 = nv1.getDateTime() ;
+            XMLGregorianCalendar cal2 = nv2.getDateTime() ;
+            boolean isDef1 = ( cal1.getTimezone() == FIELD_UNDEFINED ) ; 
+            boolean isDef2 = ( cal2.getTimezone() == FIELD_UNDEFINED ) ;
+            if ( ( isDef1 && !isDef2 ) || ( !isDef1 && isDef2 ) )
+                throw new ExprEvalTypeException("Operator '-': can't substract timezone/non-timezone values") ;
+            // Inspect duration and force to better type? xsd:dayTimeDuration
+            return NodeValue.makeDuration(xsd_substract(cal1, cal2));
+        }
+        
+        // Loose style. Subtract any duration to any date or time value.
+        if ( isDT(vs1) && vs2.equals(VSPACE_DURATION) )
+        {
+            XMLGregorianCalendar cal = nv1.getDateTime() ;
+            // add-negation
+            XMLGregorianCalendar result = xsd_subtract(cal, nv2.getDuration()) ;
+            NodeValue r = NodeValue.makeDateTime(result) ;
+            return r ;
+        }
+        
+        throw new ExprEvalTypeException("Operator '-' : Undefined subtraction: "+nv1+" and "+nv2) ; 
+    }
+
+    // XSDFuncOps
+    public static XMLGregorianCalendar xsd_add(XMLGregorianCalendar cal, Duration duration)
+    {
+        //if ( ! isYearMonth(duration) && ! isDayTime(duration) )
+
         XMLGregorianCalendar result = (XMLGregorianCalendar)cal.clone() ;
         result.add(duration) ;
         return result ;
     }
     
-    static boolean isDT(ValueSpaceClassification vs)
+    // XSDFuncOps
+    public static XMLGregorianCalendar xsd_subtract(XMLGregorianCalendar cal, Duration duration)
+    {
+        return xsd_add(cal, duration.negate()) ;
+    }
+    
+    // XSDFuncOps
+    public static Duration xsd_substract(XMLGregorianCalendar cal1, XMLGregorianCalendar cal2)
+    {
+        GregorianCalendar gcal1 = cal1.toGregorianCalendar() ;
+        GregorianCalendar gcal2 = cal2.toGregorianCalendar() ;
+        long x1 = gcal1.getTimeInMillis() ;
+        long x2 = gcal2.getTimeInMillis() ;
+        //return datatypefactory.newDurationDayTime(x1-x2) ;
+        return datatypefactory.newDuration(x1-x2) ;
+    }
+
+    // XSDFuncOps
+    private static boolean isDT(ValueSpaceClassification vs)
     {
         switch (vs)
         {
             case VSPACE_DATETIME: 
             case VSPACE_DATE:
             case VSPACE_TIME:
-            //case VSPACE_DURATION:
             case VSPACE_G_YEAR:
-            case VSPACE_G_YEARMONTH: case VSPACE_G_MONTHDAY:
-            case VSPACE_G_MONTH: case VSPACE_G_DAY:
+            case VSPACE_G_YEARMONTH: 
+            case VSPACE_G_MONTHDAY:
+            case VSPACE_G_MONTH: 
+            case VSPACE_G_DAY:
                 return true ;
             default:
                 return false ;
         }
-        
-    }
-    
-    
-    static XMLGregorianCalendar parsecal(String lex)
-    {
-        XMLGregorianCalendar cal = datatypefactory.newXMLGregorianCalendar(lex) ;
-        QName qname = cal.getXMLSchemaType() ;
-        String uri = qname.getNamespaceURI()+"#"+qname.getLocalPart() ;
-        return cal ;
-    }
-    
-    static XMLGregorianCalendar add(String lex1, String lex2)
-    {
-        System.out.println(lex1+" + "+lex2) ;
-        XMLGregorianCalendar cal = datatypefactory.newXMLGregorianCalendar(lex1) ;
-        Duration dur = datatypefactory.newDuration(lex2) ;
-        cal.add(dur) ;
-        System.out.println(str(cal)) ;
-        return cal ;
-    }    
-    
-    private static String str(XMLGregorianCalendar cal)
-    {
-        QName qname = cal.getXMLSchemaType() ;
-        return "'"+cal.toXMLFormat()+"'^^xs:"+qname.getLocalPart() ;
-    }
-
-
-    static Duration parsedur(String lex)
-    {
-        Duration dur = datatypefactory.newDuration(lex) ;
-        String dt = "duration" ;
-        if ( isYearMonth(dur) )
-            dt = "yearMonth" ;
-        if ( isDayTime(dur) )
-            dt = "dayTime" ;
-//        System.out.println("'"+dur+"'^^xs:"+dt) ;
-        return dur ;
     }
-
-    // Spec is slightly unclear.
-    // It defines it as PnDTnHnMnS
-    // but also says "restrict to D/H/M/S i.e. not necessary required"
-    // The examples include the shorter forms.
     
-    static boolean isYearMonth(Duration dur)
+    // NodeFunctions
+    public static boolean isYearMonth(Duration dur)
     {
+        // Not dur.getXMLSchemaType()
         return ( dur.isSet(YEARS) || dur.isSet(MONTHS) ) &&
             ! dur.isSet(DAYS) && ! dur.isSet(HOURS) && ! dur.isSet(MINUTES) && ! dur.isSet(SECONDS) ;
     }
 
-    static boolean isDayTime(Duration dur)
+    // NodeFunctions
+    public static boolean isDayTime(Duration dur)
     {
         return !dur.isSet(YEARS) && ! dur.isSet(MONTHS) &&
             ( dur.isSet(DAYS) || dur.isSet(HOURS) || dur.isSet(MINUTES) || dur.isSet(SECONDS) );

Added: incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/projects/nodevalue/TestDateTimeOps.java
URL: http://svn.apache.org/viewvc/incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/projects/nodevalue/TestDateTimeOps.java?rev=1334490&view=auto
==============================================================================
--- incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/projects/nodevalue/TestDateTimeOps.java (added)
+++ incubator/jena/Scratch/AFS/Dev/trunk/src/main/java/projects/nodevalue/TestDateTimeOps.java Sat May  5 20:36:25 2012
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package projects.nodevalue;
+
+import com.hp.hpl.jena.sparql.expr.NodeValue ;
+
+import org.junit.Test ;
+import org.openjena.atlas.junit.BaseTest ;
+
+public class TestDateTimeOps extends BaseTest
+{
+    @Test public void nv_add_1() { testAdd("12", "13", "25" ) ; }
+
+    
+    
+
+    @Test public void nv_sub_1() { testSub("12", "13", "-1" ) ; }
+
+    
+    static void testAdd(String s1, String s2, String s3)
+    {
+        NodeValue nv1 = NodeValue.parse(s1) ;
+        NodeValue nv2 = NodeValue.parse(s2) ;
+        NodeValue nv3 = NodeValue.parse(s3) ;
+        NodeValue nv = NV2.addNV(nv1, nv2) ;
+        assertEquals(nv3, nv) ;
+    }
+    
+    static void testSub(String s1, String s2, String s3)
+    {
+        NodeValue nv1 = NodeValue.parse(s1) ;
+        NodeValue nv2 = NodeValue.parse(s2) ;
+        NodeValue nv3 = NodeValue.parse(s3) ;
+        NodeValue nv = NV2.subNV(nv1, nv2) ;
+        assertEquals(nv3, nv) ;
+        
+    }
+
+}
+