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/04/04 13:09:51 UTC

svn commit: r1309329 - in /incubator/jena/Jena2/ARQ/trunk/src: main/java/com/hp/hpl/jena/sparql/function/CastXSD.java test/java/com/hp/hpl/jena/sparql/expr/TestExpressions2.java

Author: andy
Date: Wed Apr  4 11:09:51 2012
New Revision: 1309329

URL: http://svn.apache.org/viewvc?rev=1309329&view=rev
Log:
JENA-231 : Fix: NumberFormatException when casting to xsd:int in ARQ

Modified:
    incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/function/CastXSD.java
    incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/expr/TestExpressions2.java

Modified: incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/function/CastXSD.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/function/CastXSD.java?rev=1309329&r1=1309328&r2=1309329&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/function/CastXSD.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/main/java/com/hp/hpl/jena/sparql/function/CastXSD.java Wed Apr  4 11:09:51 2012
@@ -19,13 +19,16 @@
 package com.hp.hpl.jena.sparql.function;
 
 import com.hp.hpl.jena.datatypes.xsd.XSDDatatype ;
+import com.hp.hpl.jena.datatypes.xsd.impl.XSDAbstractDateTimeType ;
+import com.hp.hpl.jena.datatypes.xsd.impl.XSDBaseNumericType ;
 import com.hp.hpl.jena.graph.Node ;
 import com.hp.hpl.jena.sparql.expr.ExprEvalException ;
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
 
-/** General casting : lexcial form must be right. 
+/** General casting of XSD datatypes. 
  * @see CastXSD_DateTime 
  * @see CastXSD_Numeric 
+ * @see CastXSD_Boolean 
  */
 public class CastXSD implements FunctionFactory
 {
@@ -87,13 +90,46 @@ public class CastXSD implements Function
             return r ;
         }
 
+        /*
+         * In RDF (2004 at least), whitespace is not legal in lexcial forms of, for example, integers.
+         *    http://www.w3.org/TR/rdf-concepts/#section-Datatypes
+         * Whitespace facet processing is part of XML processing, not RDF's lexical to value mapping. 
+         */
+        static boolean whitespaceSurroundAllowed = false ; // ! ARQ.isStrictMode() ;
+        
         protected NodeValue cast(String s, NodeValue nv, XSDDatatype castType2)
         {
+            if ( whitespaceSurroundAllowed ) 
+                // Maybe more convenient, but is not strictly correct.
+                s = s.trim() ;
+            else
+            {
+                // Correct mode.  No white space allowed around values types numeric, boolean, dateTime, ... 
+                // See also "JenaParameters.enableWhitespaceCheckingOfTypedLiterals" which defaults to false (accept surrounding whitespace)
+                // This CastXSD - not need to check it is an XSD datatype.
+                // if ( castType.getURI().startsWith(XSDDatatype.XSD) &&
+
+                if ( castType instanceof XSDBaseNumericType || 
+                     castType.equals(XSDDatatype.XSDfloat) ||
+                     castType.equals(XSDDatatype.XSDdouble) ||
+                     castType.equals(XSDDatatype.XSDboolean) ||
+                     castType instanceof XSDAbstractDateTimeType )   // Includes durations, and Gregorian
+                {
+                    if ( s.startsWith(" ") || s.endsWith(" ") )
+                        throw new ExprEvalException("CastXSD: Not a valid literal form (has whitespace): '"+s+"'") ;
+                }
+            }
+
             // Plain cast.
-            if ( ! castType.isValid(s) )
-                throw new ExprEvalException("CastXSD: Not a valid literal form: "+s) ;
-            // Unfortunately, validity testing happens in NodeValue.makeNode as well.
-            return NodeValue.makeNode(s, castType) ;
+            try {
+                if ( ! castType.isValid(s) )
+                    throw new ExprEvalException("CastXSD: Not a valid literal form: '"+s+"'") ;
+                // Unfortunately, validity testing happens in NodeValue.makeNode as well.
+                // but better error messages this way.
+                return NodeValue.makeNode(s, castType) ;
+            } catch (RuntimeException ex) {
+                throw new ExprEvalException("CastXSD: Not a strictly valid literal form: '"+s+"'") ;
+            }
         }
     }
 }

Modified: incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/expr/TestExpressions2.java
URL: http://svn.apache.org/viewvc/incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/expr/TestExpressions2.java?rev=1309329&r1=1309328&r2=1309329&view=diff
==============================================================================
--- incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/expr/TestExpressions2.java (original)
+++ incubator/jena/Jena2/ARQ/trunk/src/test/java/com/hp/hpl/jena/sparql/expr/TestExpressions2.java Wed Apr  4 11:09:51 2012
@@ -37,7 +37,7 @@ public class TestExpressions2 extends As
     @Test public void gregorian_eq_02()         { eval("'1999'^^xsd:gYear != '1999'^^xsd:gYear", false) ; }
     
     @Test (expected=ExprEvalException.class)
-    public void gregorian_eq_03()               { evalErr("'1999'^^xsd:gYear = '1999Z'^^xsd:gYear") ; }
+    public void gregorian_eq_03()               { eval("'1999'^^xsd:gYear = '1999Z'^^xsd:gYear") ; }
 
     @Test  public void gregorian_eq_04()        { eval("'1999'^^xsd:gYear = '2001Z'^^xsd:gYear", false) ; }
     
@@ -54,12 +54,12 @@ public class TestExpressions2 extends As
     @Test public void gregorian_cmp_03()        { eval("'1999'^^xsd:gYear < '2000+01:00'^^xsd:gYear", true) ; }
 
     @Test (expected=ExprEvalException.class)
-    public void gregorian_cmp_04()              { evalErr("'1999'^^xsd:gYear < '1999+05:00'^^xsd:gYear") ; }
+    public void gregorian_cmp_04()              { eval("'1999'^^xsd:gYear < '1999+05:00'^^xsd:gYear") ; }
     
     public void gregorian_cast_01()             { eval("xsd:gYear('2010-03-22'^^xsd:date) = '2010'^^xsd:gYear", true ) ; }
 
     @Test (expected=ExprEvalException.class)
-    public void coalesce_01()                   { evalErr("COALESCE()") ; } 
+    public void coalesce_01()                   { eval("COALESCE()") ; } 
     @Test public void coalesce_02()             { eval("COALESCE(1) = 1", true) ; } 
     @Test public void coalesce_03()             { eval("COALESCE(?x,1) = 1", true) ; } 
     @Test public void coalesce_04()             { eval("COALESCE(9,1) = 9", true) ; } 
@@ -69,7 +69,7 @@ public class TestExpressions2 extends As
     @Test public void if_02()                   { eval("IF(1+2=4, 'yes', 'no') = 'no'", true) ; }
     @Test public void if_03()                   { eval("IF(true, 'yes', 1/0) = 'yes'", true) ; }
     @Test (expected=ExprEvalException.class)
-    public void if_04()                         { evalErr("IF(true, 1/0, 'no') = 'no'") ; }
+    public void if_04()                         { eval("IF(true, 1/0, 'no') = 'no'") ; }
     
     // NOT IN, IN
     @Test public void in_01()                   { eval("1 IN(1,2,3)", true) ; }
@@ -86,7 +86,7 @@ public class TestExpressions2 extends As
     @Test public void term_constructor_iri_01()     { eval("IRI('http://example/') = <http://example/>", true) ; }
     
     @Test (expected=ExprEvalException.class)
-    public void term_constructor_iri_02()           { evalErr("IRI(123)") ; } 
+    public void term_constructor_iri_02()           { eval("IRI(123)") ; } 
     @Test public void term_constructor_iri_03()     { eval("IRI(<http://example/>) = <http://example/>", true) ; }
     @Test public void term_constructor_iri_04()     { eval("isIRI(IRI(BNODE()))", true) ; }            // SPARQL extension
     @Test public void term_constructor_iri_05()     { eval("regex(str(IRI(BNODE())), '^_:' )", true) ; } // SPARQL extension
@@ -100,23 +100,38 @@ public class TestExpressions2 extends As
     @Test public void term_constructor_strdt_01()   { eval("STRDT('123',xsd:integer) = 123", true) ; }
     @Test public void term_constructor_strdt_02()   { eval("STRDT('123',<http://example/DT>) = '123'^^<http://example/DT>", true) ; }
     @Test (expected=ExprEvalException.class)
-    public void term_constructor_strdt_03()         { evalErr("STRDT('123','abc') = '123'") ; }
+    public void term_constructor_strdt_03()         { eval("STRDT('123','abc') = '123'") ; }
     @Test (expected=ExprEvalException.class)
-    public void term_constructor_strdt_04()         { evalErr("STRDT('123'^^xsd:integer,<http://example/DT>) = '123'^^<http://example/DT>") ; }
+    public void term_constructor_strdt_04()         { eval("STRDT('123'^^xsd:integer,<http://example/DT>) = '123'^^<http://example/DT>") ; }
     
     @Test public void term_constructor_strlang_01() { eval("STRLANG('abc', 'en') = 'abc'@en", true) ; }
     @Test (expected=ExprEvalException.class)
-    public void term_constructor_strlang_02()       { evalErr("STRLANG(<http://example/>, 'en') = 'abc'@en") ; }
+    public void term_constructor_strlang_02()       { eval("STRLANG(<http://example/>, 'en') = 'abc'@en") ; }
 
     @Test (expected=ExprEvalException.class)
-    public void term_constructor_strlang_03()       { evalErr("STRLANG('abc'@en, 'en') = 'abc'@en") ; }
+    public void term_constructor_strlang_03()       { eval("STRLANG('abc'@en, 'en') = 'abc'@en") ; }
+    
+    // XSD casts
+    
+    @Test public void xsd_cast_01()                 { eval("xsd:integer('1') = 1", true) ; }
+    @Test public void xsd_cast_02()                 { eval("xsd:boolean('1') = true", true) ; }
+    @Test public void xsd_cast_03()                 { eval("sameTerm(xsd:double('1.0e0'),1.0e0)", true) ; }
+    @Test public void xsd_cast_04()                 { eval("xsd:double('1') = 1", true) ; }
+
+    @Test (expected=ExprEvalException.class)
+    public void xsd_cast_10()                       { eval("xsd:integer(' 1')") ; }
+    @Test (expected=ExprEvalException.class)
+    public void xsd_cast_11()                       { eval("xsd:boolean(' 1')") ; }
+    @Test (expected=ExprEvalException.class)
+    public void xsd_cast_12()                       { eval("xsd:double(' 1.0e0')") ; }
+    @Test (expected=ExprEvalException.class)
+    public void xsd_cast_13()                       { eval("xsd:double(' 1.0e0')") ; }
     
     // ---- Workers
     
-    private static void evalErr(String string)
+    private static void eval(String string)
     { 
         eval(string, true) ;
-        throw new RuntimeException() ; 
     }
     
     // It's easier to write tests that simple are expected to return true/false